diff --git a/po/POTFILES.in b/po/POTFILES.in index 95619f9f05..3ca9b64005 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -165,6 +165,7 @@ src/util/virnetdevtap.c src/util/virnetdevvportprofile.c src/util/virnetlink.c src/util/virnodesuspend.c +src/util/virobject.c src/util/virpci.c src/util/virpidfile.c src/util/virprocess.c diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 6feded4042..8e087625a1 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -700,7 +700,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 068233c616..b04e10055e 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 7be58eed9d..70c1591074 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1769,6 +1769,8 @@ virNodeSuspendGetTargetMask; # virobject.h +virClassForObject; +virClassIsDerivedFrom; virClassName; virClassNew; virObjectFreeCallback; diff --git a/src/lxc/lxc_monitor.c b/src/lxc/lxc_monitor.c index 6971bcbaed..f697e09ab9 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 bb421bd903..db4a0bc2fa 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 b166dd66b1..0e9ec9944a 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -244,7 +244,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 cb5a3e2838..d6176c7c56 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 a8ceff52fa..04962d4fc0 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 69c4478167..8305c61f2e 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 9410cffaf2..2e6e4f6422 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 15ed91aac8..e1ee30eb67 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 cbf7261a2f..41a69d12c5 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 a937eda720..73abb91cf8 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 bd4e66fd7d..2ba3a6daa2 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 06b6325de6..414b978898 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 2e024e1d08..2915355630 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 c31d383d0b..1708d1cd84 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 661860f13f..ca7d52e962 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 56e372b3b5..3e194f9fb5 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 2d0f02ce3a..6637a8977d 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 f51b73570e..5f44ab2d6d 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); @@ -80,6 +126,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 b2f761206b..afeb4f5626 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);