From: "Daniel P. Berrange" <berrange@xxxxxxxxxx> 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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list