On Sun, Mar 11, 2012 at 02:45:04PM -0400, Lee Schermerhorn wrote: > Define a qemu emulator cache structure and function to lookup, > create, refresh emulator cache objects. The cache "tags" are > the paths to the emulator binaries. E.g., "/usr/bin/qemu" > > Subsequent patches will "hook up" the various extract/probe info > functions to consult the cache. > > Notes/questions: > 1) "qemuCapsProbes" converted to bitmap along with capabilities flags > as part of rebase. Overkill? > 2) Is it OK for the root of the cache and the nEmulators to be statically > defined in qemu_capabilities.c as opposed to a field in the driver struct? > It is private to that source file and I don't see an easy wait to get > a handle on the driver struct therein. > > --- > src/qemu/qemu_capabilities.c | 166 +++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 166 insertions(+) > > Index: libvirt-0.9.10/src/qemu/qemu_capabilities.c > =================================================================== > --- libvirt-0.9.10.orig/src/qemu/qemu_capabilities.c > +++ libvirt-0.9.10/src/qemu/qemu_capabilities.c > @@ -170,6 +170,46 @@ struct qemu_arch_info { > int nflags; > }; > > +/* > + * * Flags to record which "probes" have been cached > + * */ > +enum qemuCapsProbes { > + QEMU_PROBE_VERSION_INFO = 0, > + QEMU_PROBE_MACHINE_TYPES = 1, > + QEMU_PROBE_CPU_MODELS = 2, > + QEMU_PROBE_SIZE > +}; > + > +typedef struct _qemuEmulatorCache qemuEmulatorCache; > +typedef qemuEmulatorCache* qemuEmulatorCachePtr; > +struct _qemuEmulatorCache { > + char *path; > + char *arch; > + time_t mtime; > + virBitmapPtr cachedProbes; > + > + unsigned int version; > + virBitmapPtr caps; > + > + virCapsGuestMachinePtr *machines; > + int nmachines; > + > + char **cpus; > + unsigned int ncpus; > +}; > + > +static qemuEmulatorCachePtr *emulatorCache = NULL; > +static int nEmulators; > + > +static qemuEmulatorCachePtr > +qemuEmulatorCachedInfoGet(enum qemuCapsProbes, > + const char *binary, > + const char *arch); > + > +static void > +qemuEmulatorCachedInfoRelease(qemuEmulatorCachePtr emulator ATTRIBUTE_UNUSED) > +{ } > + > /* Feature flags for the architecture info */ > static const struct qemu_feature_flags const arch_info_i686_flags [] = { > { "pae", 1, 0 }, > @@ -319,6 +359,12 @@ cleanup: > } > > static int > +qemuCapsCacheMachineTypes(qemuEmulatorCachePtr emulator) > +{ > + return emulator ? 0 : 1; > +} > + > +static int > qemuCapsGetOldMachinesFromInfo(virCapsGuestDomainInfoPtr info, > const char *emulator, > time_t emulator_mtime, > @@ -612,6 +658,11 @@ cleanup: > return ret; > } > > +static int > +qemuCapsCacheCPUModels(qemuEmulatorCachePtr emulator) > +{ > + return emulator ? 0 : 1; > +} > > static int > qemuCapsInitGuest(virCapsPtr caps, > @@ -1510,6 +1561,12 @@ cleanup: > return ret; > } > > +static int > +qemuCapsCacheVersionInfo(qemuEmulatorCachePtr emulator) > +{ > + return emulator ? 0 : 1; > +} > + > static void > uname_normalize (struct utsname *ut) > { > @@ -1610,3 +1667,112 @@ qemuCapsGet(virBitmapPtr caps, > else > return b; > } > + > +static qemuEmulatorCachePtr > +qemuEmulatorCachedInfoGet(enum qemuCapsProbes probe, > + const char *binary, > + const char *arch) > +{ > + qemuEmulatorCachePtr emulator = NULL; > + struct stat st; > + bool alreadyCached; > + int i; > + > + if (stat(binary, &st) != 0) { > + char ebuf[1024]; > + VIR_INFO("Failed to stat emulator %s : %s", > + binary, virStrerror(errno, ebuf, sizeof(ebuf))); > + goto error; Hum ... seems to me we should still go though the emulator cache here and discard cached info (if present) for that path > + } > + > + for (i = 0; i < nEmulators; ++i) { > + emulator = emulatorCache[i]; > + > + if (!STREQ(binary, emulator->path)) > + continue; > + > + if (arch && !emulator->arch) { > + if (!(emulator->arch = strdup(arch))) > + goto no_memory; > + /* > + * We have an 'arch' now, where we didn't before. > + * So, even if we've already cached this probe, > + * refresh the cache with the specified arch. > + */ > + break; > + } > + > + if (st.st_mtime != emulator->mtime) > + break; /* binary changed, refresh cache */ > + > + if (virBitmapGetBit(emulator->cachedProbes, probe, &alreadyCached) < 0) { > + VIR_ERROR(_("Unrecognized probe id '%d'"), probe); > + goto error; > + } > + if (!alreadyCached) > + break; /* do it now */ > + > + return emulator; > + } > + > + if (i == nEmulators) { > + if (VIR_REALLOC_N(emulatorCache, nEmulators + 1) < 0) > + goto no_memory; > + if (VIR_ALLOC(emulator) < 0) > + goto no_memory; > + if (!(emulator->path = strdup(binary))) > + goto no_memory_free_emulator; > + if (arch && !(emulator->arch = strdup(arch))) > + goto no_memory_free_emulator; > + if (!(emulator->cachedProbes = virBitmapAlloc(QEMU_PROBE_SIZE))) > + goto no_memory_free_emulator; > + VIR_DEBUG("Adding emulator cache for %s - %s", > + emulator->path, emulator->arch); > + emulatorCache[nEmulators] = emulator; > + nEmulators += 1; > + } else { > + VIR_DEBUG("Refreshing emulator cache for %s - %s", > + emulator->path, emulator->arch); > + } > + > + switch (probe) { > + > + case QEMU_PROBE_VERSION_INFO: > + if (qemuCapsCacheVersionInfo(emulator) != 0 || > + virBitmapSetBit(emulator->cachedProbes, QEMU_PROBE_VERSION_INFO) < 0) > + goto error; > + break; > + > + case QEMU_PROBE_MACHINE_TYPES: > + if (qemuCapsCacheMachineTypes(emulator) != 0 || > + virBitmapSetBit(emulator->cachedProbes, QEMU_PROBE_MACHINE_TYPES) < 0) > + goto error; > + break; > + > + case QEMU_PROBE_CPU_MODELS: > + if (qemuCapsCacheCPUModels(emulator) != 0 || > + virBitmapSetBit(emulator->cachedProbes, QEMU_PROBE_CPU_MODELS) < 0) > + goto error; > + break; > + > + default: > + /* We REALLY shouldn't get here... */ > + VIR_ERROR(_("Unrecognized probe id '%d'"), probe); > + goto error; > + } > + > + > + emulator->mtime = st.st_mtime; > + return emulator; > + > +no_memory_free_emulator: > + VIR_FREE(emulator->path); > + VIR_FREE(emulator->arch); > + VIR_FREE(emulator); > + > +no_memory: > + virReportOOMError(); > + > +error: > + return NULL; > +} > > -- > libvir-list mailing list > libvir-list@xxxxxxxxxx > https://www.redhat.com/mailman/listinfo/libvir-list -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel@xxxxxxxxxxxx | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/ -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list