diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index 3c2cd926f171815dd82768e20292c9dddc654068..3739b7d8d1207a924dfd00f2d98640c583df3ec9 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -207,6 +207,11 @@ struct _qemuCaps { char **machineAliases; }; +struct _qemuCapsCache { + virMutex lock; + virHashTablePtr binaries; +}; + static virClassPtr qemuCapsClass; static void qemuCapsDispose(void *obj); @@ -2055,3 +2060,98 @@ bool qemuCapsIsValid(qemuCapsPtr caps) return sb.st_mtime == caps->mtime; } + + +static void +qemuCapsHashDataFree(void *payload, const void *key ATTRIBUTE_UNUSED) +{ + virObjectUnref(payload); +} + + +qemuCapsCachePtr +qemuCapsCacheNew(void) +{ + qemuCapsCachePtr cache; + + if (VIR_ALLOC(cache) < 0) { + virReportOOMError(); + return NULL; + } + + if (virMutexInit(&cache->lock) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Unable to initialize mutex")); + VIR_FREE(cache); + return NULL; + } + + if (!(cache->binaries = virHashCreate(10, qemuCapsHashDataFree))) + goto error; + + return cache; + +error: + qemuCapsCacheFree(cache); + return NULL; +} + + +qemuCapsPtr +qemuCapsCacheLookup(qemuCapsCachePtr cache, const char *binary) +{ + qemuCapsPtr ret = NULL; + virMutexLock(&cache->lock); + ret = virHashLookup(cache->binaries, binary); + if (ret && + !qemuCapsIsValid(ret)) { + VIR_DEBUG("Cached capabilities %p no longer valid for %s", + ret, binary); + virHashRemoveEntry(cache->binaries, binary); + ret = NULL; + } + if (!ret) { + VIR_DEBUG("Creating capabilities for %s", + binary); + ret = qemuCapsNewForBinary(binary); + if (ret) { + VIR_DEBUG("Caching capabilities %p for %s", + ret, binary); + if (virHashAddEntry(cache->binaries, binary, ret) < 0) { + virObjectUnref(ret); + ret = NULL; + } + } + } + VIR_DEBUG("Returning caps %p for %s", ret, binary); + virObjectRef(ret); + virMutexUnlock(&cache->lock); + return ret; +} + + +qemuCapsPtr +qemuCapsCacheLookupCopy(qemuCapsCachePtr cache, const char *binary) +{ + qemuCapsPtr caps = qemuCapsCacheLookup(cache, binary); + qemuCapsPtr ret; + + if (!caps) + return NULL; + + ret = qemuCapsNewCopy(caps); + virObjectUnref(caps); + return ret; +} + + +void +qemuCapsCacheFree(qemuCapsCachePtr cache) +{ + if (!cache) + return; + + virHashFree(cache->binaries); + virMutexDestroy(&cache->lock); + VIR_FREE(cache); +} diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h index 9e4543aede99be9fa49b60bf8e9f85d2676c3c91..3afbbd63744ffb9d4ecb38196b68766a277e8929 100644 --- a/src/qemu/qemu_capabilities.h +++ b/src/qemu/qemu_capabilities.h @@ -155,6 +155,9 @@ enum qemuCapsFlags { typedef struct _qemuCaps qemuCaps; typedef qemuCaps *qemuCapsPtr; +typedef struct _qemuCapsCache qemuCapsCache; +typedef qemuCapsCache *qemuCapsCachePtr; + qemuCapsPtr qemuCapsNew(void); qemuCapsPtr qemuCapsNewCopy(qemuCapsPtr caps); qemuCapsPtr qemuCapsNewForBinary(const char *binary); @@ -184,6 +187,12 @@ const char *qemuCapsGetCanonicalMachine(qemuCapsPtr caps, bool qemuCapsIsValid(qemuCapsPtr caps); + +qemuCapsCachePtr qemuCapsCacheNew(void); +qemuCapsPtr qemuCapsCacheLookup(qemuCapsCachePtr cache, const char *binary); +qemuCapsPtr qemuCapsCacheLookupCopy(qemuCapsCachePtr cache, const char *binary); +void qemuCapsCacheFree(qemuCapsCachePtr cache); + virCapsPtr qemuCapsInit(virCapsPtr old_caps); int qemuCapsProbeMachineTypes(const char *binary,