[virt-tools-list] [PATCH 31/47] Turn OS relationships into a GList structure

Daniel P. Berrange berrange at redhat.com
Wed Aug 25 19:37:26 UTC 2010


Simplify storage of OS relationships by using a single GList
instead of a pair of GTree objects. The data access patterns
mean there is no change in access efficiency

* osinfo/osinfo_common.h, osinfo/osinfo_dataread.c,
  osinfo/osinfo_db.c, osinfo/osinfo_entity.c,
  osinfo/osinfo_os.c, osinfo/osinfo_os.h: Replace
  GTree with GList for OS relationships.
---
 osinfo/osinfo_common.h   |   20 +-----
 osinfo/osinfo_dataread.c |   61 ++++---------------
 osinfo/osinfo_db.c       |    9 ++-
 osinfo/osinfo_entity.c   |   26 +++++---
 osinfo/osinfo_os.c       |  149 ++++++++++------------------------------------
 osinfo/osinfo_os.h       |    2 +
 6 files changed, 69 insertions(+), 198 deletions(-)

diff --git a/osinfo/osinfo_common.h b/osinfo/osinfo_common.h
index c660a73..dcfa109 100644
--- a/osinfo/osinfo_common.h
+++ b/osinfo/osinfo_common.h
@@ -42,14 +42,13 @@ struct __osinfoDeviceLink {
 };
 
 struct __osinfoOsLink {
-    /* <subject_os> 'verbs' <direct_object_os>
+    /* <self> 'verbs' <other_os>
      * fedora11 upgrades fedora10
      * centos clones rhel
      * scientificlinux derives from rhel
      */
-    OsinfoOs *subjectOs;
-    osinfoRelationship verb;
-    OsinfoOs *directObjectOs;
+    osinfoRelationship relshp;
+    OsinfoOs *otherOs;
 };
 
 struct __osinfoOsCheckRelationshipArgs {
@@ -103,13 +102,8 @@ struct _OsinfoOsPrivate
     // Value: List of device_link structs
     GList *deviceLinks;
 
-    // OS-OS relationships
-    // Key: gchar* (other os id)
-    // Value: Array of os_link structs
-    GTree *relationshipsByOs;
-    // Key: relationship type
     // Value: Array of os_link structs
-    GTree *relationshipsByType;
+    GList *osLinks;
 };
 
 struct _OsinfoEntityPrivate
@@ -121,11 +115,5 @@ struct _OsinfoEntityPrivate
     GTree *params;
 };
 
-/** ****************************************************************************
- *      Private Methods
- ******************************************************************************/
-
-int __osinfoAddOsRelationship (OsinfoOs *self, gchar *otherOsId, osinfoRelationship rel);
-void __osinfoClearOsRelationships (OsinfoOs *self, gchar *otherOsId);
 
 #endif /* __OSINFO_OBJECTS_H__ */
diff --git a/osinfo/osinfo_dataread.c b/osinfo/osinfo_dataread.c
index 9d92c49..3e6231d 100644
--- a/osinfo/osinfo_dataread.c
+++ b/osinfo/osinfo_dataread.c
@@ -43,49 +43,6 @@ struct __osinfoDbRet {
   g_set_error_literal((err), g_quark_from_static_string("libosinfo"), 0, (msg));
 
 
-static gboolean __osinfoResolveOsLink(gpointer key, gpointer value, gpointer data)
-{
-    gchar *targetOsId = (gchar *) key;
-    struct __osinfoDbRet *dbRet = (struct __osinfoDbRet *) data;
-    OsinfoDb *db = dbRet->db;
-    struct __osinfoOsLink *osLink = (struct __osinfoOsLink *) value;
-    OsinfoOs *targetOs;
-    OsinfoOsList *oslist = osinfo_db_get_os_list(db);
-
-    targetOs = OSINFO_OS(osinfo_list_find_by_id(OSINFO_LIST(oslist), targetOsId));
-    if (!targetOs) {
-        OSINFO_ERROR(dbRet->err, "missing os");
-        return TRUE;
-    }
-
-    osLink->directObjectOs = targetOs;
-    return FALSE;
-}
-
-static gboolean __osinfoFixOsLinks(OsinfoList *list, OsinfoEntity *entity, gpointer data)
-{
-    g_return_val_if_fail(OSINFO_OS(entity), TRUE);
-
-    struct __osinfoDbRet *dbRet = data;
-    OsinfoOs *os = OSINFO_OS(entity);
-
-    g_tree_foreach(os->priv->relationshipsByOs, __osinfoResolveOsLink, dbRet);
-    if (*dbRet->err)
-        return TRUE;
-
-    return FALSE;
-}
-
-static void __osinfoFixObjLinks(OsinfoDb *db, GError **err)
-{
-    g_return_if_fail(OSINFO_IS_DB(db));
-
-    struct __osinfoDbRet dbRet = {db, err };
-    OsinfoOsList *oses = osinfo_db_get_os_list(db);
-
-    osinfo_list_foreach(OSINFO_LIST(oses), __osinfoFixOsLinks, &dbRet);
-}
-
 static int __osinfoProcessTag(xmlTextReaderPtr reader, char** ptr_to_key, char** ptr_to_val)
 {
     int node_type, ret, err = 0;
@@ -246,6 +203,7 @@ error:
 }
 
 static int __osinfoProcessOsRelationship(xmlTextReaderPtr reader,
+					 OsinfoDb *db,
                                          OsinfoOs *os,
                                          osinfoRelationship relationship)
 {
@@ -259,9 +217,14 @@ static int __osinfoProcessOsRelationship(xmlTextReaderPtr reader,
         return -EINVAL;
     }
 
-    ret = __osinfoAddOsRelationship (os, id, relationship);
+    OsinfoOs *otheros = osinfo_db_get_os(db, id);
+    if (!otheros) {
+        free(id);
+        return -ENOENT;
+    }
+    osinfo_os_add_related_os(os, relationship, otheros);
     free(id);
-    return ret;
+    return 0;
 }
 
 static int __osinfoProcessOs(OsinfoDb *db,
@@ -367,17 +330,17 @@ static int __osinfoProcessOs(OsinfoDb *db,
                 goto cleanup_error;
         }
         else if (strcmp(name, "upgrades") == 0) {
-            err = __osinfoProcessOsRelationship(reader, os, UPGRADES);
+	    err = __osinfoProcessOsRelationship(reader, db, os, UPGRADES);
             if (err != 0)
                 goto cleanup_error;
         }
         else if (strcmp(name, "clones") == 0) {
-            err = __osinfoProcessOsRelationship(reader, os, CLONES);
+	    err = __osinfoProcessOsRelationship(reader, db, os, CLONES);
             if (err != 0)
                 goto cleanup_error;
         }
         else if (strcmp(name, "derives-from") == 0) {
-            err = __osinfoProcessOsRelationship(reader, os, DERIVES_FROM);
+	    err = __osinfoProcessOsRelationship(reader, db, os, DERIVES_FROM);
             if (err != 0)
                 goto cleanup_error;
         }
@@ -784,8 +747,6 @@ void osinfo_dataread(OsinfoDb *db, GError **err)
             break;
     }
     closedir(dir);
-    if (!*err)
-        __osinfoFixObjLinks(db, err);
 
 cleanup:
     xmlCleanupParser();
diff --git a/osinfo/osinfo_db.c b/osinfo/osinfo_db.c
index 2a5740f..09ba57a 100644
--- a/osinfo/osinfo_db.c
+++ b/osinfo/osinfo_db.c
@@ -288,11 +288,12 @@ static gboolean __osinfoAddOsIfRelationship(OsinfoList *list, OsinfoEntity *enti
     struct __osinfoOsCheckRelationshipArgs *args = data;
     OsinfoOs *os = OSINFO_OS(entity);
     OsinfoList *newList = args->list;
+    OsinfoOsList *thisList = osinfo_os_get_related(os, args->relshp);
+    int i;
 
-    GPtrArray *relatedOses = NULL;
-    relatedOses = g_tree_lookup(os->priv->relationshipsByType, (gpointer) args->relshp);
-    if (relatedOses) {
-        osinfo_list_add(newList, OSINFO_ENTITY (os));
+    for (i = 0 ; i < osinfo_list_get_length(OSINFO_LIST(thisList)) ; i++) {
+        OsinfoEntity *entity = osinfo_list_get_nth(OSINFO_LIST(thisList), i);
+	osinfo_list_add(newList, entity);
     }
 
     return FALSE;
diff --git a/osinfo/osinfo_entity.c b/osinfo/osinfo_entity.c
index da48489..8df1de5 100644
--- a/osinfo/osinfo_entity.c
+++ b/osinfo/osinfo_entity.c
@@ -252,30 +252,36 @@ static gboolean osinfo_entity_relation_matcher(OsinfoFilter *self,
 					       gpointer data)
 {
     OsinfoOs *os = data;
-    GPtrArray *osOses;
+    OsinfoOsList *oslist = osinfo_os_get_related(os, relshp);
+    gboolean ret = TRUE;
 
-    osOses = g_tree_lookup(os->priv->relationshipsByType, GINT_TO_POINTER(relshp));
-    if (relOses && !osOses)
-        return FALSE;
+    if (relOses && osinfo_list_get_length(OSINFO_LIST(oslist)) == 0) {
+        ret = FALSE;
+	goto cleanup;
+    }
 
     while (relOses) {
         OsinfoOs *currOs = relOses->data;
-        int j;
+        int i;
 	gboolean found = FALSE;
-        for (j = 0; j < osOses->len; j++) {
-            OsinfoOs *testOs = g_ptr_array_index(osOses, j);
+	for (i = 0 ; i < osinfo_list_get_length(OSINFO_LIST(oslist)) ; i++) {
+	    OsinfoOs *testOs = OSINFO_OS(osinfo_list_get_nth(OSINFO_LIST(oslist), i));
             if (testOs == currOs) {
                 found = TRUE;
                 break;
             }
         }
-        if (!found)
-	    return FALSE;
+        if (!found) {
+	    ret = FALSE;
+	    goto cleanup;
+	}
 
 	relOses = relOses->next;
     }
 
-    return TRUE;
+ cleanup:
+    g_object_unref(oslist);
+    return ret;
 }
 
 
diff --git a/osinfo/osinfo_os.c b/osinfo/osinfo_os.c
index dc27c6d..5842a12 100644
--- a/osinfo/osinfo_os.c
+++ b/osinfo/osinfo_os.c
@@ -11,6 +11,11 @@ static void osinfo_device_link_free(gpointer data, gpointer opaque G_GNUC_UNUSED
     __osinfoFreeDeviceLink(data);
 }
 
+static void osinfo_os_link_free(gpointer data, gpointer opaque G_GNUC_UNUSED)
+{
+    __osinfoFreeOsLink(data);
+}
+
 
 static void
 osinfo_os_finalize (GObject *object)
@@ -20,8 +25,9 @@ osinfo_os_finalize (GObject *object)
     g_list_foreach(self->priv->deviceLinks, osinfo_device_link_free, NULL);
     g_list_free(self->priv->deviceLinks);
     g_hash_table_unref(self->priv->hypervisors);
-    g_tree_destroy (self->priv->relationshipsByOs);
-    g_tree_destroy (self->priv->relationshipsByType);
+
+    g_list_foreach(self->priv->osLinks, osinfo_os_link_free, NULL);
+    g_list_free(self->priv->osLinks);
 
     /* Chain up to the parent class */
     G_OBJECT_CLASS (osinfo_os_parent_class)->finalize (object);
@@ -53,13 +59,7 @@ osinfo_os_init (OsinfoOs *self)
     self->priv = priv = OSINFO_OS_GET_PRIVATE(self);
 
     self->priv->deviceLinks = NULL;
-
-    self->priv->relationshipsByOs = g_tree_new_full(__osinfoStringCompare,
-                                                NULL,
-                                                g_free,
-                                                __osinfoFreeRelationship);
-    self->priv->relationshipsByType = g_tree_new(__osinfoIntCompareBase);
-
+    self->priv->osLinks = NULL;
     self->priv->hypervisors = g_hash_table_new_full(g_str_hash,
 						    g_str_equal,
 						    g_free,
@@ -74,106 +74,6 @@ OsinfoOs *osinfo_os_new(const gchar *id)
 }
 
 
-static int __osinfoAddOsRelationshipByOs(OsinfoOs *self,
-                                         gchar *otherOsId,
-                                         osinfoRelationship rel,
-                                         struct __osinfoOsLink *osLink)
-{
-    gboolean found;
-    gpointer origKey, foundValue;
-    GPtrArray *relationshipsForOs;
-    gchar *otherOsIdDup = NULL;
-
-    found = g_tree_lookup_extended(self->priv->relationshipsByOs, otherOsId, &origKey, &foundValue);
-    if (!found) {
-        otherOsIdDup = g_strdup(otherOsId);
-        relationshipsForOs = g_ptr_array_new_with_free_func(__osinfoFreeOsLink);
-
-        g_tree_insert(self->priv->relationshipsByOs, otherOsIdDup, relationshipsForOs);
-    }
-    else
-        relationshipsForOs = (GPtrArray *) foundValue;
-
-    g_ptr_array_add(relationshipsForOs, osLink);
-    return 0;
-}
-
-static int __osinfoAddOsRelationshipByType(OsinfoOs *self,
-                                           osinfoRelationship relshp,
-                                           struct __osinfoOsLink *osLink)
-{
-    gboolean found;
-    gpointer origKey, foundValue;
-    GPtrArray *relationshipsForType;
-
-    found = g_tree_lookup_extended(self->priv->relationshipsByType, (gpointer) relshp, &origKey, &foundValue);
-    if (!found) {
-        relationshipsForType = g_ptr_array_new();
-
-        g_tree_insert(self->priv->relationshipsByType, (gpointer) relshp, relationshipsForType);
-    }
-    else
-        relationshipsForType = (GPtrArray *) foundValue;
-
-    g_ptr_array_add(relationshipsForType, osLink);
-    return 0;
-}
-
-static void __osinfoRemoveOsLink(OsinfoOs *self,
-                                 gchar *otherOsId,
-                                 osinfoRelationship relshp,
-                                 struct __osinfoOsLink *osLink)
-{
-    gboolean found;
-    gpointer origKey, foundValue;
-    GPtrArray *relationshipsForOs;
-    GPtrArray *relationshipsForType;
-
-    // First from by-os list
-    found = g_tree_lookup_extended(self->priv->relationshipsByOs, otherOsId, &origKey, &foundValue);
-    if (found) {
-        relationshipsForOs = (GPtrArray *) foundValue;
-        g_ptr_array_remove(relationshipsForOs, osLink);
-    }
-
-    // Now from by-relshp list
-    found = g_tree_lookup_extended(self->priv->relationshipsByType, (gpointer) relshp, &origKey, &foundValue);
-    if (found) {
-        relationshipsForType = (GPtrArray *) foundValue;
-        g_ptr_array_remove(relationshipsForType, osLink);
-    }
-}
-
-int __osinfoAddOsRelationship (OsinfoOs *self, gchar *otherOsId, osinfoRelationship rel)
-{
-    if ( !OSINFO_IS_OS(self) || !otherOsId)
-        return -EINVAL;
-
-    struct __osinfoOsLink *osLink = NULL;
-    osLink = g_new0(struct __osinfoOsLink, 1);
-
-    osLink->subjectOs = self;
-    osLink->verb = rel;
-
-    int ret;
-    ret = __osinfoAddOsRelationshipByOs(self, otherOsId, rel, osLink);
-    if (ret != 0)
-        goto error_free;
-
-    ret = __osinfoAddOsRelationshipByType(self, rel, osLink);
-    if (ret != 0)
-        goto error_cleanup;
-
-    return ret;
-
-error_cleanup:
-    __osinfoRemoveOsLink(self, otherOsId, rel, osLink);
-error_free:
-    g_free(osLink);
-    return ret;
-}
-
-
 OsinfoDevice *osinfo_os_get_preferred_device(OsinfoOs *self, OsinfoHypervisor *hv, gchar *devType, OsinfoFilter *filter,
 					     const gchar **driver)
 {
@@ -211,16 +111,15 @@ OsinfoOsList *osinfo_os_get_related(OsinfoOs *self, osinfoRelationship relshp)
 
     // Create our list
     OsinfoOsList *newList = osinfo_oslist_new();
+    GList *tmp = self->priv->osLinks;
+
+    while (tmp) {
+        struct __osinfoOsLink *link = tmp->data;
+
+	if (link->relshp == relshp)
+	    osinfo_list_add(OSINFO_LIST(newList), OSINFO_ENTITY(link->otherOs));
 
-    GPtrArray *relatedOses = NULL;
-    relatedOses = g_tree_lookup(self->priv->relationshipsByType, (gpointer) relshp);
-    if (relatedOses) {
-        int i, len;
-        len = relatedOses->len;
-        for (i = 0; i < len; i++) {
-            struct __osinfoOsLink *osLink = g_ptr_array_index(relatedOses, i);
-            osinfo_list_add(OSINFO_LIST (newList), OSINFO_ENTITY (osLink->directObjectOs));
-        }
+        tmp = tmp->next;
     }
 
     return newList;
@@ -279,3 +178,17 @@ void osinfo_os_add_device(OsinfoOs *self, OsinfoHypervisor *hv, OsinfoDevice *de
     }
 }
 
+
+void osinfo_os_add_related_os(OsinfoOs *self, osinfoRelationship relshp, OsinfoOs *otheros)
+{
+    g_return_if_fail(OSINFO_IS_OS(self));
+    g_return_if_fail(OSINFO_IS_OS(otheros));
+
+    struct __osinfoOsLink *osLink = g_new0(struct __osinfoOsLink, 1);
+
+    g_object_ref(otheros);
+    osLink->otherOs = otheros;
+    osLink->relshp = relshp;
+
+    self->priv->osLinks = g_list_prepend(self->priv->osLinks, osLink);
+}
diff --git a/osinfo/osinfo_os.h b/osinfo/osinfo_os.h
index 033bdf4..7cc3e6c 100644
--- a/osinfo/osinfo_os.h
+++ b/osinfo/osinfo_os.h
@@ -60,4 +60,6 @@ OsinfoDeviceList *osinfo_os_get_devices(OsinfoOs *self, OsinfoHypervisor *hv, Os
 
 void osinfo_os_add_device(OsinfoOs *self, OsinfoHypervisor *hv, OsinfoDevice *dev, const gchar *driver);
 
+void osinfo_os_add_related_os(OsinfoOs *self, osinfoRelationship relshp, OsinfoOs *otheros);
+
 #endif /* __OSINFO_OS_H__ */
-- 
1.7.2.1




More information about the virt-tools-list mailing list