Use this lock to coordinate requests to cache and stats events from vzsdk. Request is a series of calls of vzCountersCacheGetParam which must be enslosed in a vzCountersCacheBegin, vzCountersCacheEnd. Signed-off-by: Nikolay Shirokovskiy <nshirokovskiy@xxxxxxxxxxxxx> --- src/vz/vz_driver.c | 236 ++++++++++++++++++++++++++++++++++++++--------------- src/vz/vz_sdk.c | 120 ++++++++++++++++----------- src/vz/vz_sdk.h | 14 +++- src/vz/vz_utils.h | 2 + 4 files changed, 256 insertions(+), 116 deletions(-) diff --git a/src/vz/vz_driver.c b/src/vz/vz_driver.c index 95739bd..1aabfd7 100644 --- a/src/vz/vz_driver.c +++ b/src/vz/vz_driver.c @@ -597,15 +597,45 @@ vzDomainLookupByName(virConnectPtr conn, const char *name) } static int +vzStatsGetCpuTotal(vzCountersCachePtr cache, + unsigned int num, + unsigned long long *total) +{ + int ret = -1; + size_t i; + + if (vzCountersCacheBegin(cache) < 0) + return -1; + + for (i = 0; i < num; ++i) { + unsigned long long cpu; + + if (prlsdkGetVcpuStats(cache, i, &cpu) < 0) { + virReportError(VIR_ERR_OPERATION_FAILED, "%s", + _("cannot read cputime for domain")); + goto cleanup; + } + total += cpu; + } + + ret = 0; + + cleanup: + vzCountersCacheEnd(cache); + + return ret; +} + +static int vzDomainGetInfo(virDomainPtr domain, virDomainInfoPtr info) { virDomainObjPtr dom; + vzDomObjPtr privdom; int ret = -1; - size_t i; unsigned int nvcpus; if (!(dom = vzDomObjFromDomainRef(domain))) - goto cleanup; + return -1; info->state = virDomainObjGetState(dom, NULL); info->memory = dom->def->mem.cur_balloon; @@ -614,26 +644,17 @@ vzDomainGetInfo(virDomainPtr domain, virDomainInfoPtr info) info->cpuTime = 0; if (!virDomainObjIsActive(dom)) { - ret = 0; - goto cleanup; + virDomainObjEndAPI(&dom); + return 0; } nvcpus = virDomainDefGetVcpus(dom->def); - for (i = 0; i < nvcpus; ++i) { - unsigned long long vtime; + virObjectUnlock(dom); + privdom = dom->privateData; + ret = vzStatsGetCpuTotal(privdom->cache, nvcpus, &info->cpuTime); + virObjectUnref(dom); - if (prlsdkGetVcpuStats(dom, i, &vtime) < 0) { - virReportError(VIR_ERR_OPERATION_FAILED, "%s", - _("cannot read cputime for domain")); - goto cleanup; - } - info->cpuTime += vtime; - } - ret = 0; - - cleanup: - virDomainObjEndAPI(&dom); return ret; } @@ -869,6 +890,33 @@ vzConnectBaselineCPU(virConnectPtr conn ATTRIBUTE_UNUSED, return cpuBaselineXML(xmlCPUs, ncpus, NULL, 0, flags); } +static int +vzStatsGetCpuInfo(vzCountersCachePtr cache, + virVcpuInfoPtr info, + int num) + +{ + int ret = -1; + size_t i; + + if (vzCountersCacheBegin(cache) < 0) + return -1; + + memset(info, 0, sizeof(*info) * num); + for (i = 0; i < num; i++) { + info[i].number = i; + info[i].state = VIR_VCPU_RUNNING; + if (prlsdkGetVcpuStats(cache, i, &info[i].cpuTime) < 0) + goto cleanup; + } + + ret = num; + + cleanup: + vzCountersCacheEnd(cache); + + return ret; +} static int vzDomainGetVcpus(virDomainPtr domain, @@ -878,11 +926,12 @@ vzDomainGetVcpus(virDomainPtr domain, int maplen) { virDomainObjPtr dom = NULL; + vzDomObjPtr privdom; size_t i; int ret = -1; if (!(dom = vzDomObjFromDomainRef(domain))) - goto cleanup; + return -1; if (!virDomainObjIsActive(dom)) { virReportError(VIR_ERR_OPERATION_INVALID, @@ -905,20 +954,19 @@ vzDomainGetVcpus(virDomainPtr domain, } if (info != NULL) { - memset(info, 0, sizeof(*info) * maxinfo); - for (i = 0; i < maxinfo; i++) { - info[i].number = i; - info[i].state = VIR_VCPU_RUNNING; - if (prlsdkGetVcpuStats(dom, i, &info[i].cpuTime) < 0) - goto cleanup; - } + virObjectUnlock(dom); + privdom = dom->privateData; + ret = vzStatsGetCpuInfo(privdom->cache, info, maxinfo); + virObjectUnref(dom); + + return ret; } ret = maxinfo; cleanup: - if (dom) - virDomainObjEndAPI(&dom); + virDomainObjEndAPI(&dom); + return ret; } @@ -1278,10 +1326,64 @@ vzDomainGetMaxMemory(virDomainPtr domain) } static int +vzStatsGetBlockStats(vzCountersCachePtr cache, + const char *disk, + char **disks, + int ndisks, + virDomainBlockStatsPtr stats) +{ + int ret = -1; + size_t i; + + if (vzCountersCacheBegin(cache) < 0) + return -1; + + if (disk) { + if (prlsdkGetBlockStats(cache, disk, stats) < 0) + goto cleanup; + } else if (disks) { + virDomainBlockStatsStruct s; + +#define PARALLELS_ZERO_STATS(VAR, TYPE, NAME) \ + stats->VAR = 0; + + PARALLELS_BLOCK_STATS_FOREACH(PARALLELS_ZERO_STATS) + +#undef PARALLELS_ZERO_STATS + + for (i = 0; i < ndisks; i++) { + if (prlsdkGetBlockStats(cache, disks[i], &s) < 0) + goto cleanup; + +#define PARALLELS_SUM_STATS(VAR, TYPE, NAME) \ + if (s.VAR != -1) \ + stats->VAR += s.VAR; + + PARALLELS_BLOCK_STATS_FOREACH(PARALLELS_SUM_STATS) + +#undef PARALLELS_SUM_STATS + } + } else { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("one of disks or disk parameters should be set")); + goto cleanup; + } + + stats->errs = -1; + ret = 0; + + cleanup: + vzCountersCacheEnd(cache); + + return ret; +} + +static int vzDomainBlockStats(virDomainPtr domain, const char *path, virDomainBlockStatsPtr stats) { virDomainObjPtr dom = NULL; + vzDomObjPtr privdom; int ret = -1; size_t i; int idx; @@ -1292,59 +1394,41 @@ vzDomainBlockStats(virDomainPtr domain, const char *path, if (!(dom = vzDomObjFromDomainRef(domain))) return -1; + privdom = dom->privateData; + if (*path) { if ((idx = virDomainDiskIndexByName(dom->def, path, false)) < 0) { virReportError(VIR_ERR_INVALID_ARG, _("invalid path: %s"), path); - goto cleanup; + goto error; } if (!(disk = prlsdkGetDiskStatName(dom->def->disks[idx]))) - goto cleanup; - - if (prlsdkGetBlockStats(dom, disk, stats) < 0) - goto cleanup; + goto error; } else { - virDomainBlockStatsStruct s; - -#define PARALLELS_ZERO_STATS(VAR, TYPE, NAME) \ - stats->VAR = 0; - - PARALLELS_BLOCK_STATS_FOREACH(PARALLELS_ZERO_STATS) - -#undef PARALLELS_ZERO_STATS - ndisks = dom->def->ndisks; if (VIR_ALLOC_N(disks, ndisks)) - goto cleanup; + goto error; for (i = 0; i < ndisks; i++) if (!(disks[i] = prlsdkGetDiskStatName(dom->def->disks[i]))) - goto cleanup; - - for (i = 0; i < ndisks; i++) { - if (prlsdkGetBlockStats(dom, disk, &s) < 0) - goto cleanup; - -#define PARALLELS_SUM_STATS(VAR, TYPE, NAME) \ - if (s.VAR != -1) \ - stats->VAR += s.VAR; - - PARALLELS_BLOCK_STATS_FOREACH(PARALLELS_SUM_STATS) - -#undef PARALLELS_SUM_STATS - } + goto error; } - stats->errs = -1; - ret = 0; + + virObjectUnlock(dom); + privdom = dom->privateData; + ret = vzStatsGetBlockStats(privdom->cache, disk, disks, ndisks, stats); + virObjectUnref(dom); cleanup: - if (dom) - virDomainObjEndAPI(&dom); VIR_FREE(disk); virStringFreeListCount(disks, ndisks); return ret; + + error: + virDomainObjEndAPI(&dom); + goto cleanup; } static int @@ -1403,13 +1487,25 @@ vzDomainInterfaceStats(virDomainPtr domain, virDomainInterfaceStatsPtr stats) { virDomainObjPtr dom = NULL; + vzDomObjPtr privdom; + vzCountersCachePtr cache; int ret; if (!(dom = vzDomObjFromDomainRef(domain))) return -1; - ret = prlsdkGetNetStats(dom, path, stats); - virDomainObjEndAPI(&dom); + virObjectUnlock(dom); + privdom = dom->privateData; + cache = privdom->cache; + + if (vzCountersCacheBegin(cache) < 0) { + virObjectUnref(dom); + return -1; + } + + ret = prlsdkGetNetStats(cache, privdom->sdkdom, path, stats); + vzCountersCacheEnd(cache); + virObjectUnref(dom); return ret; } @@ -1421,14 +1517,26 @@ vzDomainMemoryStats(virDomainPtr domain, unsigned int flags) { virDomainObjPtr dom = NULL; + vzDomObjPtr privdom; + vzCountersCachePtr cache; int ret = -1; virCheckFlags(0, -1); if (!(dom = vzDomObjFromDomainRef(domain))) return -1; - ret = prlsdkGetMemoryStats(dom, stats, nr_stats); - virDomainObjEndAPI(&dom); + virObjectUnlock(dom); + privdom = dom->privateData; + cache = privdom->cache; + + if (vzCountersCacheBegin(cache) < 0) { + virObjectUnref(dom); + return -1; + } + + ret = prlsdkGetMemoryStats(cache, stats, nr_stats); + vzCountersCacheEnd(cache); + virObjectUnref(dom); return ret; } diff --git a/src/vz/vz_sdk.c b/src/vz/vz_sdk.c index 5cef432..a5474dc 100644 --- a/src/vz/vz_sdk.c +++ b/src/vz/vz_sdk.c @@ -41,7 +41,7 @@ static int prlsdkUUIDParse(const char *uuidstr, unsigned char *uuid); static vzCountersCachePtr -vzCountersCacheNew(void); +vzCountersCacheNew(PRL_HANDLE sdkdom); static void vzCountersCacheFree(vzCountersCachePtr cache); @@ -1638,7 +1638,7 @@ prlsdkLoadDomain(vzDriverPtr driver, virDomainObjPtr dom) } if (pdom->sdkdom == PRL_INVALID_HANDLE) { - if (!(pdom->cache = vzCountersCacheNew())) + if (!(pdom->cache = vzCountersCacheNew(sdkdom))) goto error; pdom->sdkdom = sdkdom; } else { @@ -1876,47 +1876,52 @@ prlsdkHandleVmRemovedEvent(vzDriverPtr driver, #define PARALLELS_STATISTICS_DROP_COUNT 3 -static PRL_RESULT +static void prlsdkHandlePerfEvent(vzDriverPtr driver, PRL_HANDLE event, unsigned char *uuid) { - virDomainObjPtr dom = NULL; + virDomainObjPtr dom; vzDomObjPtr privdom = NULL; PRL_HANDLE job = PRL_INVALID_HANDLE; + vzCountersCachePtr cache; - dom = virDomainObjListFindByUUID(driver->domains, uuid); - if (dom == NULL) - goto cleanup; + dom = virDomainObjListFindByUUIDRef(driver->domains, uuid); + if (dom == NULL) { + PrlHandle_Free(event); + return; + } + + virObjectUnlock(dom); privdom = dom->privateData; + cache = privdom->cache; + virMutexLock(&cache->lock); /* delayed event after unsubscribe */ - if (privdom->cache->count == -1) + if (cache->count == -1) goto cleanup; - PrlHandle_Free(privdom->cache->stats); - privdom->cache->stats = PRL_INVALID_HANDLE; + PrlHandle_Free(cache->stats); + cache->stats = PRL_INVALID_HANDLE; - if (privdom->cache->count > PARALLELS_STATISTICS_DROP_COUNT) { - job = PrlVm_UnsubscribeFromPerfStats(privdom->sdkdom); + if (cache->count > PARALLELS_STATISTICS_DROP_COUNT) { + job = PrlVm_UnsubscribeFromPerfStats(cache->sdkdom); if (PRL_FAILED(waitJob(job))) goto cleanup; /* change state to unsubscribed */ - privdom->cache->count = -1; + cache->count = -1; } else { - ++privdom->cache->count; - privdom->cache->stats = event; + ++cache->count; + cache->stats = event; /* thus we get own of event handle */ event = PRL_INVALID_HANDLE; - virCondSignal(&privdom->cache->cond); + virCondSignal(&cache->cond); } cleanup: PrlHandle_Free(event); - if (dom) - virObjectUnlock(dom); - - return PRL_ERR_SUCCESS; + virMutexUnlock(&cache->lock); + virObjectUnref(dom); } static PRL_RESULT @@ -4004,14 +4009,14 @@ prlsdkDomainManagedSaveRemove(virDomainObjPtr dom) } static int -prlsdkExtractStatsParam(PRL_HANDLE sdkstats, const char *name, long long *val) +vzCountersCacheGetParam(vzCountersCachePtr cache, const char *name, long long *val) { PRL_HANDLE param = PRL_INVALID_HANDLE; PRL_RESULT pret; PRL_INT64 pval = 0; int ret = -1; - pret = PrlEvent_GetParamByName(sdkstats, name, ¶m); + pret = PrlEvent_GetParamByName(cache->stats, name, ¶m); if (pret == PRL_ERR_NO_DATA) { *val = -1; ret = 0; @@ -4033,36 +4038,37 @@ prlsdkExtractStatsParam(PRL_HANDLE sdkstats, const char *name, long long *val) #define PARALLELS_STATISTICS_TIMEOUT (60 * 1000) -static int -prlsdkGetStatsParam(virDomainObjPtr dom, const char *name, long long *val) +int +vzCountersCacheBegin(vzCountersCachePtr cache) { - vzDomObjPtr privdom = dom->privateData; PRL_HANDLE job = PRL_INVALID_HANDLE; unsigned long long now; - if (privdom->cache->stats != PRL_INVALID_HANDLE) { + virMutexLock(&cache->lock); + + if (cache->stats != PRL_INVALID_HANDLE) { /* reset count to keep subscribtion */ - privdom->cache->count = 0; - return prlsdkExtractStatsParam(privdom->cache->stats, name, val); + cache->count = 0; + return 0; } - if (privdom->cache->count == -1) { - job = PrlVm_SubscribeToPerfStats(privdom->sdkdom, NULL); + if (cache->count == -1) { + job = PrlVm_SubscribeToPerfStats(cache->sdkdom, NULL); if (PRL_FAILED(waitJob(job))) goto error; } /* change state to subscribed in case of unsubscribed or reset count so we stop unsubscribe attempts */ - privdom->cache->count = 0; + cache->count = 0; if (virTimeMillisNow(&now) < 0) { virReportSystemError(errno, "%s", _("Unable to get current time")); goto error; } - while (privdom->cache->stats == PRL_INVALID_HANDLE) { - if (virCondWaitUntil(&privdom->cache->cond, &dom->parent.lock, + while (cache->stats == PRL_INVALID_HANDLE) { + if (virCondWaitUntil(&cache->cond, &cache->lock, now + PARALLELS_STATISTICS_TIMEOUT) < 0) { if (errno == ETIMEDOUT) { virReportError(VIR_ERR_OPERATION_TIMEOUT, "%s", @@ -4076,11 +4082,20 @@ prlsdkGetStatsParam(virDomainObjPtr dom, const char *name, long long *val) } } - return prlsdkExtractStatsParam(privdom->cache->stats, name, val); + return 0; + error: + virMutexUnlock(&cache->lock); + return -1; } +void +vzCountersCacheEnd(vzCountersCachePtr cache) +{ + virMutexUnlock(&cache->lock); +} + static void vzCountersCacheFree(vzCountersCachePtr cache) { @@ -4089,11 +4104,12 @@ vzCountersCacheFree(vzCountersCachePtr cache) PrlHandle_Free(cache->stats); virCondDestroy(&cache->cond); + virMutexDestroy(&cache->lock); VIR_FREE(cache); } static vzCountersCachePtr -vzCountersCacheNew(void) +vzCountersCacheNew(PRL_HANDLE sdkdom) { vzCountersCachePtr cache = NULL; @@ -4104,8 +4120,14 @@ vzCountersCacheNew(void) virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("cannot initialize condition")); goto error; } + if (virMutexInit(&cache->lock) < 0) { + virCondDestroy(&cache->cond); + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("cannot initialize mutex")); + goto error; + } cache->stats = PRL_INVALID_HANDLE; cache->count = -1; + cache->sdkdom = sdkdom; return cache; @@ -4114,6 +4136,7 @@ vzCountersCacheNew(void) return NULL; } + char* prlsdkGetDiskStatName(virDomainDiskDefPtr disk) { virDomainDeviceDriveAddressPtr address; @@ -4148,7 +4171,7 @@ char* prlsdkGetDiskStatName(virDomainDiskDefPtr disk) } int -prlsdkGetBlockStats(virDomainObjPtr dom, +prlsdkGetBlockStats(vzCountersCachePtr cache, const char *disk, virDomainBlockStatsPtr stats) { @@ -4158,7 +4181,7 @@ prlsdkGetBlockStats(virDomainObjPtr dom, #define PRLSDK_GET_STAT_PARAM(VAL, TYPE, NAME) \ if (virAsprintf(&name, "devices.%s.%s", disk, NAME) < 0) \ goto cleanup; \ - if (prlsdkGetStatsParam(dom, name, &stats->VAL) < 0) \ + if (vzCountersCacheGetParam(cache, name, &stats->VAL) < 0) \ goto cleanup; \ VIR_FREE(name); @@ -4176,20 +4199,19 @@ prlsdkGetBlockStats(virDomainObjPtr dom, static PRL_HANDLE -prlsdkFindNetByPath(virDomainObjPtr dom, const char *path) +prlsdkFindNetByPath(PRL_HANDLE sdkdom, const char *path) { PRL_UINT32 count = 0; - vzDomObjPtr privdom = dom->privateData; PRL_RESULT pret; size_t i; char *name = NULL; PRL_HANDLE net = PRL_INVALID_HANDLE; - pret = PrlVmCfg_GetNetAdaptersCount(privdom->sdkdom, &count); + pret = PrlVmCfg_GetNetAdaptersCount(sdkdom, &count); prlsdkCheckRetGoto(pret, error); for (i = 0; i < count; ++i) { - pret = PrlVmCfg_GetNetAdapter(privdom->sdkdom, i, &net); + pret = PrlVmCfg_GetNetAdapter(sdkdom, i, &net); prlsdkCheckRetGoto(pret, error); if (!(name = prlsdkGetStringParamVar(PrlVmDevNet_GetHostInterfaceName, @@ -4216,7 +4238,9 @@ prlsdkFindNetByPath(virDomainObjPtr dom, const char *path) } int -prlsdkGetNetStats(virDomainObjPtr dom, const char *path, +prlsdkGetNetStats(vzCountersCachePtr cache, + PRL_HANDLE sdkdom, + const char *path, virDomainInterfaceStatsPtr stats) { int ret = -1; @@ -4225,7 +4249,7 @@ prlsdkGetNetStats(virDomainObjPtr dom, const char *path, PRL_RESULT pret; PRL_HANDLE net = PRL_INVALID_HANDLE; - net = prlsdkFindNetByPath(dom, path); + net = prlsdkFindNetByPath(sdkdom, path); if (net == PRL_INVALID_HANDLE) goto cleanup; @@ -4235,7 +4259,7 @@ prlsdkGetNetStats(virDomainObjPtr dom, const char *path, #define PRLSDK_GET_NET_COUNTER(VAL, NAME) \ if (virAsprintf(&name, "net.nic%d.%s", net_index, NAME) < 0) \ goto cleanup; \ - if (prlsdkGetStatsParam(dom, name, &stats->VAL) < 0) \ + if (vzCountersCacheGetParam(cache, name, &stats->VAL) < 0) \ goto cleanup; \ VIR_FREE(name); @@ -4259,7 +4283,7 @@ prlsdkGetNetStats(virDomainObjPtr dom, const char *path, } int -prlsdkGetVcpuStats(virDomainObjPtr dom, int idx, unsigned long long *vtime) +prlsdkGetVcpuStats(vzCountersCachePtr cache, int idx, unsigned long long *vtime) { char *name = NULL; long long ptime = 0; @@ -4267,7 +4291,7 @@ prlsdkGetVcpuStats(virDomainObjPtr dom, int idx, unsigned long long *vtime) if (virAsprintf(&name, "guest.vcpu%u.time", (unsigned int)idx) < 0) goto cleanup; - if (prlsdkGetStatsParam(dom, name, &ptime) < 0) + if (vzCountersCacheGetParam(cache, name, &ptime) < 0) goto cleanup; *vtime = ptime == -1 ? 0 : ptime; ret = 0; @@ -4278,7 +4302,7 @@ prlsdkGetVcpuStats(virDomainObjPtr dom, int idx, unsigned long long *vtime) } int -prlsdkGetMemoryStats(virDomainObjPtr dom, +prlsdkGetMemoryStats(vzCountersCachePtr cache, virDomainMemoryStatPtr stats, unsigned int nr_stats) { @@ -4287,7 +4311,7 @@ prlsdkGetMemoryStats(virDomainObjPtr dom, size_t i = 0; #define PRLSDK_GET_COUNTER(NAME, VALUE) \ - if (prlsdkGetStatsParam(dom, NAME, &VALUE) < 0) \ + if (vzCountersCacheGetParam(cache, NAME, &VALUE) < 0) \ goto cleanup; \ #define PRLSDK_MEMORY_STAT_SET(TAG, VALUE) \ diff --git a/src/vz/vz_sdk.h b/src/vz/vz_sdk.h index 033a3fe..87466e7 100644 --- a/src/vz/vz_sdk.h +++ b/src/vz/vz_sdk.h @@ -68,17 +68,20 @@ int prlsdkDetachVolume(virDomainObjPtr dom, virDomainDiskDefPtr disk); char* prlsdkGetDiskStatName(virDomainDiskDefPtr disk); int -prlsdkGetBlockStats(virDomainObjPtr dom, const char *disk, virDomainBlockStatsPtr stats); +prlsdkGetBlockStats(vzCountersCachePtr cache, const char *disk, virDomainBlockStatsPtr stats); int prlsdkAttachNet(vzDriverPtr driver, virDomainObjPtr dom, virDomainNetDefPtr net); int prlsdkDetachNet(vzDriverPtr driver, virDomainObjPtr dom, virDomainNetDefPtr net); int -prlsdkGetNetStats(virDomainObjPtr dom, const char *path, virDomainInterfaceStatsPtr stats); +prlsdkGetNetStats(vzCountersCachePtr cache, + PRL_HANDLE sdkdom, + const char *path, + virDomainInterfaceStatsPtr stats); int -prlsdkGetVcpuStats(virDomainObjPtr dom, int idx, unsigned long long *time); +prlsdkGetVcpuStats(vzCountersCachePtr cache, int idx, unsigned long long *time); int -prlsdkGetMemoryStats(virDomainObjPtr dom, virDomainMemoryStatPtr stats, unsigned int nr_stats); +prlsdkGetMemoryStats(vzCountersCachePtr cache, virDomainMemoryStatPtr stats, unsigned int nr_stats); void prlsdkDomObjFreePrivate(void *p); /* memsize is in MiB */ @@ -94,3 +97,6 @@ prlsdkMigrate(virDomainObjPtr dom, const char unsigned *session_uuid, const char *dname, unsigned int flags); + +int vzCountersCacheBegin(vzCountersCachePtr cache); +void vzCountersCacheEnd(vzCountersCachePtr cache); diff --git a/src/vz/vz_utils.h b/src/vz/vz_utils.h index 43d46ca..a3ff152 100644 --- a/src/vz/vz_utils.h +++ b/src/vz/vz_utils.h @@ -95,7 +95,9 @@ typedef struct _vzConn *vzConnPtr; struct _vzCountersCache { + PRL_HANDLE sdkdom; /* unreferenced */ PRL_HANDLE stats; + virMutex lock; virCond cond; /* = -1 - unsubscribed > -1 - subscribed */ -- 1.8.3.1 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list