static char configDir[PATH_MAX];
static virHashTablePtr configCache = NULL;
+static virHashTablePtr nameConfigMap = NULL;
static int nconnections = 0;
static time_t lastRefresh = 0;
}
-/* Remove any configs which were not refreshed recently */
-static int xenXMConfigReaper(const void *payload, const char *key ATTRIBUTE_UNUSED, const void *data) {
- time_t now = *(const time_t *)data;
- xenXMConfCachePtr entry = (xenXMConfCachePtr)payload;
-
- if (entry->refreshedAt != now)
- return (1);
- return (0);
-}
-
/* Convenience method to grab a int from the config file object */
static int xenXMConfigGetInt(virConfPtr conf, const char *name, long *value) {
virConfValuePtr val;
/* Ensure that a config object has a valid UUID in it,
if it doesn't then (re-)generate one */
-static int xenXMConfigEnsureUUID(virConfPtr conf) {
+static int xenXMConfigEnsureIdentity(virConfPtr conf, const char *filename) {
unsigned char uuid[16];
+ const char *name;
+
+ /* Had better have a name...*/
+ if (xenXMConfigGetString(conf, "name", &name) < 0) {
+ virConfValuePtr value;
+ value = malloc(sizeof(virConfValue));
+ if (!value) {
+ return (-1);
+ }
+
+ /* Set name based on filename */
+ value->type = VIR_CONF_STRING;
+ value->str = strdup(filename);
+ if (!value->str) {
+ free(value);
+ return (-1);
+ }
+ if (virConfSetValue(conf, "name", value) < 0)
+ return (-1);
+ }
/* If there is no uuid...*/
if (xenXMConfigGetUUID(conf, "uuid", uuid) < 0) {
}
+/* Remove any configs which were not refreshed recently */
+static int xenXMConfigReaper(const void *payload, const char *key ATTRIBUTE_UNUSED, const void *data) {
+ time_t now = *(const time_t *)data;
+ xenXMConfCachePtr entry = (xenXMConfCachePtr)payload;
+
+ if (entry->refreshedAt != now) {
+ const char *olddomname;
+ /* We're going to pure this config file, so check if it
+ is currently mapped as owner of a named domain. */
+ if (xenXMConfigGetString(entry->conf, "name", &olddomname) != -1) {
+ char *nameowner = (char *)virHashLookup(nameConfigMap, olddomname);
+ if (nameowner && !strcmp(nameowner, key)) {
+ virHashRemoveEntry(nameConfigMap, olddomname, NULL);
+ }
+ }
+ return (1);
+ }
+ return (0);
+}
+
/* This method is called by various methods to scan /etc/xen
(or whatever directory was set by LIBVIRT_XM_CONFIG_DIR
environment variable) and process any domain configs. It
struct stat st;
int newborn = 0;
char path[PATH_MAX];
+ const char *domname = NULL;
/*
* Skip a bunch of crufty files that clearly aren't config files
/* If we already have a matching entry and it is not
modified, then carry on to next one*/
- if ((entry = virHashLookup(configCache, ent->d_name))) {
+ if ((entry = virHashLookup(configCache, path))) {
+ const char *olddomname = NULL;
+
if (entry->refreshedAt >= st.st_mtime) {
entry->refreshedAt = now;
continue;
}
- }
- if (entry) { /* Existing entry which needs refresh */
+ /* If we currently own the name, then release it and
+ re-acquire it later - just in case it was renamed */
+ if (xenXMConfigGetString(entry->conf, "name", &olddomname) != -1) {
+ char *nameowner = (char *)virHashLookup(nameConfigMap, olddomname);
+ if (nameowner && !strcmp(nameowner, path)) {
+ virHashRemoveEntry(nameConfigMap, olddomname, NULL);
+ }
+ }
+
+ /* Clear existing config entry which needs refresh */
virConfFree(entry->conf);
entry->conf = NULL;
} else { /* Completely new entry */
entry->refreshedAt = now;
if (!(entry->conf = virConfReadFile(entry->filename)) ||
- xenXMConfigEnsureUUID(entry->conf) < 0) {
+ xenXMConfigEnsureIdentity(entry->conf, ent->d_name) < 0) {
if (!newborn) {
- virHashRemoveEntry(configCache, ent->d_name, NULL);
+ virHashRemoveEntry(configCache, path, NULL);
}
free(entry);
continue;
}
+ /* Lookup what domain name the conf contains */
+ if (xenXMConfigGetString(entry->conf, "name", &domname) < 0) {
+ if (!newborn) {
+ virHashRemoveEntry(configCache, path, NULL);
+ }
+ free(entry);
+ goto cleanup;
+ }
+
/* If its a completely new entry, it must be stuck into
the cache (refresh'd entries are already registered) */
if (newborn) {
- if (virHashAddEntry(configCache, ent->d_name, entry) < 0) {
+ if (virHashAddEntry(configCache, entry->filename, entry) < 0) {
virConfFree(entry->conf);
free(entry);
goto cleanup;
}
}
+
+ /* See if we need to map this config file in as the primary owner
+ * of the domain in question
+ */
+ if (!virHashLookup(nameConfigMap, domname)) {
+ if (virHashAddEntry(nameConfigMap, domname, entry->filename) < 0) {
+ virHashRemoveEntry(configCache, ent->d_name, NULL);
+ virConfFree(entry->conf);
+ free(entry);
+ }
+ }
}
/* Reap all entries which were not changed, by comparing
configCache = virHashCreate(50);
if (!configCache)
return (-1);
+ nameConfigMap = virHashCreate(50);
+ if (!nameConfigMap) {
+ virHashFree(configCache, NULL);
+ configCache = NULL;
+ return (-1);
+ }
}
nconnections++;
*/
int xenXMClose(virConnectPtr conn ATTRIBUTE_UNUSED) {
if (!nconnections--) {
+ virHashFree(nameConfigMap, NULL);
+ nameConfigMap = NULL;
virHashFree(configCache, xenXMConfigFree);
configCache = NULL;
}
* VCPUs and memory.
*/
int xenXMDomainGetInfo(virDomainPtr domain, virDomainInfoPtr info) {
+ const char *filename;
xenXMConfCachePtr entry;
long vcpus;
long mem;
if (domain->handle != -1)
return (-1);
- if (!(entry = virHashLookup(configCache, domain->name)))
+ if (!(filename = virHashLookup(nameConfigMap, domain->name)))
+ return (-1);
+
+ if (!(entry = virHashLookup(configCache, filename)))
return (-1);
memset(info, 0, sizeof(virDomainInfo));
*/
char *xenXMDomainDumpXML(virDomainPtr domain, int flags ATTRIBUTE_UNUSED) {
virBufferPtr buf;
+ const char *filename;
xenXMConfCachePtr entry;
char *xml;
const char *name;
}
if (domain->handle != -1)
return (NULL);
- if (!(entry = virHashLookup(configCache, domain->name)))
+
+ if (!(filename = virHashLookup(nameConfigMap, domain->name)))
+ return (NULL);
+
+ if (!(entry = virHashLookup(configCache, filename)))
return (NULL);
if (xenXMConfigGetString(entry->conf, "name", &name) < 0)
* Update amount of memory in the config file
*/
int xenXMDomainSetMemory(virDomainPtr domain, unsigned long memory) {
+ const char *filename;
xenXMConfCachePtr entry;
virConfValuePtr value;
if (domain->handle != -1)
return (-1);
- if (!(entry = virHashLookup(configCache, domain->name)))
+ if (!(filename = virHashLookup(nameConfigMap, domain->name)))
+ return (-1);
+
+ if (!(entry = virHashLookup(configCache, filename)))
return (-1);
if (!(value = malloc(sizeof(virConfValue))))
* Update maximum memory limit in config
*/
int xenXMDomainSetMaxMemory(virDomainPtr domain, unsigned long memory) {
+ const char *filename;
xenXMConfCachePtr entry;
virConfValuePtr value;
if (domain->handle != -1)
return (-1);
- if (!(entry = virHashLookup(configCache, domain->name)))
+ if (!(filename = virHashLookup(nameConfigMap, domain->name)))
+ return (-1);
+
+ if (!(entry = virHashLookup(configCache, filename)))
return (-1);
if (!(value = malloc(sizeof(virConfValue))))
* Get max memory limit from config
*/
unsigned long xenXMDomainGetMaxMemory(virDomainPtr domain) {
+ const char *filename;
xenXMConfCachePtr entry;
long val;
if (domain->handle != -1)
return (-1);
- if (!(entry = virHashLookup(configCache, domain->name)))
+ if (!(filename = virHashLookup(nameConfigMap, domain->name)))
+ return (-1);
+
+ if (!(entry = virHashLookup(configCache, filename)))
return (-1);
if (xenXMConfigGetInt(entry->conf, "maxmem", &val) < 0 ||
* Set the VCPU count in config
*/
int xenXMDomainSetVcpus(virDomainPtr domain, unsigned int vcpus) {
+ const char *filename;
xenXMConfCachePtr entry;
virConfValuePtr value;
if (domain->handle != -1)
return (-1);
- if (!(entry = virHashLookup(configCache, domain->name)))
+ if (!(filename = virHashLookup(nameConfigMap, domain->name)))
+ return (-1);
+
+ if (!(entry = virHashLookup(configCache, filename)))
return (-1);
if (!(value = malloc(sizeof(virConfValue))))
* Find an inactive domain based on its name
*/
virDomainPtr xenXMDomainLookupByName(virConnectPtr conn, const char *domname) {
+ const char *filename;
xenXMConfCachePtr entry;
virDomainPtr ret;
unsigned char uuid[16];
if (xenXMConfigCacheRefresh() < 0)
return (NULL);
- if (!(entry = virHashLookup(configCache, domname))) {
+ if (!(filename = virHashLookup(nameConfigMap, domname)))
+ return (NULL);
+
+ if (!(entry = virHashLookup(configCache, filename))) {
return (NULL);
}
if (!(value = virConfGetValue(conf, "name")) || value->type != VIR_CONF_STRING || value->str == NULL)
goto error;
- if (virHashLookup(configCache, value->str) != 0)
+ if (virHashLookup(nameConfigMap, value->str))
goto error;
if ((strlen(configDir) + 1 + strlen(value->str) + 1) > PATH_MAX)
if (xenXMConfigGetUUID(conf, "uuid", uuid) < 0)
goto error;
- if (virHashAddEntry(configCache, value->str, entry) < 0)
+ if (virHashAddEntry(configCache, filename, entry) < 0)
+ goto error;
+
+ if (virHashAddEntry(nameConfigMap, value->str, entry->filename) < 0) {
+ virHashRemoveEntry(configCache, filename, NULL);
goto error;
+ }
+
entry = NULL;
if (!(ret = virGetDomain(conn, value->str, uuid)))
* Delete a domain from disk
*/
int xenXMDomainUndefine(virDomainPtr domain) {
+ const char *filename;
xenXMConfCachePtr entry;
if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) {
xenXMError((domain ? domain->conn : NULL), VIR_ERR_INVALID_ARG,
if (domain->conn->flags & VIR_CONNECT_RO)
return (-1);
- if (!(entry = virHashLookup(configCache, domain->name)))
+ if (!(filename = virHashLookup(nameConfigMap, domain->name)))
+ return (-1);
+
+ if (!(entry = virHashLookup(configCache, filename)))
return (-1);
if (unlink(entry->filename) < 0)
return (-1);
+ if (virHashRemoveEntry(nameConfigMap, entry->filename, NULL) < 0)
+ return(-1);
+
if (virHashRemoveEntry(configCache, domain->name, xenXMConfigFree) < 0)
return (-1);
ctx.max = maxnames;
ctx.names = names;
- virHashForEach(configCache, xenXMListIterator, &ctx);
+ virHashForEach(nameConfigMap, xenXMListIterator, &ctx);
return (ctx.count);
}
if (xenXMConfigCacheRefresh() < 0)
return (-1);
- return virHashSize(configCache);
+ return virHashSize(nameConfigMap);
}
/*