Using the virObjectLockable class as the base and the virObjectLookupKeys
uuid and name from the virObjectLookupKeys, create the virObjectLookupHash
to manage a common mechanism to store objects for a driver via self locking
hash tables.
Each hash table will have :
tableElemsStart -> # of elements to create the initial table
objsUUID -> Hash table for the LookupKeys->UUID
objsName -> Hash table for the LookupKeys->name
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 | 85 +++++++++++++++++++++++++++++++++++++++++++++++-
src/util/virobject.h | 24 ++++++++++++++
3 files changed, 110 insertions(+), 1 deletion(-)
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 6a87e6b..655a8f8 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -2274,6 +2274,7 @@ virNumaSetupMemoryPolicy;
# util/virobject.h
virClassForObject;
virClassForObjectLockable;
+virClassForObjectLookupHash;
virClassForObjectLookupKeys;
virClassIsDerivedFrom;
virClassName;
@@ -2285,6 +2286,7 @@ virObjectListFree;
virObjectListFreeCount;
virObjectLock;
virObjectLockableNew;
+virObjectLookupHashNew;
virObjectLookupKeysGetName;
virObjectLookupKeysGetUUID;
virObjectLookupKeysIsActive;
diff --git a/src/util/virobject.c b/src/util/virobject.c
index 6e2b222..79f1fe9 100644
--- a/src/util/virobject.c
+++ b/src/util/virobject.c
@@ -67,9 +67,11 @@ struct _virClass {
static virClassPtr virObjectClass;
static virClassPtr virObjectLockableClass;
static virClassPtr virObjectLookupKeysClass;
+static virClassPtr virObjectLookupHashClass;
static void virObjectLockableDispose(void *anyobj);
static void virObjectLookupKeysDispose(void *anyobj);
+static void virObjectLookupHashDispose(void *anyobj);
static int
virObjectOnceInit(void)
@@ -92,6 +94,12 @@ virObjectOnceInit(void)
virObjectLookupKeysDispose)))
return -1;
+ if (!(virObjectLookupHashClass = virClassNew(virObjectLockableClass,
+ "virObjectLookupHash",
+ sizeof(virObjectLookupHash),
+ virObjectLookupHashDispose)))
+ return -1;
+
return 0;
}
@@ -144,6 +152,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
@@ -344,6 +367,65 @@ virObjectLookupKeysDispose(void *anyobj)
/**
+ * virObjectLookupHashNew:
+ * @klass: the klass to check
+ * @tableElemsStart: number of elements initially in the table
+ *
+ * Create a new poolable hash table object for storing hash tables capable
+ * of storing virObjectLookupKeys objects.
+ *
+ * Returns: New object on success, NULL on failure w/ error message set
+ */
+void *
+virObjectLookupHashNew(virClassPtr klass,
+ int tableElemsStart)
+{
+ virObjectLookupHashPtr obj;
+
+ if (!virClassIsDerivedFrom(klass, virClassForObjectLookupHash())) {
+ virReportInvalidArg(klass,
+ _("Class %s must derive from
virObjectLookupHash"),
+ virClassName(klass));
+ return NULL;
+ }
+
+ if (!(obj = virObjectLockableNew(klass)))
+ return NULL;
+
+ obj->tableElemsStart = tableElemsStart;
+
+ if (!(obj->objsUUID = virHashCreate(tableElemsStart,
+ virObjectFreeHashData)))
+ goto error;
+
+ if (!(obj->objsName = virHashCreate(tableElemsStart,
+ virObjectFreeHashData)))
+ goto error;
+
+ VIR_DEBUG("obj=%p, elems=%d objsUUID=%p objsName=%p",
+ obj, tableElemsStart, obj->objsUUID, obj->objsName);
+
+ return obj;
+
+ error:
+ virObjectUnref(obj);
+ return NULL;
+}
+
+
+static void
+virObjectLookupHashDispose(void *anyobj)
+{
+ virObjectLookupHashPtr obj = anyobj;
+
+ VIR_DEBUG("dispose obj=%p", obj);
+
+ virHashFree(obj->objsUUID);
+ virHashFree(obj->objsName);
+}
+
+
+/**
* virObjectUnref:
* @anyobj: any instance of virObjectPtr
*
@@ -410,7 +492,8 @@ static virObjectLockablePtr
virObjectGetLockableObj(void *anyobj)
{
if (virObjectIsClass(anyobj, virObjectLockableClass) ||
- virObjectIsClass(anyobj, virObjectLookupKeysClass))
+ virObjectIsClass(anyobj, virObjectLookupKeysClass) ||
+ virObjectIsClass(anyobj, virObjectLookupHashClass))
return anyobj;
VIR_OBJECT_USAGE_PRINT_WARNING(anyobj, virObjectLockableClass);
diff --git a/src/util/virobject.h b/src/util/virobject.h
index 9e0ecc1..3c45182 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;
@@ -37,6 +38,9 @@ typedef virObjectLockable *virObjectLockablePtr;
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,
@@ -71,10 +75,25 @@ struct _virObjectLookupKeys {
bool active; /* true if object is active */
};
+struct _virObjectLookupHash {
+ virObjectLockable parent;
+
+ int tableElemsStart;
+
+ /* uuid string -> object mapping for O(1),
+ * lockless lookup-by-uuid */
+ virHashTable *objsUUID;
+
+ /* name key -> object mapping for O(1),
+ * lockless lookup-by-name */
+ virHashTable *objsName;
+};
+
virClassPtr virClassForObject(void);
virClassPtr virClassForObjectLockable(void);
virClassPtr virClassForObjectLookupKeys(void);
+virClassPtr virClassForObjectLookupHash(void);
# ifndef VIR_PARENT_REQUIRED
# define VIR_PARENT_REQUIRED ATTRIBUTE_NONNULL(1)
@@ -127,6 +146,11 @@ virObjectLookupKeysNew(virClassPtr klass,
const char *name)
ATTRIBUTE_NONNULL(1);
+void *
+virObjectLookupHashNew(virClassPtr klass,
+ int tableElemsStart)
+ ATTRIBUTE_NONNULL(1);
+
void
virObjectLock(void *lockableobj)
ATTRIBUTE_NONNULL(1);
--
2.9.4