[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[libvirt] [PATCHv2 2/8] Add event callbacks to libxl driver



---
 src/libxl/libxl_conf.h   |    8 ++-
 src/libxl/libxl_driver.c |  194 +++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 197 insertions(+), 5 deletions(-)

diff --git a/src/libxl/libxl_conf.h b/src/libxl/libxl_conf.h
index bb49d35..a86df9a 100644
--- a/src/libxl/libxl_conf.h
+++ b/src/libxl/libxl_conf.h
@@ -26,6 +26,7 @@
 
 # include "internal.h"
 # include "domain_conf.h"
+# include "domain_event.h"
 # include "capabilities.h"
 # include "configmake.h"
 # include "bitmap.h"
@@ -57,6 +58,12 @@ struct _libxlDriverPrivate {
     virBitmapPtr reservedVNCPorts;
     virDomainObjList domains;
 
+    /* A list of callbacks */
+    virDomainEventCallbackListPtr domainEventCallbacks;
+    virDomainEventQueuePtr domainEventQueue;
+    int domainEventTimer;
+    int domainEventDispatching;
+
     char *configDir;
     char *autostartDir;
     char *logDir;
@@ -87,5 +94,4 @@ int
 libxlBuildDomainConfig(libxlDriverPrivatePtr driver,
                        virDomainDefPtr def, libxl_domain_config *d_config);
 
-
 #endif /* LIBXL_CONF_H */
diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c
index 80a43a0..64f1505 100644
--- a/src/libxl/libxl_driver.c
+++ b/src/libxl/libxl_driver.c
@@ -99,6 +99,58 @@ libxlDomainObjPrivateFree(void *data)
     VIR_FREE(priv);
 }
 
+static void
+libxlDomainEventDispatchFunc(virConnectPtr conn, virDomainEventPtr event,
+                             virConnectDomainEventGenericCallback cb,
+                             void *cbopaque, void *opaque)
+{
+    libxlDriverPrivatePtr driver = opaque;
+
+    /* Drop the lock whle dispatching, for sake of re-entrancy */
+    libxlDriverUnlock(driver);
+    virDomainEventDispatchDefaultFunc(conn, event, cb, cbopaque, NULL);
+    libxlDriverLock(driver);
+}
+
+static void
+libxlDomainEventFlush(int timer ATTRIBUTE_UNUSED, void *opaque)
+{
+    libxlDriverPrivatePtr driver = opaque;
+    virDomainEventQueue tempQueue;
+
+    libxlDriverLock(driver);
+
+    driver->domainEventDispatching = 1;
+
+    /* Copy the queue, so we're reentrant safe */
+    tempQueue.count = driver->domainEventQueue->count;
+    tempQueue.events = driver->domainEventQueue->events;
+    driver->domainEventQueue->count = 0;
+    driver->domainEventQueue->events = NULL;
+
+    virEventUpdateTimeout(driver->domainEventTimer, -1);
+    virDomainEventQueueDispatch(&tempQueue,
+                                driver->domainEventCallbacks,
+                                libxlDomainEventDispatchFunc,
+                                driver);
+
+    /* Purge any deleted callbacks */
+    virDomainEventCallbackListPurgeMarked(driver->domainEventCallbacks);
+
+    driver->domainEventDispatching = 0;
+    libxlDriverUnlock(driver);
+}
+
+/* driver must be locked before calling */
+static void
+libxlDomainEventQueue(libxlDriverPrivatePtr driver, virDomainEventPtr event)
+{
+    if (virDomainEventQueuePush(driver->domainEventQueue, event) < 0)
+        virDomainEventFree(event);
+    if (driver->domainEventQueue->count == 1)
+        virEventUpdateTimeout(driver->domainEventTimer, 0);
+}
+
 /*
  * Remove reference to domain object.
  */
@@ -187,6 +239,7 @@ static void libxlEventHandler(int watch,
     libxlDriverPrivatePtr driver = libxl_driver;
     virDomainObjPtr vm = data;
     libxlDomainObjPrivatePtr priv;
+    virDomainEventPtr dom_event = NULL;
     libxl_event event;
     libxl_dominfo info;
 
@@ -225,6 +278,10 @@ static void libxlEventHandler(int watch,
         switch (info.shutdown_reason) {
             case SHUTDOWN_poweroff:
             case SHUTDOWN_crash:
+                if (info.shutdown_reason == SHUTDOWN_crash)
+                    dom_event = virDomainEventNewFromObj(vm,
+                                              VIR_DOMAIN_EVENT_STOPPED,
+                                              VIR_DOMAIN_EVENT_STOPPED_CRASHED);
                 libxlVmReap(driver, vm, 0);
                 if (!vm->persistent) {
                     virDomainRemoveInactive(&driver->domains, vm);
@@ -244,6 +301,11 @@ static void libxlEventHandler(int watch,
 cleanup:
     if (vm)
         virDomainObjUnlock(vm);
+    if (dom_event) {
+        libxlDriverLock(driver);
+        libxlDomainEventQueue(driver, dom_event);
+        libxlDriverUnlock(driver);
+    }
     libxl_free_event(&event);
 }
 
@@ -303,6 +365,7 @@ libxlVmStart(libxlDriverPrivatePtr driver,
 {
     libxl_domain_config d_config;
     virDomainDefPtr def = vm->def;
+    virDomainEventPtr event = NULL;
     int ret;
     uint32_t domid = 0;
     char *dom_xml = NULL;
@@ -347,9 +410,14 @@ libxlVmStart(libxlDriverPrivatePtr driver,
         vm->state = VIR_DOMAIN_PAUSED;
     }
 
+
     if (virDomainSaveStatus(driver->caps, driver->stateDir, vm) < 0)
         goto error;
 
+    event = virDomainEventNewFromObj(vm, VIR_DOMAIN_EVENT_STARTED,
+                                     VIR_DOMAIN_EVENT_STARTED_BOOTED);
+    libxlDomainEventQueue(driver, event);
+
     libxl_domain_config_destroy(&d_config);
     VIR_FREE(dom_xml);
     return 0;
@@ -447,6 +515,13 @@ libxlShutdown(void)
     VIR_FREE(libxl_driver->libDir);
     VIR_FREE(libxl_driver->saveDir);
 
+    /* Free domain callback list */
+    virDomainEventCallbackListFree(libxl_driver->domainEventCallbacks);
+    virDomainEventQueueFree(libxl_driver->domainEventQueue);
+
+    if (libxl_driver->domainEventTimer != -1)
+        virEventRemoveTimeout(libxl_driver->domainEventTimer);
+
     libxlDriverUnlock(libxl_driver);
     virMutexDestroy(&libxl_driver->lock);
     VIR_FREE(libxl_driver);
@@ -556,6 +631,16 @@ libxlStartup(int privileged) {
     }
     VIR_FREE(log_file);
 
+    /* Init callback list */
+    if (VIR_ALLOC(libxl_driver->domainEventCallbacks) < 0)
+        goto out_of_memory;
+    if (!(libxl_driver->domainEventQueue = virDomainEventQueueNew()))
+        goto out_of_memory;
+    if ((libxl_driver->domainEventTimer =
+         virEventAddTimeout(-1, libxlDomainEventFlush, libxl_driver, NULL)) < 0)
+        goto error;
+
+
     libxl_driver->logger =
             (xentoollog_logger *)xtl_createlogger_stdiostream(libxl_driver->logger_file, XTL_DEBUG,  0);
     if (!libxl_driver->logger) {
@@ -698,6 +783,11 @@ libxlOpen(virConnectPtr conn,
 static int
 libxlClose(virConnectPtr conn ATTRIBUTE_UNUSED)
 {
+    libxlDriverPrivatePtr driver = conn->privateData;
+
+    libxlDriverLock(driver);
+    virDomainEventCallbackListRemoveConn(conn, driver->domainEventCallbacks);
+    libxlDriverUnlock(driver);
     conn->privateData = NULL;
     return 0;
 }
@@ -1026,6 +1116,7 @@ libxlDomainDestroy(virDomainPtr dom)
     virDomainObjPtr vm;
     int ret = -1;
     libxlDomainObjPrivatePtr priv;
+    virDomainEventPtr event = NULL;
 
     libxlDriverLock(driver);
     vm = virDomainFindByUUID(&driver->domains, dom->uuid);
@@ -1043,6 +1134,9 @@ libxlDomainDestroy(virDomainPtr dom)
         goto cleanup;
     }
 
+    event = virDomainEventNewFromObj(vm,VIR_DOMAIN_EVENT_STOPPED,
+                                     VIR_DOMAIN_EVENT_STOPPED_DESTROYED);
+
     priv = vm->privateData;
     if (libxlVmReap(driver, vm, 1) != 0) {
         libxlError(VIR_ERR_INTERNAL_ERROR,
@@ -1060,6 +1154,8 @@ libxlDomainDestroy(virDomainPtr dom)
 cleanup:
     if (vm)
         virDomainObjUnlock(vm);
+    if (event)
+        libxlDomainEventQueue(driver, event);
     libxlDriverUnlock(driver);
     return ret;
 }
@@ -1308,6 +1404,7 @@ libxlDomainDefineXML(virConnectPtr conn, const char *xml)
     virDomainDefPtr def = NULL;
     virDomainObjPtr vm = NULL;
     virDomainPtr dom = NULL;
+    virDomainEventPtr event = NULL;
     int dupVM;
 
     libxlDriverLock(driver);
@@ -1335,10 +1432,17 @@ libxlDomainDefineXML(virConnectPtr conn, const char *xml)
     if (dom)
         dom->id = vm->def->id;
 
+    event = virDomainEventNewFromObj(vm, VIR_DOMAIN_EVENT_DEFINED,
+                                     !dupVM ?
+                                     VIR_DOMAIN_EVENT_DEFINED_ADDED :
+                                     VIR_DOMAIN_EVENT_DEFINED_UPDATED);
+
 cleanup:
     virDomainDefFree(def);
     if (vm)
         virDomainObjUnlock(vm);
+    if (event)
+        libxlDomainEventQueue(driver, event);
     libxlDriverUnlock(driver);
     return dom;
 }
@@ -1348,6 +1452,7 @@ libxlDomainUndefine(virDomainPtr dom)
 {
     libxlDriverPrivatePtr driver = dom->conn->privateData;
     virDomainObjPtr vm;
+    virDomainEventPtr event = NULL;
     int ret = -1;
 
     libxlDriverLock(driver);
@@ -1379,6 +1484,9 @@ libxlDomainUndefine(virDomainPtr dom)
                               vm) < 0)
         goto cleanup;
 
+    event = virDomainEventNewFromObj(vm, VIR_DOMAIN_EVENT_UNDEFINED,
+                                     VIR_DOMAIN_EVENT_UNDEFINED_REMOVED);
+
     virDomainRemoveInactive(&driver->domains, vm);
     vm = NULL;
     ret = 0;
@@ -1386,6 +1494,8 @@ libxlDomainUndefine(virDomainPtr dom)
   cleanup:
     if (vm)
         virDomainObjUnlock(vm);
+    if (event)
+        libxlDomainEventQueue(driver, event);
     libxlDriverUnlock(driver);
     return ret;
 }
@@ -1411,6 +1521,44 @@ libxlNodeGetFreeMemory(virConnectPtr conn)
 }
 
 static int
+libxlDomainEventRegister(virConnectPtr conn,
+                         virConnectDomainEventCallback callback, void *opaque,
+                         virFreeCallback freecb)
+{
+    libxlDriverPrivatePtr driver = conn->privateData;
+    int ret;
+
+    libxlDriverLock(driver);
+    ret = virDomainEventCallbackListAdd(conn, driver->domainEventCallbacks,
+                                        callback, opaque, freecb);
+    libxlDriverUnlock(driver);
+
+    return ret;
+}
+
+
+static int
+libxlDomainEventDeregister(virConnectPtr conn,
+                          virConnectDomainEventCallback callback)
+{
+    libxlDriverPrivatePtr driver = conn->privateData;
+    int ret;
+
+    libxlDriverLock(driver);
+    if (driver->domainEventDispatching)
+        ret = virDomainEventCallbackListMarkDelete(conn,
+                                                   driver->domainEventCallbacks,
+                                                   callback);
+    else
+        ret = virDomainEventCallbackListRemove(conn,
+                                               driver->domainEventCallbacks,
+                                               callback);
+    libxlDriverUnlock(driver);
+
+    return ret;
+}
+
+static int
 libxlDomainIsActive(virDomainPtr dom)
 {
     libxlDriverPrivatePtr driver = dom->conn->privateData;
@@ -1454,6 +1602,44 @@ libxlDomainIsPersistent(virDomainPtr dom)
     return ret;
 }
 
+static int
+libxlDomainEventRegisterAny(virConnectPtr conn, virDomainPtr dom, int eventID,
+                            virConnectDomainEventGenericCallback callback,
+                            void *opaque, virFreeCallback freecb)
+{
+    libxlDriverPrivatePtr driver = conn->privateData;
+    int ret;
+
+    libxlDriverLock(driver);
+    ret = virDomainEventCallbackListAddID(conn, driver->domainEventCallbacks,
+                                          dom, eventID, callback, opaque,
+                                          freecb);
+    libxlDriverUnlock(driver);
+
+    return ret;
+}
+
+
+static int
+libxlDomainEventDeregisterAny(virConnectPtr conn, int callbackID)
+{
+    libxlDriverPrivatePtr driver = conn->privateData;
+    int ret;
+
+    libxlDriverLock(driver);
+    if (driver->domainEventDispatching)
+        ret = virDomainEventCallbackListMarkDeleteID(conn,
+                                                     driver->domainEventCallbacks,
+                                                     callbackID);
+    else
+        ret = virDomainEventCallbackListRemoveID(conn,
+                                                 driver->domainEventCallbacks,
+                                                 callbackID);
+    libxlDriverUnlock(driver);
+
+    return ret;
+}
+
 
 static virDriver libxlDriver = {
     VIR_DRV_LIBXL,
@@ -1531,8 +1717,8 @@ static virDriver libxlDriver = {
     NULL,                       /* domainGetBlockInfo */
     NULL,                       /* nodeGetCellsFreeMemory */
     libxlNodeGetFreeMemory,     /* getFreeMemory */
-    NULL,                       /* domainEventRegister */
-    NULL,                       /* domainEventDeregister */
+    libxlDomainEventRegister,   /* domainEventRegister */
+    libxlDomainEventDeregister, /* domainEventDeregister */
     NULL,                       /* domainMigratePrepare2 */
     NULL,                       /* domainMigrateFinish2 */
     NULL,                       /* nodeDeviceDettach */
@@ -1550,8 +1736,8 @@ static virDriver libxlDriver = {
     NULL,                       /* domainAbortJob */
     NULL,                       /* domainMigrateSetMaxDowntime */
     NULL,                       /* domainMigrateSetMaxSpeed */
-    NULL,                       /* domainEventRegisterAny */
-    NULL,                       /* domainEventDeregisterAny */
+    libxlDomainEventRegisterAny,/* domainEventRegisterAny */
+    libxlDomainEventDeregisterAny,/* domainEventDeregisterAny */
     NULL,                       /* domainManagedSave */
     NULL,                       /* domainHasManagedSaveImage */
     NULL,                       /* domainManagedSaveRemove */
-- 
1.7.4.1


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]