]> xenbits.xensource.com Git - libvirt.git/commitdiff
Allow for multi-level inheritance of virObject classes
authorDaniel P. Berrange <berrange@redhat.com>
Wed, 9 Jan 2013 17:37:27 +0000 (17:37 +0000)
committerDaniel P. Berrange <berrange@redhat.com>
Tue, 15 Jan 2013 19:21:31 +0000 (19:21 +0000)
Currently all classes must directly inherit from virObject.
This allows for arbitrarily deep hierarchy. There's not much
to this aside from chaining up the 'dispose' handlers from
each class & providing APIs to check types.

Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
23 files changed:
po/POTFILES.in
src/conf/domain_conf.c
src/datatypes.c
src/libvirt_private.syms
src/lxc/lxc_monitor.c
src/qemu/qemu_agent.c
src/qemu/qemu_capabilities.c
src/qemu/qemu_monitor.c
src/rpc/virkeepalive.c
src/rpc/virnetclient.c
src/rpc/virnetclientprogram.c
src/rpc/virnetclientstream.c
src/rpc/virnetsaslcontext.c
src/rpc/virnetserver.c
src/rpc/virnetserverclient.c
src/rpc/virnetserverprogram.c
src/rpc/virnetserverservice.c
src/rpc/virnetsocket.c
src/rpc/virnetsshsession.c
src/rpc/virnettlscontext.c
src/util/virdnsmasq.c
src/util/virobject.c
src/util/virobject.h

index 95619f9f053fdc9f201f435eedb3b88624a3f36c..3ca9b640054dcc1eb99b86d1b9a6ae34a4a8673a 100644 (file)
@@ -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
index 6feded4042bf2e638bfc9d23585ad2e70428e591..8e087625a10a092c4def97073677b41e932c51af 100644 (file)
@@ -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;
index 068233c616d2cd6e9de63f9ed9064ba52c900ae5..b04e10055e59bf95cda009e7139b6d69350f1b34 100644 (file)
@@ -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;
index 7be58eed9da8d9eb550d86dcd49e7696e0216ccd..70c1591074495e856a9f66dabc52ef281922517e 100644 (file)
@@ -1769,6 +1769,8 @@ virNodeSuspendGetTargetMask;
 
 
 # virobject.h
+virClassForObject;
+virClassIsDerivedFrom;
 virClassName;
 virClassNew;
 virObjectFreeCallback;
index 6971bcbaedacc9cd287e3bd1d30ab0ab847b09e3..f697e09ab92ef0e6e4aec092beae47dcc5da0964 100644 (file)
@@ -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;
index bb421bd903134ec91384094527362bdf2ba4874b..db4a0bc2fa2c5c2ca9b5c1c8468ae6a1e511ce11 100644 (file)
@@ -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;
index b166dd66b11ea50e1c73bed7a8b68f51e4458b0f..0e9ec9944a750babea9eba65420cdea7da124ab9 100644 (file)
@@ -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;
index cb5a3e2838c53c271da322cc46c276a5056816e8..d6176c7c5627988a61a33abcf17d97cade1e1a05 100644 (file)
@@ -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;
index a8ceff52fa2bfc33486a4aa6739a3fd5b152dfc3..04962d4fc0ce974670779e176ab0388cfa059b20 100644 (file)
@@ -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;
index 69c44781672b4f6284414e1781897742b556f30b..8305c61f2e8f22f27f893185c659a25279b37c9b 100644 (file)
@@ -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;
index 9410cffaf2a380c6a2c9a1680172448386e2c21e..2e6e4f6422fbb5400e932d75fa084d76998d159f 100644 (file)
@@ -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;
index 15ed91aac8fc912c8b54b6bc837d2f8585523205..e1ee30eb67370d5ee945575b55af2a4e8fcb6229 100644 (file)
@@ -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;
index cbf7261a2f65d6ffc80f522c245cd4a8ccf2831e..41a69d12c5c70f56fdbe0fff1571e1739b9fe5d7 100644 (file)
@@ -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;
index a937eda720695f849c91fb1db4ba2dfd9ea2e2dd..73abb91cf8989636fe4b4dddfc893c8f5034655b 100644 (file)
@@ -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;
index bd4e66fd7db958af29c8a3dc23ac46c414e41857..2ba3a6daa2a7702cb2a068cc38788a76d6a2a117 100644 (file)
@@ -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;
index 06b6325de68e6cb6c4faeb4dd2372c4a4b9d2785..414b9788989c0dbb1afc18f0000bc2c7f282f5ea 100644 (file)
@@ -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;
index 2e024e1d08a7c85d269a4effc425f5714d5baafe..2915355630d6579015b7f58a96aa09ba29ddc40b 100644 (file)
@@ -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;
index c31d383d0b0c18ef3c4061f8b536a110a7a4077e..1708d1cd8444a3955552bd90b0f7886f6f4c618a 100644 (file)
@@ -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;
index 661860f13f047d17b48d4808ff6c8e8967e3fb53..ca7d52e9622b2bc686d1649705e8c11ded826ad9 100644 (file)
@@ -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;
index 56e372b3b5b49e14c3157788990e31ebdeb93215..3e194f9fb5d905aa5fe52907bea7106ace22ec0d 100644 (file)
@@ -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;
index 2d0f02ce3a602d3b2084b0b7b96894b2d45125d2..6637a8977debd5224a83e32dbbefa03fc5c0c8a7 100644 (file)
@@ -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;
index f51b73570e39f82114d4612461781bc21f224902..5f44ab2d6d5b6632d61d641ae02d7ce18a482a1c 100644 (file)
@@ -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);
 }
 
 
index b2f761206b28b088086bb13be23e92c42a5fbb60..afeb4f56266bb2eed7eea7bb5801e05a532a7c51 100644 (file)
@@ -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);