From: "Daniel P. Berrange" <berrange(a)redhat.com>
Currently all classes must directly inherit from virObject.
This allows for arbitrarily deep hierarchy. There's not much
too this aside from chaining up the 'dispose' handlers from
each class & providing APIs to check types.
---
src/conf/domain_conf.c | 3 +-
src/datatypes.c | 3 +-
src/libvirt_private.syms | 2 ++
src/lxc/lxc_monitor.c | 3 +-
src/qemu/qemu_agent.c | 3 +-
src/qemu/qemu_capabilities.c | 3 +-
src/qemu/qemu_monitor.c | 7 ++--
src/rpc/virkeepalive.c | 3 +-
src/rpc/virnetclient.c | 3 +-
src/rpc/virnetclientprogram.c | 3 +-
src/rpc/virnetclientstream.c | 3 +-
src/rpc/virnetsaslcontext.c | 6 ++--
src/rpc/virnetserver.c | 3 +-
src/rpc/virnetserverclient.c | 3 +-
src/rpc/virnetserverprogram.c | 3 +-
src/rpc/virnetserverservice.c | 3 +-
src/rpc/virnetsocket.c | 3 +-
src/rpc/virnetsshsession.c | 3 +-
src/rpc/virnettlscontext.c | 6 ++--
src/util/virdnsmasq.c | 3 +-
src/util/virobject.c | 84 ++++++++++++++++++++++++++++++++++++++++---
src/util/virobject.h | 9 ++++-
22 files changed, 134 insertions(+), 28 deletions(-)
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index b3a35b7..38dc334 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -695,7 +695,8 @@ static void virDomainObjDispose(void *obj);
static int virDomainObjOnceInit(void)
{
- if (!(virDomainObjClass = virClassNew("virDomainObj",
+ if (!(virDomainObjClass = virClassNew(virClassForObject(),
+ "virDomainObj",
sizeof(virDomainObj),
virDomainObjDispose)))
return -1;
diff --git a/src/datatypes.c b/src/datatypes.c
index 068233c..b04e100 100644
--- a/src/datatypes.c
+++ b/src/datatypes.c
@@ -64,7 +64,8 @@ static int
virDataTypesOnceInit(void)
{
#define DECLARE_CLASS(basename) \
- if (!(basename ## Class = virClassNew(#basename, \
+ if (!(basename ## Class = virClassNew(virClassForObject(), \
+ #basename, \
sizeof(basename), \
basename ## Dispose))) \
return -1;
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index d079cc9..092cb59 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1767,6 +1767,8 @@ virNodeSuspendGetTargetMask;
# virobject.h
+virClassForObject;
+virClassIsDerivedFrom;
virClassName;
virClassNew;
virObjectFreeCallback;
diff --git a/src/lxc/lxc_monitor.c b/src/lxc/lxc_monitor.c
index 6971bcb..f697e09 100644
--- a/src/lxc/lxc_monitor.c
+++ b/src/lxc/lxc_monitor.c
@@ -50,7 +50,8 @@ static void virLXCMonitorDispose(void *obj);
static int virLXCMonitorOnceInit(void)
{
- if (!(virLXCMonitorClass = virClassNew("virLXCMonitor",
+ if (!(virLXCMonitorClass = virClassNew(virClassForObject(),
+ "virLXCMonitor",
sizeof(virLXCMonitor),
virLXCMonitorDispose)))
return -1;
diff --git a/src/qemu/qemu_agent.c b/src/qemu/qemu_agent.c
index bb421bd..db4a0bc 100644
--- a/src/qemu/qemu_agent.c
+++ b/src/qemu/qemu_agent.c
@@ -121,7 +121,8 @@ static void qemuAgentDispose(void *obj);
static int qemuAgentOnceInit(void)
{
- if (!(qemuAgentClass = virClassNew("qemuAgent",
+ if (!(qemuAgentClass = virClassNew(virClassForObject(),
+ "qemuAgent",
sizeof(qemuAgent),
qemuAgentDispose)))
return -1;
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
index 320d8c8..29b5066 100644
--- a/src/qemu/qemu_capabilities.c
+++ b/src/qemu/qemu_capabilities.c
@@ -241,7 +241,8 @@ static void qemuCapsDispose(void *obj);
static int qemuCapsOnceInit(void)
{
- if (!(qemuCapsClass = virClassNew("qemuCaps",
+ if (!(qemuCapsClass = virClassNew(virClassForObject(),
+ "qemuCaps",
sizeof(qemuCaps),
qemuCapsDispose)))
return -1;
diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
index cb5a3e2..d6176c7 100644
--- a/src/qemu/qemu_monitor.c
+++ b/src/qemu/qemu_monitor.c
@@ -86,9 +86,10 @@ static void qemuMonitorDispose(void *obj);
static int qemuMonitorOnceInit(void)
{
- if (!(qemuMonitorClass = virClassNew("qemuMonitor",
- sizeof(qemuMonitor),
- qemuMonitorDispose)))
+ if (!(qemuMonitorClass = virClassNew(virClassForObject(),
+ "qemuMonitor",
+ sizeof(qemuMonitor),
+ qemuMonitorDispose)))
return -1;
return 0;
diff --git a/src/rpc/virkeepalive.c b/src/rpc/virkeepalive.c
index a8ceff5..04962d4 100644
--- a/src/rpc/virkeepalive.c
+++ b/src/rpc/virkeepalive.c
@@ -58,7 +58,8 @@ static void virKeepAliveDispose(void *obj);
static int virKeepAliveOnceInit(void)
{
- if (!(virKeepAliveClass = virClassNew("virKeepAlive",
+ if (!(virKeepAliveClass = virClassNew(virClassForObject(),
+ "virKeepAlive",
sizeof(virKeepAlive),
virKeepAliveDispose)))
return -1;
diff --git a/src/rpc/virnetclient.c b/src/rpc/virnetclient.c
index a79b79b..f281548 100644
--- a/src/rpc/virnetclient.c
+++ b/src/rpc/virnetclient.c
@@ -117,7 +117,8 @@ static void virNetClientDispose(void *obj);
static int virNetClientOnceInit(void)
{
- if (!(virNetClientClass = virClassNew("virNetClient",
+ if (!(virNetClientClass = virClassNew(virClassForObject(),
+ "virNetClient",
sizeof(virNetClient),
virNetClientDispose)))
return -1;
diff --git a/src/rpc/virnetclientprogram.c b/src/rpc/virnetclientprogram.c
index 9410cff..2e6e4f6 100644
--- a/src/rpc/virnetclientprogram.c
+++ b/src/rpc/virnetclientprogram.c
@@ -52,7 +52,8 @@ static void virNetClientProgramDispose(void *obj);
static int virNetClientProgramOnceInit(void)
{
- if (!(virNetClientProgramClass = virClassNew("virNetClientProgram",
+ if (!(virNetClientProgramClass = virClassNew(virClassForObject(),
+ "virNetClientProgram",
sizeof(virNetClientProgram),
virNetClientProgramDispose)))
return -1;
diff --git a/src/rpc/virnetclientstream.c b/src/rpc/virnetclientstream.c
index 15ed91a..e1ee30e 100644
--- a/src/rpc/virnetclientstream.c
+++ b/src/rpc/virnetclientstream.c
@@ -68,7 +68,8 @@ static void virNetClientStreamDispose(void *obj);
static int virNetClientStreamOnceInit(void)
{
- if (!(virNetClientStreamClass = virClassNew("virNetClientStream",
+ if (!(virNetClientStreamClass = virClassNew(virClassForObject(),
+ "virNetClientStream",
sizeof(virNetClientStream),
virNetClientStreamDispose)))
return -1;
diff --git a/src/rpc/virnetsaslcontext.c b/src/rpc/virnetsaslcontext.c
index cbf7261..41a69d1 100644
--- a/src/rpc/virnetsaslcontext.c
+++ b/src/rpc/virnetsaslcontext.c
@@ -55,12 +55,14 @@ static void virNetSASLSessionDispose(void *obj);
static int virNetSASLContextOnceInit(void)
{
- if (!(virNetSASLContextClass = virClassNew("virNetSASLContext",
+ if (!(virNetSASLContextClass = virClassNew(virClassForObject(),
+ "virNetSASLContext",
sizeof(virNetSASLContext),
virNetSASLContextDispose)))
return -1;
- if (!(virNetSASLSessionClass = virClassNew("virNetSASLSession",
+ if (!(virNetSASLSessionClass = virClassNew(virClassForObject(),
+ "virNetSASLSession",
sizeof(virNetSASLSession),
virNetSASLSessionDispose)))
return -1;
diff --git a/src/rpc/virnetserver.c b/src/rpc/virnetserver.c
index b9df71b..03efbb8 100644
--- a/src/rpc/virnetserver.c
+++ b/src/rpc/virnetserver.c
@@ -119,7 +119,8 @@ static void virNetServerDispose(void *obj);
static int virNetServerOnceInit(void)
{
- if (!(virNetServerClass = virClassNew("virNetServer",
+ if (!(virNetServerClass = virClassNew(virClassForObject(),
+ "virNetServer",
sizeof(virNetServer),
virNetServerDispose)))
return -1;
diff --git a/src/rpc/virnetserverclient.c b/src/rpc/virnetserverclient.c
index bf23d24..ce8bd6d 100644
--- a/src/rpc/virnetserverclient.c
+++ b/src/rpc/virnetserverclient.c
@@ -112,7 +112,8 @@ static void virNetServerClientDispose(void *obj);
static int virNetServerClientOnceInit(void)
{
- if (!(virNetServerClientClass = virClassNew("virNetServerClient",
+ if (!(virNetServerClientClass = virClassNew(virClassForObject(),
+ "virNetServerClient",
sizeof(virNetServerClient),
virNetServerClientDispose)))
return -1;
diff --git a/src/rpc/virnetserverprogram.c b/src/rpc/virnetserverprogram.c
index 06b6325..414b978 100644
--- a/src/rpc/virnetserverprogram.c
+++ b/src/rpc/virnetserverprogram.c
@@ -49,7 +49,8 @@ static void virNetServerProgramDispose(void *obj);
static int virNetServerProgramOnceInit(void)
{
- if (!(virNetServerProgramClass = virClassNew("virNetServerProgram",
+ if (!(virNetServerProgramClass = virClassNew(virClassForObject(),
+ "virNetServerProgram",
sizeof(virNetServerProgram),
virNetServerProgramDispose)))
return -1;
diff --git a/src/rpc/virnetserverservice.c b/src/rpc/virnetserverservice.c
index 61dd682..05fe41b 100644
--- a/src/rpc/virnetserverservice.c
+++ b/src/rpc/virnetserverservice.c
@@ -55,7 +55,8 @@ static void virNetServerServiceDispose(void *obj);
static int virNetServerServiceOnceInit(void)
{
- if (!(virNetServerServiceClass = virClassNew("virNetServerService",
+ if (!(virNetServerServiceClass = virClassNew(virClassForObject(),
+ "virNetServerService",
sizeof(virNetServerService),
virNetServerServiceDispose)))
return -1;
diff --git a/src/rpc/virnetsocket.c b/src/rpc/virnetsocket.c
index a817999..f96b47c 100644
--- a/src/rpc/virnetsocket.c
+++ b/src/rpc/virnetsocket.c
@@ -104,7 +104,8 @@ static void virNetSocketDispose(void *obj);
static int virNetSocketOnceInit(void)
{
- if (!(virNetSocketClass = virClassNew("virNetSocket",
+ if (!(virNetSocketClass = virClassNew(virClassForObject(),
+ "virNetSocket",
sizeof(virNetSocket),
virNetSocketDispose)))
return -1;
diff --git a/src/rpc/virnetsshsession.c b/src/rpc/virnetsshsession.c
index 661860f..ca7d52e 100644
--- a/src/rpc/virnetsshsession.c
+++ b/src/rpc/virnetsshsession.c
@@ -161,7 +161,8 @@ static virClassPtr virNetSSHSessionClass;
static int
virNetSSHSessionOnceInit(void)
{
- if (!(virNetSSHSessionClass = virClassNew("virNetSSHSession",
+ if (!(virNetSSHSessionClass = virClassNew(virClassForObject(),
+ "virNetSSHSession",
sizeof(virNetSSHSession),
virNetSSHSessionDispose)))
return -1;
diff --git a/src/rpc/virnettlscontext.c b/src/rpc/virnettlscontext.c
index 56e372b..3e194f9 100644
--- a/src/rpc/virnettlscontext.c
+++ b/src/rpc/virnettlscontext.c
@@ -85,12 +85,14 @@ static void virNetTLSSessionDispose(void *obj);
static int virNetTLSContextOnceInit(void)
{
- if (!(virNetTLSContextClass = virClassNew("virNetTLSContext",
+ if (!(virNetTLSContextClass = virClassNew(virClassForObject(),
+ "virNetTLSContext",
sizeof(virNetTLSContext),
virNetTLSContextDispose)))
return -1;
- if (!(virNetTLSSessionClass = virClassNew("virNetTLSSession",
+ if (!(virNetTLSSessionClass = virClassNew(virClassForObject(),
+ "virNetTLSSession",
sizeof(virNetTLSSession),
virNetTLSSessionDispose)))
return -1;
diff --git a/src/util/virdnsmasq.c b/src/util/virdnsmasq.c
index 2d0f02c..6637a89 100644
--- a/src/util/virdnsmasq.c
+++ b/src/util/virdnsmasq.c
@@ -628,7 +628,8 @@ dnsmasqCapsDispose(void *obj)
static int dnsmasqCapsOnceInit(void)
{
- if (!(dnsmasqCapsClass = virClassNew("dnsmasqCaps",
+ if (!(dnsmasqCapsClass = virClassNew(virClassForObject(),
+ "dnsmasqCaps",
sizeof(dnsmasqCaps),
dnsmasqCapsDispose))) {
return -1;
diff --git a/src/util/virobject.c b/src/util/virobject.c
index f51b735..5f44ab2 100644
--- a/src/util/virobject.c
+++ b/src/util/virobject.c
@@ -33,6 +33,8 @@
static unsigned int magicCounter = 0xCAFE0000;
struct _virClass {
+ virClassPtr parent;
+
unsigned int magic;
const char *name;
size_t objectSize;
@@ -40,9 +42,39 @@ struct _virClass {
virObjectDisposeCallback dispose;
};
+static virClassPtr virObjectClass;
+
+static int virObjectOnceInit(void)
+{
+ if (!(virObjectClass = virClassNew(NULL,
+ "virObject",
+ sizeof(virObject),
+ NULL)))
+ return -1;
+
+ return 0;
+}
+
+VIR_ONCE_GLOBAL_INIT(virObject);
+
+
+/**
+ * virClassForObject:
+ *
+ * Returns the class instance for the base virObject type
+ */
+virClassPtr virClassForObject(void)
+{
+ if (!virObjectInitialize() < 0)
+ return NULL;
+
+ return virObjectClass;
+}
+
/**
* virClassNew:
+ * @parent: the parent class
* @name: the class name
* @objectSize: total size of the object struct
* @dispose: callback to run to free object fields
@@ -56,15 +88,29 @@ struct _virClass {
*
* Returns a new class instance
*/
-virClassPtr virClassNew(const char *name,
+virClassPtr virClassNew(virClassPtr parent,
+ const char *name,
size_t objectSize,
virObjectDisposeCallback dispose)
{
virClassPtr klass;
+ if (parent == NULL &&
+ STRNEQ(name, "virObject")) {
+ virReportInvalidNonNullArg(parent);
+ return NULL;
+ } else if (parent &&
+ objectSize <= parent->objectSize) {
+ virReportInvalidArg(objectSize,
+ _("object size %zu of %s is smaller than parent class
%zu"),
+ objectSize, name, parent->objectSize);
+ return NULL;
+ }
+
if (VIR_ALLOC(klass) < 0)
goto no_memory;
+ klass->parent = parent;
if (!(klass->name = strdup(name)))
goto no_memory;
klass->magic = virAtomicIntInc(&magicCounter);
@@ -81,6 +127,27 @@ no_memory:
/**
+ * virClassIsDerivedFrom:
+ * @klass: the klass to check
+ * @parent: the possible parent class
+ *
+ * Determine if @klass is derived from @parent
+ *
+ * Return true if @klass is derived from @parent, false otherwise
+ */
+bool virClassIsDerivedFrom(virClassPtr klass,
+ virClassPtr parent)
+{
+ while (klass) {
+ if (klass->magic == parent->magic)
+ return true;
+ klass = klass->parent;
+ }
+ return false;
+}
+
+
+/**
* virObjectNew:
* @klass: the klass of object to create
*
@@ -135,8 +202,14 @@ bool virObjectUnref(void *anyobj)
PROBE(OBJECT_UNREF, "obj=%p", obj);
if (lastRef) {
PROBE(OBJECT_DISPOSE, "obj=%p", obj);
- if (obj->klass->dispose)
- obj->klass->dispose(obj);
+ virClassPtr klass = obj->klass;
+ while (klass) {
+ if (klass->dispose)
+ klass->dispose(obj);
+ klass = klass->parent;
+ }
+
+ virMutexDestroy(&obj->lock);
/* Clear & poison object */
memset(obj, 0, obj->klass->objectSize);
@@ -184,7 +257,10 @@ bool virObjectIsClass(void *anyobj,
virClassPtr klass)
{
virObjectPtr obj = anyobj;
- return obj != NULL && (obj->magic == klass->magic) &&
(obj->klass == klass);
+ if (!obj)
+ return false;
+
+ return virClassIsDerivedFrom(obj->klass, klass);
}
diff --git a/src/util/virobject.h b/src/util/virobject.h
index b2f7612..afeb4f5 100644
--- a/src/util/virobject.h
+++ b/src/util/virobject.h
@@ -38,7 +38,10 @@ struct _virObject {
virClassPtr klass;
};
-virClassPtr virClassNew(const char *name,
+virClassPtr virClassForObject(void);
+
+virClassPtr virClassNew(virClassPtr parent,
+ const char *name,
size_t objectSize,
virObjectDisposeCallback dispose)
ATTRIBUTE_NONNULL(1);
@@ -46,6 +49,10 @@ virClassPtr virClassNew(const char *name,
const char *virClassName(virClassPtr klass)
ATTRIBUTE_NONNULL(1);
+bool virClassIsDerivedFrom(virClassPtr klass,
+ virClassPtr parent)
+ ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
+
void *virObjectNew(virClassPtr klass)
ATTRIBUTE_NONNULL(1);
bool virObjectUnref(void *obj);
--
1.8.0.1