Rather than a forward linked list, let's use the ObjectRWLockable object
in order to manage the data.
Requires numerous changes from List to Object management similar to
many other drivers/vir*obj.c modules
Signed-off-by: John Ferlan <jferlan(a)redhat.com>
---
This is the real one - I need more coffee.
src/conf/virinterfaceobj.c | 365 +++++++++++++++++++++++++++++++--------------
src/libvirt_private.syms | 1 -
src/test/test_driver.c | 6 +-
3 files changed, 253 insertions(+), 119 deletions(-)
diff --git a/src/conf/virinterfaceobj.c b/src/conf/virinterfaceobj.c
index e993b929d7..cf3626def4 100644
--- a/src/conf/virinterfaceobj.c
+++ b/src/conf/virinterfaceobj.c
@@ -25,6 +25,7 @@
#include "viralloc.h"
#include "virerror.h"
#include "virinterfaceobj.h"
+#include "virhash.h"
#include "virlog.h"
#include "virstring.h"
@@ -40,14 +41,19 @@ struct _virInterfaceObj {
};
struct _virInterfaceObjList {
- size_t count;
- virInterfaceObjPtr *objs;
+ virObjectRWLockable parent;
+
+ /* name string -> virInterfaceObj mapping
+ * for O(1), lockless lookup-by-name */
+ virHashTable *objsName;
};
/* virInterfaceObj manipulation */
static virClassPtr virInterfaceObjClass;
+static virClassPtr virInterfaceObjListClass;
static void virInterfaceObjDispose(void *obj);
+static void virInterfaceObjListDispose(void *obj);
static int
virInterfaceObjOnceInit(void)
@@ -58,6 +64,12 @@ virInterfaceObjOnceInit(void)
virInterfaceObjDispose)))
return -1;
+ if (!(virInterfaceObjListClass = virClassNew(virClassForObjectRWLockable(),
+ "virInterfaceObjList",
+ sizeof(virInterfaceObjList),
+ virInterfaceObjListDispose)))
+ return -1;
+
return 0;
}
@@ -130,119 +142,188 @@ virInterfaceObjListNew(void)
{
virInterfaceObjListPtr interfaces;
- if (VIR_ALLOC(interfaces) < 0)
+ if (virInterfaceObjInitialize() < 0)
+ return NULL;
+
+ if (!(interfaces = virObjectRWLockableNew(virInterfaceObjListClass)))
+ return NULL;
+
+ if (!(interfaces->objsName = virHashCreate(10, virObjectFreeHashData))) {
+ virObjectUnref(interfaces);
return NULL;
+ }
+
return interfaces;
}
+struct _virInterfaceObjFindMACData {
+ const char *matchStr;
+ bool error;
+ int nmacs;
+ int maxmacs;
+ char **const macs;
+};
+
+static int
+virInterfaceObjListFindByMACStringCb(void *payload,
+ const void *name ATTRIBUTE_UNUSED,
+ void *opaque)
+{
+ virInterfaceObjPtr obj = payload;
+ struct _virInterfaceObjFindMACData *data = opaque;
+
+ if (data->error)
+ return 0;
+
+ if (data->nmacs == data->maxmacs)
+ return 0;
+
+ virObjectLock(obj);
+
+ if (STRCASEEQ(obj->def->mac, data->matchStr)) {
+ if (VIR_STRDUP(data->macs[data->nmacs], data->matchStr) < 0) {
+ data->error = true;
+ goto cleanup;
+ }
+ data->nmacs++;
+ }
+
+ cleanup:
+ virObjectUnlock(obj);
+ return 0;
+}
+
+
int
virInterfaceObjListFindByMACString(virInterfaceObjListPtr interfaces,
const char *mac,
char **const matches,
int maxmatches)
{
- size_t i;
- int matchct = 0;
+ struct _virInterfaceObjFindMACData data = { .matchStr = mac,
+ .error = false,
+ .nmacs = 0,
+ .maxmacs = maxmatches,
+ .macs = matches };
- for (i = 0; i < interfaces->count; i++) {
- virInterfaceObjPtr obj = interfaces->objs[i];
- virInterfaceDefPtr def;
+ virObjectRWLockRead(interfaces);
+ virHashForEach(interfaces->objsName, virInterfaceObjListFindByMACStringCb,
+ &data);
+ virObjectRWUnlock(interfaces);
- virObjectLock(obj);
- def = obj->def;
- if (STRCASEEQ(def->mac, mac)) {
- if (matchct < maxmatches) {
- if (VIR_STRDUP(matches[matchct], def->name) < 0) {
- virObjectUnlock(obj);
- goto error;
- }
- matchct++;
- }
- }
- virObjectUnlock(obj);
- }
- return matchct;
+ if (data.error)
+ goto error;
+
+ return data.nmacs;
error:
- while (--matchct >= 0)
- VIR_FREE(matches[matchct]);
+ while (--data.nmacs >= 0)
+ VIR_FREE(data.macs[data.nmacs]);
return -1;
}
+static virInterfaceObjPtr
+virInterfaceObjListFindByNameLocked(virInterfaceObjListPtr interfaces,
+ const char *name)
+{
+ return virObjectRef(virHashLookup(interfaces->objsName, name));
+}
+
+
virInterfaceObjPtr
virInterfaceObjListFindByName(virInterfaceObjListPtr interfaces,
const char *name)
{
- size_t i;
-
- for (i = 0; i < interfaces->count; i++) {
- virInterfaceObjPtr obj = interfaces->objs[i];
- virInterfaceDefPtr def;
-
+ virInterfaceObjPtr obj;
+ virObjectRWLockRead(interfaces);
+ obj = virInterfaceObjListFindByNameLocked(interfaces, name);
+ virObjectRWUnlock(interfaces);
+ if (obj)
virObjectLock(obj);
- def = obj->def;
- if (STREQ(def->name, name))
- return virObjectRef(obj);
- virObjectUnlock(obj);
- }
- return NULL;
+ return obj;
}
void
-virInterfaceObjListFree(virInterfaceObjListPtr interfaces)
+virInterfaceObjListDispose(void *obj)
{
- size_t i;
+ virInterfaceObjListPtr interfaces = obj;
+
+ virHashFree(interfaces->objsName);
+}
+
+
+struct _virInterfaceObjListCloneData {
+ bool error;
+ virInterfaceObjListPtr dest;
+};
+
+static int
+virInterfaceObjListCloneCb(void *payload,
+ const void *name ATTRIBUTE_UNUSED,
+ void *opaque)
+{
+ virInterfaceObjPtr srcObj = payload;
+ struct _virInterfaceObjListCloneData *data = opaque;
+ char *xml = NULL;
+ virInterfaceDefPtr backup = NULL;
+ virInterfaceObjPtr obj;
+
+ if (data->error)
+ return 0;
+
+ virObjectLock(srcObj);
+
+ if (!(xml = virInterfaceDefFormat(srcObj->def)))
+ goto error;
+
+ if (!(backup = virInterfaceDefParseString(xml)))
+ goto error;
+ VIR_FREE(xml);
- for (i = 0; i < interfaces->count; i++)
- virObjectUnref(interfaces->objs[i]);
- VIR_FREE(interfaces->objs);
- VIR_FREE(interfaces);
+ if (!(obj = virInterfaceObjListAssignDef(data->dest, backup)))
+ goto error;
+ virInterfaceObjEndAPI(&obj);
+
+ virObjectUnlock(srcObj);
+ return 0;
+
+ error:
+ data->error = true;
+ VIR_FREE(xml);
+ virInterfaceDefFree(backup);
+ virObjectUnlock(srcObj);
+ return 0;
}
virInterfaceObjListPtr
virInterfaceObjListClone(virInterfaceObjListPtr interfaces)
{
- size_t i;
- unsigned int cnt;
- virInterfaceObjListPtr dest;
+ struct _virInterfaceObjListCloneData data = { .error = false,
+ .dest = NULL };
if (!interfaces)
return NULL;
- if (!(dest = virInterfaceObjListNew()))
+ if (!(data.dest = virInterfaceObjListNew()))
return NULL;
- cnt = interfaces->count;
- for (i = 0; i < cnt; i++) {
- virInterfaceObjPtr srcobj = interfaces->objs[i];
- virInterfaceDefPtr backup;
- virInterfaceObjPtr obj;
- char *xml = virInterfaceDefFormat(srcobj->def);
-
- if (!xml)
- goto error;
+ virObjectRWLockRead(interfaces);
+ virHashForEach(interfaces->objsName, virInterfaceObjListCloneCb, &data);
+ virObjectRWUnlock(interfaces);
- if (!(backup = virInterfaceDefParseString(xml))) {
- VIR_FREE(xml);
- goto error;
- }
-
- VIR_FREE(xml);
- if (!(obj = virInterfaceObjListAssignDef(dest, backup)))
- goto error;
- virInterfaceObjEndAPI(&obj);
- }
+ if (data.error)
+ goto error;
- return dest;
+ return data.dest;
error:
- virInterfaceObjListFree(dest);
+ virObjectUnref(data.dest);
return NULL;
}
@@ -253,9 +334,11 @@ virInterfaceObjListAssignDef(virInterfaceObjListPtr interfaces,
{
virInterfaceObjPtr obj;
- if ((obj = virInterfaceObjListFindByName(interfaces, def->name))) {
+ virObjectRWLockWrite(interfaces);
+ if ((obj = virInterfaceObjListFindByNameLocked(interfaces, def->name))) {
virInterfaceDefFree(obj->def);
obj->def = def;
+ virObjectRWUnlock(interfaces);
return obj;
}
@@ -263,13 +346,19 @@ virInterfaceObjListAssignDef(virInterfaceObjListPtr interfaces,
if (!(obj = virInterfaceObjNew()))
return NULL;
- if (VIR_APPEND_ELEMENT_COPY(interfaces->objs,
- interfaces->count, obj) < 0) {
- virInterfaceObjEndAPI(&obj);
- return NULL;
- }
+ if (virHashAddEntry(interfaces->objsName, def->name, obj) < 0)
+ goto error;
+ virObjectRef(obj);
+
obj->def = def;
- return virObjectRef(obj);
+ virObjectRWUnlock(interfaces);
+
+ return obj;
+
+ error:
+ virInterfaceObjEndAPI(&obj);
+ virObjectRWUnlock(interfaces);
+ return NULL;
}
@@ -277,20 +366,37 @@ void
virInterfaceObjListRemove(virInterfaceObjListPtr interfaces,
virInterfaceObjPtr obj)
{
- size_t i;
+ virObjectRef(obj);
+ virObjectUnlock(obj);
+ virObjectRWLockWrite(interfaces);
+ virObjectLock(obj);
+ virHashRemoveEntry(interfaces->objsName, obj->def->name);
+ virObjectUnlock(obj);
+ virObjectUnref(obj);
+ virObjectRWUnlock(interfaces);
+}
+
+
+struct _virInterfaceObjNumOfInterfacesData {
+ bool wantActive;
+ int count;
+};
+
+static int
+virInterfaceObjListNumOfInterfacesCb(void *payload,
+ const void *name ATTRIBUTE_UNUSED,
+ void *opaque)
+{
+ virInterfaceObjPtr obj = payload;
+ struct _virInterfaceObjNumOfInterfacesData *data = opaque;
+
+ virObjectLock(obj);
+
+ if (data->wantActive == virInterfaceObjIsActive(obj))
+ data->count++;
virObjectUnlock(obj);
- for (i = 0; i < interfaces->count; i++) {
- virObjectLock(interfaces->objs[i]);
- if (interfaces->objs[i] == obj) {
- virObjectUnlock(interfaces->objs[i]);
- virObjectUnref(interfaces->objs[i]);
-
- VIR_DELETE_ELEMENT(interfaces->objs, i, interfaces->count);
- break;
- }
- virObjectUnlock(interfaces->objs[i]);
- }
+ return 0;
}
@@ -298,18 +404,55 @@ int
virInterfaceObjListNumOfInterfaces(virInterfaceObjListPtr interfaces,
bool wantActive)
{
- size_t i;
- int ninterfaces = 0;
+ struct _virInterfaceObjNumOfInterfacesData data = {
+ .wantActive = wantActive, .count = 0 };
- for (i = 0; (i < interfaces->count); i++) {
- virInterfaceObjPtr obj = interfaces->objs[i];
- virObjectLock(obj);
- if (wantActive == virInterfaceObjIsActive(obj))
- ninterfaces++;
- virObjectUnlock(obj);
+ virObjectRWLockRead(interfaces);
+ virHashForEach(interfaces->objsName, virInterfaceObjListNumOfInterfacesCb,
+ &data);
+ virObjectRWUnlock(interfaces);
+
+ return data.count;
+}
+
+
+struct _virInterfaceObjGetNamesData {
+ bool wantActive;
+ bool error;
+ int nnames;
+ int maxnames;
+ char **const names;
+};
+
+static int
+virInterfaceObjListGetNamesCb(void *payload,
+ const void *name ATTRIBUTE_UNUSED,
+ void *opaque)
+{
+ virInterfaceObjPtr obj = payload;
+ struct _virInterfaceObjGetNamesData *data = opaque;
+
+ if (data->error)
+ return 0;
+
+ if (data->maxnames >= 0 && data->nnames == data->maxnames)
+ return 0;
+
+ virObjectLock(obj);
+
+ if (data->wantActive != virInterfaceObjIsActive(obj))
+ goto cleanup;
+
+ if (VIR_STRDUP(data->names[data->nnames], obj->def->name) < 0) {
+ data->error = true;
+ goto cleanup;
}
- return ninterfaces;
+ data->nnames++;
+
+ cleanup:
+ virObjectUnlock(obj);
+ return 0;
}
@@ -319,30 +462,22 @@ virInterfaceObjListGetNames(virInterfaceObjListPtr interfaces,
char **const names,
int maxnames)
{
- int nnames = 0;
- size_t i;
+ struct _virInterfaceObjGetNamesData data = {
+ .wantActive = wantActive, .error = false, .nnames = 0,
+ .maxnames = maxnames, .names = names };
- for (i = 0; i < interfaces->count && nnames < maxnames; i++) {
- virInterfaceObjPtr obj = interfaces->objs[i];
- virInterfaceDefPtr def;
+ virObjectRWLockRead(interfaces);
+ virHashForEach(interfaces->objsName, virInterfaceObjListGetNamesCb, &data);
+ virObjectRWUnlock(interfaces);
- virObjectLock(obj);
- def = obj->def;
- if (wantActive == virInterfaceObjIsActive(obj)) {
- if (VIR_STRDUP(names[nnames], def->name) < 0) {
- virObjectUnlock(obj);
- goto failure;
- }
- nnames++;
- }
- virObjectUnlock(obj);
- }
+ if (data.error)
+ goto error;
- return nnames;
+ return data.nnames;
- failure:
- while (--nnames >= 0)
- VIR_FREE(names[nnames]);
+ error:
+ while (--data.nnames >= 0)
+ VIR_FREE(data.names[data.nnames]);
return -1;
}
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 26c5ddb405..9133199895 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -932,7 +932,6 @@ virInterfaceObjListAssignDef;
virInterfaceObjListClone;
virInterfaceObjListFindByMACString;
virInterfaceObjListFindByName;
-virInterfaceObjListFree;
virInterfaceObjListGetNames;
virInterfaceObjListNew;
virInterfaceObjListNumOfInterfaces;
diff --git a/src/test/test_driver.c b/src/test/test_driver.c
index 1c48347994..14bba7494c 100644
--- a/src/test/test_driver.c
+++ b/src/test/test_driver.c
@@ -154,7 +154,7 @@ testDriverFree(testDriverPtr driver)
virObjectUnref(driver->domains);
virNodeDeviceObjListFree(driver->devs);
virObjectUnref(driver->networks);
- virInterfaceObjListFree(driver->ifaces);
+ virObjectUnref(driver->ifaces);
virStoragePoolObjListFree(&driver->pools);
virObjectUnref(driver->eventState);
virMutexUnlock(&driver->lock);
@@ -3880,7 +3880,7 @@ testInterfaceChangeCommit(virConnectPtr conn,
goto cleanup;
}
- virInterfaceObjListFree(privconn->backupIfaces);
+ virObjectUnref(privconn->backupIfaces);
privconn->transaction_running = false;
ret = 0;
@@ -3910,7 +3910,7 @@ testInterfaceChangeRollback(virConnectPtr conn,
goto cleanup;
}
- virInterfaceObjListFree(privconn->ifaces);
+ virObjectUnref(privconn->ifaces);
privconn->ifaces = privconn->backupIfaces;
privconn->backupIfaces = NULL;
--
2.13.6