[libvirt] [PATCH v4 03/17] util: Introduce virObjectLookupHash

John Ferlan jferlan at redhat.com
Fri Aug 18 21:50:27 UTC 2017


Using the virObjectRWLockable class as the base with the concepts
from virObjectLookupKeys of either 1 or 2 lookup keys possible,
create the virObjectLookupHash to manage a common mechanism to
store objects for driver/vir*obj.c via self locking hash tables
using the RW locking APIs.

Each hash table will have:

    objsKey1 -> Hash table for the LookupKeys->key1

and may also have:

    objsKey2 -> Hash table for the LookupKeys->key2

A secondary benefit of self locking hash tables is each driver then
does not have to keep a higher level driver lock for interactions with
the object storage since the object itself can manage locking as needed.

Signed-off-by: John Ferlan <jferlan at redhat.com>
---
 src/libvirt_private.syms |  2 ++
 src/util/virobject.c     | 83 +++++++++++++++++++++++++++++++++++++++++++++++-
 src/util/virobject.h     | 23 ++++++++++++++
 3 files changed, 107 insertions(+), 1 deletion(-)

diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 082a0ba..66cf865 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -2318,6 +2318,7 @@ virNumaSetupMemoryPolicy;
 # util/virobject.h
 virClassForObject;
 virClassForObjectLockable;
+virClassForObjectLookupHash;
 virClassForObjectLookupKeys;
 virClassForObjectRWLockable;
 virClassIsDerivedFrom;
@@ -2330,6 +2331,7 @@ virObjectListFree;
 virObjectListFreeCount;
 virObjectLock;
 virObjectLockableNew;
+virObjectLookupHashNew;
 virObjectLookupKeysNew;
 virObjectNew;
 virObjectRef;
diff --git a/src/util/virobject.c b/src/util/virobject.c
index aec10eb..f677b5f 100644
--- a/src/util/virobject.c
+++ b/src/util/virobject.c
@@ -69,10 +69,12 @@ static virClassPtr virObjectClass;
 static virClassPtr virObjectLockableClass;
 static virClassPtr virObjectRWLockableClass;
 static virClassPtr virObjectLookupKeysClass;
+static virClassPtr virObjectLookupHashClass;
 
 static void virObjectLockableDispose(void *anyobj);
 static void virObjectRWLockableDispose(void *anyobj);
 static void virObjectLookupKeysDispose(void *anyobj);
+static void virObjectLookupHashDispose(void *anyobj);
 
 static int
 virObjectOnceInit(void)
@@ -101,6 +103,12 @@ virObjectOnceInit(void)
                                                  virObjectLookupKeysDispose)))
         return -1;
 
+    if (!(virObjectLookupHashClass = virClassNew(virObjectRWLockableClass,
+                                                 "virObjectLookupHash",
+                                                 sizeof(virObjectLookupHash),
+                                                 virObjectLookupHashDispose)))
+        return -1;
+
     return 0;
 }
 
@@ -168,6 +176,21 @@ virClassForObjectLookupKeys(void)
 
 
 /**
+ * virClassForObjectLookupHash:
+ *
+ * Returns the class instance for the virObjectLookupHash type
+ */
+virClassPtr
+virClassForObjectLookupHash(void)
+{
+    if (virObjectInitialize() < 0)
+        return NULL;
+
+    return virObjectLookupHashClass;
+}
+
+
+/**
  * virClassNew:
  * @parent: the parent class
  * @name: the class name
@@ -413,6 +436,63 @@ virObjectLookupKeysDispose(void *anyobj)
 
 
 /**
+ * virObjectLookupHashNew:
+ * @klass: the klass to check
+ * @tableElemsStart: initial size of each hash table
+ * @createBoth: boolean to determine how many hash tables to create
+ *
+ * Create a new poolable hash table object for storing either 1 or 2
+ * hash tables capable of storing virObjectLookupKeys objects. This
+ * object will use the RWLockable objects in order to allow for concurrent
+ * table reads by multiple threads looking to return lists of data.
+ *
+ * Returns: New object on success, NULL on failure w/ error message set
+ */
+void *
+virObjectLookupHashNew(virClassPtr klass,
+                       int tableElemsStart,
+                       bool createBoth)
+{
+    virObjectLookupHashPtr obj;
+
+    if (!virClassIsDerivedFrom(klass, virClassForObjectLookupHash())) {
+        virReportInvalidArg(klass,
+                            _("Class %s must derive from virObjectLookupHash"),
+                            virClassName(klass));
+        return NULL;
+    }
+
+    if (!(obj = virObjectRWLockableNew(klass)))
+        return NULL;
+
+    if (!(obj->objsKey1 = virHashCreate(tableElemsStart,
+                                        virObjectFreeHashData)))
+        goto error;
+
+    if (createBoth &&
+        !(obj->objsKey2 = virHashCreate(tableElemsStart,
+                                        virObjectFreeHashData)))
+        goto error;
+
+    return obj;
+
+ error:
+    virObjectUnref(obj);
+    return NULL;
+}
+
+
+static void
+virObjectLookupHashDispose(void *anyobj)
+{
+    virObjectLookupHashPtr obj = anyobj;
+
+    virHashFree(obj->objsKey1);
+    virHashFree(obj->objsKey2);
+}
+
+
+/**
  * virObjectUnref:
  * @anyobj: any instance of virObjectPtr
  *
@@ -490,7 +570,8 @@ virObjectGetLockableObj(void *anyobj)
 static virObjectRWLockablePtr
 virObjectGetRWLockableObj(void *anyobj)
 {
-    if (virObjectIsClass(anyobj, virObjectRWLockableClass))
+    if (virObjectIsClass(anyobj, virObjectRWLockableClass) ||
+        virObjectIsClass(anyobj, virObjectLookupHashClass))
         return anyobj;
 
     VIR_OBJECT_USAGE_PRINT_ERROR(anyobj, virObjectRWLockable);
diff --git a/src/util/virobject.h b/src/util/virobject.h
index 0f7d5ca..a5c03be 100644
--- a/src/util/virobject.h
+++ b/src/util/virobject.h
@@ -23,6 +23,7 @@
 # define __VIR_OBJECT_H__
 
 # include "internal.h"
+# include "virhash.h"
 # include "virthread.h"
 
 typedef struct _virClass virClass;
@@ -40,6 +41,9 @@ typedef virObjectRWLockable *virObjectRWLockablePtr;
 typedef struct _virObjectLookupKeys virObjectLookupKeys;
 typedef virObjectLookupKeys *virObjectLookupKeysPtr;
 
+typedef struct _virObjectLookupHash virObjectLookupHash;
+typedef virObjectLookupHash *virObjectLookupHashPtr;
+
 typedef void (*virObjectDisposeCallback)(void *obj);
 
 /* Most code should not play with the contents of this struct; however,
@@ -77,11 +81,24 @@ struct _virObjectLookupKeys {
     char *key2;
 };
 
+struct _virObjectLookupHash {
+    virObjectRWLockable parent;
+
+    /* key1 string -> object mapping for O(1),
+     * lockless lookup-by-key1 */
+    virHashTable *objsKey1;
+
+    /* key2 string -> object mapping for O(1),
+     * lockless lookup-by-key2 */
+    virHashTable *objsKey2;
+};
+
 
 virClassPtr virClassForObject(void);
 virClassPtr virClassForObjectLockable(void);
 virClassPtr virClassForObjectRWLockable(void);
 virClassPtr virClassForObjectLookupKeys(void);
+virClassPtr virClassForObjectLookupHash(void);
 
 # ifndef VIR_PARENT_REQUIRED
 #  define VIR_PARENT_REQUIRED ATTRIBUTE_NONNULL(1)
@@ -138,6 +155,12 @@ virObjectLookupKeysNew(virClassPtr klass,
                        const char *key2)
     ATTRIBUTE_NONNULL(1);
 
+void *
+virObjectLookupHashNew(virClassPtr klass,
+                       int tableElemsStart,
+                       bool createBoth)
+    ATTRIBUTE_NONNULL(1);
+
 void
 virObjectLock(void *lockableobj)
     ATTRIBUTE_NONNULL(1);
-- 
2.9.4




More information about the libvir-list mailing list