[libvirt] [PATCH v3 01/15] virNetworkObjListPtr: Turn list into a hash table

Michal Privoznik mprivozn at redhat.com
Tue Mar 10 16:45:07 UTC 2015


Signed-off-by: Michal Privoznik <mprivozn at redhat.com>
---
 src/conf/network_conf.c | 382 ++++++++++++++++++++++++++++++------------------
 1 file changed, 237 insertions(+), 145 deletions(-)

diff --git a/src/conf/network_conf.c b/src/conf/network_conf.c
index 9c1d578..ae29c47 100644
--- a/src/conf/network_conf.c
+++ b/src/conf/network_conf.c
@@ -54,8 +54,7 @@
 struct _virNetworkObjList {
     virObject parent;
 
-    size_t count;
-    virNetworkObjPtr *objs;
+    virHashTablePtr objs;
 };
 
 VIR_ENUM_IMPL(virNetworkForward,
@@ -96,6 +95,13 @@ static int virNetworkObjOnceInit(void)
 
 VIR_ONCE_GLOBAL_INIT(virNetworkObj)
 
+static void
+virNetworkObjListDataFree(void *payload, const void *name ATTRIBUTE_UNUSED)
+{
+    virNetworkObjPtr obj = payload;
+    virNetworkObjFree(obj);
+}
+
 virNetworkObjListPtr virNetworkObjListNew(void)
 {
     virNetworkObjListPtr nets;
@@ -106,37 +112,52 @@ virNetworkObjListPtr virNetworkObjListNew(void)
     if (!(nets = virObjectNew(virNetworkObjListClass)))
         return NULL;
 
+    if (!(nets->objs = virHashCreate(50, virNetworkObjListDataFree))) {
+        virObjectUnref(nets);
+        return NULL;
+    }
+
     return nets;
 }
 
 virNetworkObjPtr virNetworkObjFindByUUID(virNetworkObjListPtr nets,
                                          const unsigned char *uuid)
 {
-    size_t i;
+    virNetworkObjPtr ret = NULL;
+    char uuidstr[VIR_UUID_STRING_BUFLEN];
 
-    for (i = 0; i < nets->count; i++) {
-        virNetworkObjLock(nets->objs[i]);
-        if (!memcmp(nets->objs[i]->def->uuid, uuid, VIR_UUID_BUFLEN))
-            return nets->objs[i];
-        virNetworkObjUnlock(nets->objs[i]);
-    }
+    virUUIDFormat(uuid, uuidstr);
 
-    return NULL;
+    ret = virHashLookup(nets->objs, uuidstr);
+    if (ret)
+        virNetworkObjLock(ret);
+    return ret;
+}
+
+static int
+virNetworkObjSearchName(const void *payload,
+                        const void *name ATTRIBUTE_UNUSED,
+                        const void *data)
+{
+    virNetworkObjPtr net = (virNetworkObjPtr) payload;
+    int want = 0;
+
+    virNetworkObjLock(net);
+    if (STREQ(net->def->name, (const char *)data))
+        want = 1;
+    virNetworkObjUnlock(net);
+    return want;
 }
 
 virNetworkObjPtr virNetworkObjFindByName(virNetworkObjListPtr nets,
                                          const char *name)
 {
-    size_t i;
+    virNetworkObjPtr ret = NULL;
 
-    for (i = 0; i < nets->count; i++) {
-        virNetworkObjLock(nets->objs[i]);
-        if (STREQ(nets->objs[i]->def->name, name))
-            return nets->objs[i];
-        virNetworkObjUnlock(nets->objs[i]);
-    }
-
-    return NULL;
+    ret = virHashSearch(nets->objs, virNetworkObjSearchName, name);
+    if (ret)
+        virNetworkObjLock(ret);
+    return ret;
 }
 
 bool
@@ -315,12 +336,8 @@ static void
 virNetworkObjListDispose(void *obj)
 {
     virNetworkObjListPtr nets = obj;
-    size_t i;
 
-    for (i = 0; i < nets->count; i++)
-        virNetworkObjFree(nets->objs[i]);
-
-    VIR_FREE(nets->objs);
+    virHashFree(nets->objs);
 }
 
 /*
@@ -403,6 +420,7 @@ virNetworkAssignDef(virNetworkObjListPtr nets,
                     bool live)
 {
     virNetworkObjPtr network;
+    char uuidstr[VIR_UUID_STRING_BUFLEN];
 
     if ((network = virNetworkObjFindByName(nets, def->name))) {
         virNetworkObjAssignDef(network, def, live);
@@ -419,8 +437,11 @@ virNetworkAssignDef(virNetworkObjListPtr nets,
     }
     virNetworkObjLock(network);
 
-    if (VIR_APPEND_ELEMENT_COPY(nets->objs, nets->count, network) < 0 ||
-        !(network->class_id = virBitmapNew(CLASS_ID_BITMAP_SIZE)))
+    if (!(network->class_id = virBitmapNew(CLASS_ID_BITMAP_SIZE)))
+        goto error;
+
+    virUUIDFormat(def->uuid, uuidstr);
+    if (virHashAddEntry(nets->objs, uuidstr, network) < 0)
         goto error;
 
     /* The first three class IDs are already taken */
@@ -600,20 +621,11 @@ virNetworkConfigChangeSetup(virNetworkObjPtr network, unsigned int flags)
 void virNetworkRemoveInactive(virNetworkObjListPtr nets,
                               virNetworkObjPtr net)
 {
-    size_t i;
+    char uuidstr[VIR_UUID_STRING_BUFLEN];
 
+    virUUIDFormat(net->def->uuid, uuidstr);
     virNetworkObjUnlock(net);
-    for (i = 0; i < nets->count; i++) {
-        virNetworkObjLock(nets->objs[i]);
-        if (nets->objs[i] == net) {
-            virNetworkObjUnlock(nets->objs[i]);
-            virNetworkObjFree(nets->objs[i]);
-
-            VIR_DELETE_ELEMENT(nets->objs, i, nets->count);
-            break;
-        }
-        virNetworkObjUnlock(nets->objs[i]);
-    }
+    virHashRemoveEntry(nets->objs, uuidstr);
 }
 
 /* return ips[index], or NULL if there aren't enough ips */
@@ -3102,23 +3114,39 @@ char *virNetworkConfigFile(const char *dir,
     return ret;
 }
 
+struct virNetworkBridgeInUseHelperData {
+    const char *bridge;
+    const char *skipname;
+};
+
+static int
+virNetworkBridgeInUseHelper(const void *payload,
+                            const void *name ATTRIBUTE_UNUSED,
+                            const void *opaque)
+{
+    int ret = 0;
+    virNetworkObjPtr net = (virNetworkObjPtr) payload;
+    const struct virNetworkBridgeInUseHelperData *data = opaque;
+
+    virNetworkObjLock(net);
+    if (net->def->bridge &&
+        STREQ(net->def->bridge, data->bridge) &&
+        !(data->skipname && STREQ(net->def->name, data->skipname)))
+        ret = 1;
+    virNetworkObjUnlock(net);
+    return ret;
+}
+
 int virNetworkBridgeInUse(virNetworkObjListPtr nets,
                           const char *bridge,
                           const char *skipname)
 {
-    size_t i;
-    unsigned int ret = 0;
+    virNetworkObjPtr obj;
+    struct virNetworkBridgeInUseHelperData data = {bridge, skipname};
 
-    for (i = 0; i < nets->count; i++) {
-        virNetworkObjLock(nets->objs[i]);
-        if (nets->objs[i]->def->bridge &&
-            STREQ(nets->objs[i]->def->bridge, bridge) &&
-            !(skipname && STREQ(nets->objs[i]->def->name, skipname)))
-                ret = 1;
-        virNetworkObjUnlock(nets->objs[i]);
-    }
+    obj = virHashSearch(nets->objs, virNetworkBridgeInUseHelper, &data);
 
-    return ret;
+    return obj != NULL;
 }
 
 char *virNetworkAllocateBridge(virNetworkObjListPtr nets,
@@ -4271,6 +4299,52 @@ virNetworkMatch(virNetworkObjPtr netobj,
 }
 #undef MATCH
 
+struct virNetworkObjListData {
+    virConnectPtr conn;
+    virNetworkPtr *nets;
+    virNetworkObjListFilter filter;
+    unsigned int flags;
+    int nnets;
+    bool error;
+};
+
+static void
+virNetworkObjListPopulate(void *payload,
+                          const void *name ATTRIBUTE_UNUSED,
+                          void *opaque)
+{
+    struct virNetworkObjListData *data = opaque;
+    virNetworkObjPtr obj = payload;
+    virNetworkPtr net = NULL;
+
+    if (data->error)
+        return;
+
+    virNetworkObjLock(obj);
+
+    if (data->filter &&
+        !data->filter(data->conn, obj->def))
+        goto cleanup;
+
+    if (!virNetworkMatch(obj, data->flags))
+        goto cleanup;
+
+    if (!data->nets) {
+        data->nnets++;
+        goto cleanup;
+    }
+
+    if (!(net = virGetNetwork(data->conn, obj->def->name, obj->def->uuid))) {
+        data->error = true;
+        goto cleanup;
+    }
+
+    data->nets[data->nnets++] = net;
+
+ cleanup:
+    virNetworkObjUnlock(obj);
+}
+
 int
 virNetworkObjListExport(virConnectPtr conn,
                         virNetworkObjListPtr netobjs,
@@ -4278,53 +4352,50 @@ virNetworkObjListExport(virConnectPtr conn,
                         virNetworkObjListFilter filter,
                         unsigned int flags)
 {
-    virNetworkPtr *tmp_nets = NULL;
-    virNetworkPtr net = NULL;
-    int nnets = 0;
     int ret = -1;
-    size_t i;
+    struct virNetworkObjListData data = { conn, NULL, filter, flags, 0, false};
 
-    if (nets && VIR_ALLOC_N(tmp_nets, netobjs->count + 1) < 0)
+    if (nets && VIR_ALLOC_N(data.nets, virHashSize(netobjs->objs) + 1) < 0)
         goto cleanup;
 
-    for (i = 0; i < netobjs->count; i++) {
-        virNetworkObjPtr netobj = netobjs->objs[i];
-        virNetworkObjLock(netobj);
-        if ((!filter || filter(conn, netobj->def)) &&
-            virNetworkMatch(netobj, flags)) {
-            if (nets) {
-                if (!(net = virGetNetwork(conn,
-                                          netobj->def->name,
-                                          netobj->def->uuid))) {
-                    virNetworkObjUnlock(netobj);
-                    goto cleanup;
-                }
-                tmp_nets[nnets] = net;
-            }
-            nnets++;
-        }
-        virNetworkObjUnlock(netobj);
-    }
+    virHashForEach(netobjs->objs, virNetworkObjListPopulate, &data);
 
-    if (tmp_nets) {
+    if (data.error)
+        goto cleanup;
+
+    if (data.nets) {
         /* trim the array to the final size */
-        ignore_value(VIR_REALLOC_N(tmp_nets, nnets + 1));
-        *nets = tmp_nets;
-        tmp_nets = NULL;
+        ignore_value(VIR_REALLOC_N(data.nets, data.nnets + 1));
+        *nets = data.nets;
+        data.nets = NULL;
     }
 
-    ret = nnets;
-
+    ret = data.nnets;
  cleanup:
-    if (tmp_nets) {
-        for (i = 0; i < nnets; i++)
-            virObjectUnref(tmp_nets[i]);
-    }
+    while (data.nets && data.nnets)
+        virObjectUnref(data.nets[--data.nnets]);
 
-    VIR_FREE(tmp_nets);
+    VIR_FREE(data.nets);
     return ret;
 }
 
+struct virNetworkObjListForEachHelperData {
+    virNetworkObjListIterator callback;
+    void *opaque;
+    int ret;
+};
+
+static void
+virNetworkObjListForEachHelper(void *payload,
+                               const void *name ATTRIBUTE_UNUSED,
+                               void *opaque)
+{
+    struct virNetworkObjListForEachHelperData *data = opaque;
+
+    if (data->callback(payload, data->opaque) < 0)
+        data->ret = -1;
+}
+
 /**
  * virNetworkObjListForEach:
  * @nets: a list of network objects
@@ -4341,15 +4412,54 @@ virNetworkObjListForEach(virNetworkObjListPtr nets,
                          virNetworkObjListIterator callback,
                          void *opaque)
 {
-    int ret = 0;
-    size_t i = 0;
+    struct virNetworkObjListForEachHelperData data = {callback, opaque, 0};
+    virHashForEach(nets->objs, virNetworkObjListForEachHelper, &data);
+    return data.ret;
+}
 
-    for (i = 0; i < nets->count; i++) {
-        if (callback(nets->objs[i], opaque) < 0)
-            ret = -1;
+struct virNetworkObjListGetHelperData {
+    virConnectPtr conn;
+    virNetworkObjListFilter filter;
+    char **names;
+    int nnames;
+    bool active;
+    int got;
+    bool error;
+};
+
+static void
+virNetworkObjListGetHelper(void *payload,
+                           const void *name ATTRIBUTE_UNUSED,
+                           void *opaque)
+{
+    struct virNetworkObjListGetHelperData *data = opaque;
+    virNetworkObjPtr obj = payload;
+
+    if (data->error)
+        return;
+
+    if (data->nnames >= 0 &&
+        data->got == data->nnames)
+        return;
+
+    virNetworkObjLock(obj);
+
+    if (data->filter &&
+        !data->filter(data->conn, obj->def))
+        goto cleanup;
+
+    if ((data->active && virNetworkObjIsActive(obj)) ||
+        (!data->active && !virNetworkObjIsActive(obj))) {
+        if (data->names &&
+            VIR_STRDUP(data->names[data->got], obj->def->name) < 0) {
+            data->error = true;
+            goto cleanup;
+        }
+        data->got++;
     }
 
-    return ret;
+ cleanup:
+    virNetworkObjUnlock(obj);
 }
 
 int
@@ -4360,34 +4470,23 @@ virNetworkObjListGetNames(virNetworkObjListPtr nets,
                           virNetworkObjListFilter filter,
                           virConnectPtr conn)
 {
-    int got = 0;
-    size_t i;
+    int ret = -1;
 
-    for (i = 0; i < nets->count && got < nnames; i++) {
-        virNetworkObjPtr obj = nets->objs[i];
-        virNetworkObjLock(obj);
-        if (filter && !filter(conn, obj->def)) {
-            virNetworkObjUnlock(obj);
-            continue;
-        }
+    struct virNetworkObjListGetHelperData data = {
+        conn, filter, names, nnames, active, 0, false};
 
-        if ((active && virNetworkObjIsActive(obj)) ||
-            (!active && !virNetworkObjIsActive(obj))) {
-            if (VIR_STRDUP(names[got], obj->def->name) < 0) {
-                virNetworkObjUnlock(obj);
-                goto error;
-            }
-            got++;
-        }
-        virNetworkObjUnlock(obj);
+    virHashForEach(nets->objs, virNetworkObjListGetHelper, &data);
+
+    if (data.error)
+        goto cleanup;
+
+    ret = data.got;
+ cleanup:
+    if (ret < 0) {
+        while (data.got)
+            VIR_FREE(data.names[--data.got]);
     }
-
-    return got;
-
- error:
-    for (i = 0; i < got; i++)
-        VIR_FREE(names[i]);
-    return -1;
+    return ret;
 }
 
 int
@@ -4396,24 +4495,31 @@ virNetworkObjListNumOfNetworks(virNetworkObjListPtr nets,
                                virNetworkObjListFilter filter,
                                virConnectPtr conn)
 {
-    int count = 0;
-    size_t i;
+    struct virNetworkObjListGetHelperData data = {
+        conn, filter, NULL, -1, active, 0, false};
 
-    for (i = 0; i < nets->count; i++) {
-        virNetworkObjPtr obj = nets->objs[i];
-        virNetworkObjLock(obj);
-        if (filter && !filter(conn, obj->def)) {
-            virNetworkObjUnlock(obj);
-            continue;
-        }
+    virHashForEach(nets->objs, virNetworkObjListGetHelper, &data);
 
-        if ((active && virNetworkObjIsActive(obj)) ||
-            (!active && !virNetworkObjIsActive(obj)))
-            count++;
-        virNetworkObjUnlock(obj);
-    }
+    return data.got;
+}
 
-    return count;
+struct virNetworkObjListPruneHelperData {
+    unsigned int flags;
+};
+
+static int
+virNetworkObjListPruneHelper(const void *payload,
+                             const void *name ATTRIBUTE_UNUSED,
+                             const void *opaque)
+{
+    const struct virNetworkObjListPruneHelperData *data = opaque;
+    virNetworkObjPtr obj = (virNetworkObjPtr) payload;
+    int want = 0;
+
+    virNetworkObjLock(obj);
+    want = virNetworkMatch(obj, data->flags);
+    virNetworkObjUnlock(obj);
+    return want;
 }
 
 /**
@@ -4428,21 +4534,7 @@ void
 virNetworkObjListPrune(virNetworkObjListPtr nets,
                        unsigned int flags)
 {
-    size_t i = 0;
+    struct virNetworkObjListPruneHelperData data = {flags};
 
-    while (i < nets->count) {
-        virNetworkObjPtr obj = nets->objs[i];
-
-        virNetworkObjLock(obj);
-
-        if (virNetworkMatch(obj, flags)) {
-            virNetworkObjUnlock(obj);
-            virNetworkObjFree(obj);
-
-            VIR_DELETE_ELEMENT(nets->objs, i, nets->count);
-        } else {
-            virNetworkObjUnlock(obj);
-            i++;
-        }
-    }
+    virHashRemoveSet(nets->objs, virNetworkObjListPruneHelper, &data);
 }
-- 
2.0.5




More information about the libvir-list mailing list