Signed-off-by: Michal Privoznik <mprivozn(a)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