From: "Daniel P. Berrange" <berrange@xxxxxxxxxx> Introduce a qemuCapsCachePtr object to provide a global cache of capabilities for QEMU binaries. The cache auto-populates on first request for capabilities about a binary, and will auto-refresh if the binary has changed since a previous cache was populated Signed-off-by: Daniel P. Berrange <berrange@xxxxxxxxxx> --- src/qemu/qemu_capabilities.c | 99 ++++++++++++++++++++++++++++++++++++++++++++ src/qemu/qemu_capabilities.h | 9 ++++ 2 files changed, 108 insertions(+) diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index 3b08ef8..1163dd8 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -206,6 +206,11 @@ struct _qemuCaps { char **machineAliases; }; +struct _qemuCapsCache { + virMutex lock; + virHashTablePtr binaries; +}; + static virClassPtr qemuCapsClass; static void qemuCapsDispose(void *obj); @@ -1940,6 +1945,10 @@ qemuCapsPtr qemuCapsNewForBinary(const char *binary) tmp = strstr(binary, QEMU_SYSTEM_PREFIX); if (tmp) { tmp += strlen(QEMU_SYSTEM_PREFIX); + + /* For historical compat we uses 'itanium' as arch name */ + if (STREQ(tmp, "ia64")) + tmp = "itanium"; } else { uname_normalize(&ut); tmp = ut.machine; @@ -2048,3 +2057,93 @@ 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 485c297..27ed378 100644 --- a/src/qemu/qemu_capabilities.h +++ b/src/qemu/qemu_capabilities.h @@ -154,6 +154,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); @@ -183,6 +186,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, -- 1.7.11.4 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list