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(a)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