]> xenbits.xensource.com Git - people/liuw/libxenctrl-split/libvirt.git/commitdiff
event: prepare client to track domain callbackID
authorEric Blake <eblake@redhat.com>
Wed, 8 Jan 2014 04:00:54 +0000 (21:00 -0700)
committerEric Blake <eblake@redhat.com>
Wed, 12 Feb 2014 17:48:15 +0000 (10:48 -0700)
We want to convert over to server-side events, even for older
APIs.  To do that, the client side of the remote driver wants
to distinguish between legacy virConnectDomainEventRegister and
normal virConnectDomainEventRegisterAny, while knowing the
client callbackID and the server's serverID for both types of
registration.  The client also needs to probe whether the
server supports server-side filtering.  However, for ease of
review, we don't actually use the new RPCs until a later patch.

* src/conf/object_event_private.h (virObjectEventStateCallbackID):
Add parameter.
* src/conf/object_event.c (virObjectEventCallbackListAddID)
(virObjectEventStateRegisterID): Separate legacy from callbackID.
(virObjectEventStateCallbackID): Pass through parameter.
(virObjectEventCallbackLookup): Let legacy and global domain
lifecycle events share a common remoteID.
* src/conf/network_event.c (virNetworkEventStateRegisterID):
Update caller.
* src/conf/domain_event.c (virDomainEventStateRegister)
(virDomainEventStateRegisterID, virDomainEventStateDeregister):
Likewise.
(virDomainEventStateRegisterClient)
(virDomainEventStateCallbackID): Implement new functions.
* src/conf/domain_event.h (virDomainEventStateRegisterClient)
(virDomainEventStateCallbackID): New prototypes.
* src/remote/remote_driver.c (private_data): Add field.
(doRemoteOpen): Probe server feature.
(remoteConnectDomainEventRegister)
(remoteConnectDomainEventRegisterAny): Use new function.

Signed-off-by: Eric Blake <eblake@redhat.com>
src/conf/domain_event.c
src/conf/domain_event.h
src/conf/network_event.c
src/conf/object_event.c
src/conf/object_event_private.h
src/remote/remote_driver.c

index 8639a014d6c787709c21788d796dbf5acff71e5b..a490fe53f525ded3b9c78e1a178e3eae64368785 100644 (file)
@@ -1281,6 +1281,8 @@ virDomainEventStateRegister(virConnectPtr conn,
                             void *opaque,
                             virFreeCallback freecb)
 {
+    int callbackID;
+
     if (virDomainEventsInitialize() < 0)
         return -1;
 
@@ -1288,7 +1290,8 @@ virDomainEventStateRegister(virConnectPtr conn,
                                          NULL, NULL, virDomainEventClass,
                                          VIR_DOMAIN_EVENT_ID_LIFECYCLE,
                                          VIR_OBJECT_EVENT_CALLBACK(callback),
-                                         opaque, freecb, NULL, false);
+                                         opaque, freecb,
+                                         true, &callbackID, false);
 }
 
 
@@ -1326,7 +1329,75 @@ virDomainEventStateRegisterID(virConnectPtr conn,
                                          NULL, NULL,
                                          virDomainEventClass, eventID,
                                          VIR_OBJECT_EVENT_CALLBACK(cb),
-                                         opaque, freecb, callbackID, false);
+                                         opaque, freecb,
+                                         false, callbackID, false);
+}
+
+
+/**
+ * virDomainEventStateRegisterClient:
+ * @conn: connection to associate with callback
+ * @state: object event state
+ * @dom: optional domain for filtering the event
+ * @eventID: ID of the event type to register for
+ * @cb: function to invoke when event fires
+ * @opaque: data blob to pass to @callback
+ * @freecb: callback to free @opaque
+ * @legacy: true if callback is tracked by function instead of callbackID
+ * @callbackID: filled with callback ID
+ * @remoteID: true if server supports filtering
+ *
+ * Register the function @cb with connection @conn, from @state, for
+ * events of type @eventID, and return the registration handle in
+ * @callbackID.  This version is intended for use on the client side
+ * of RPC.
+ *
+ * Returns: the number of callbacks now registered, or -1 on error
+ */
+int
+virDomainEventStateRegisterClient(virConnectPtr conn,
+                                  virObjectEventStatePtr state,
+                                  virDomainPtr dom,
+                                  int eventID,
+                                  virConnectDomainEventGenericCallback cb,
+                                  void *opaque,
+                                  virFreeCallback freecb,
+                                  bool legacy,
+                                  int *callbackID,
+                                  bool remoteID)
+{
+    if (virDomainEventsInitialize() < 0)
+        return -1;
+
+    return virObjectEventStateRegisterID(conn, state, dom ? dom->uuid : NULL,
+                                         NULL, NULL,
+                                         virDomainEventClass, eventID,
+                                         VIR_OBJECT_EVENT_CALLBACK(cb),
+                                         opaque, freecb,
+                                         legacy, callbackID, remoteID);
+}
+
+
+/**
+ * virDomainEventStateCallbackID:
+ * @conn: connection associated with callback
+ * @state: object event state
+ * @cb: function registered as a callback with virDomainEventStateRegister()
+ * @remoteID: associated remote id of the callback
+ *
+ * Returns the callbackID of @cb, or -1 with an error issued if the
+ * function is not currently registered.
+ */
+int
+virDomainEventStateCallbackID(virConnectPtr conn,
+                              virObjectEventStatePtr state,
+                              virConnectDomainEventCallback cb,
+                              int *remoteID)
+{
+    return virObjectEventStateCallbackID(conn, state, virDomainEventClass,
+                                         VIR_DOMAIN_EVENT_ID_LIFECYCLE,
+                                         VIR_OBJECT_EVENT_CALLBACK(cb),
+                                         remoteID);
 }
 
 
@@ -1351,7 +1422,8 @@ virDomainEventStateDeregister(virConnectPtr conn,
     callbackID = virObjectEventStateCallbackID(conn, state,
                                                virDomainEventClass,
                                                VIR_DOMAIN_EVENT_ID_LIFECYCLE,
-                                               VIR_OBJECT_EVENT_CALLBACK(cb));
+                                               VIR_OBJECT_EVENT_CALLBACK(cb),
+                                               NULL);
     if (callbackID < 0)
         return -1;
     return virObjectEventStateDeregisterID(conn, state, callbackID);
index b033b23fda38a05c1f47e23d10ffd3c7f5fcfd49..be577e9131a224a04744933b83dce1378f20edcb 100644 (file)
@@ -192,6 +192,28 @@ virDomainEventStateRegisterID(virConnectPtr conn,
                               int *callbackID)
     ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(5);
 int
+virDomainEventStateRegisterClient(virConnectPtr conn,
+                                  virObjectEventStatePtr state,
+                                  virDomainPtr dom,
+                                  int eventID,
+                                  virConnectDomainEventGenericCallback cb,
+                                  void *opaque,
+                                  virFreeCallback freecb,
+                                  bool legacy,
+                                  int *callbackID,
+                                  bool remoteID)
+    ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(5)
+    ATTRIBUTE_NONNULL(9);
+
+int
+virDomainEventStateCallbackID(virConnectPtr conn,
+                              virObjectEventStatePtr state,
+                              virConnectDomainEventCallback callback,
+                              int *remoteID)
+    ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3)
+    ATTRIBUTE_NONNULL(4);
+
+int
 virDomainEventStateDeregister(virConnectPtr conn,
                               virObjectEventStatePtr state,
                               virConnectDomainEventCallback callback)
index 4c59356664cfbfc56f3ed471be7b7ab6181b7b95..f2cfefed3499f515950603082f0b73a2a033c95c 100644 (file)
@@ -155,7 +155,8 @@ virNetworkEventStateRegisterID(virConnectPtr conn,
                                          NULL, NULL,
                                          virNetworkEventClass, eventID,
                                          VIR_OBJECT_EVENT_CALLBACK(cb),
-                                         opaque, freecb, callbackID, false);
+                                         opaque, freecb,
+                                         false, callbackID, false);
 }
 
 
@@ -194,7 +195,8 @@ virNetworkEventStateRegisterClient(virConnectPtr conn,
                                          NULL, NULL,
                                          virNetworkEventClass, eventID,
                                          VIR_OBJECT_EVENT_CALLBACK(cb),
-                                         opaque, freecb, callbackID, true);
+                                         opaque, freecb,
+                                         false, callbackID, true);
 }
 
 
index aff49566145e9456b4d81479aa89381c30b7aa88..de452577e1c06071ae1d20bf7331e5ad2494aecc 100644 (file)
@@ -334,13 +334,13 @@ virObjectEventCallbackLookup(virConnectPtr conn,
         if (cb->klass == klass &&
             cb->eventID == eventID &&
             cb->conn == conn &&
-            cb->legacy == legacy &&
             ((uuid && cb->uuid_filter &&
               memcmp(cb->uuid, uuid, VIR_UUID_BUFLEN) == 0) ||
              (!uuid && !cb->uuid_filter))) {
             if (remoteID)
                 *remoteID = cb->remoteID;
-            if (cb->cb == callback)
+            if (cb->legacy == legacy &&
+                cb->cb == callback)
                 return cb->callbackID;
         }
     }
@@ -360,6 +360,7 @@ virObjectEventCallbackLookup(virConnectPtr conn,
  * @callback: the callback to add
  * @opaque: opaque data to pass to @callback
  * @freecb: callback to free @opaque
+ * @legacy: true if callback is tracked by function instead of callbackID
  * @callbackID: filled with callback ID
  * @serverFilter: true if server supports object filtering
  *
@@ -376,6 +377,7 @@ virObjectEventCallbackListAddID(virConnectPtr conn,
                                 virConnectObjectEventGenericCallback callback,
                                 void *opaque,
                                 virFreeCallback freecb,
+                                bool legacy,
                                 int *callbackID,
                                 bool serverFilter)
 {
@@ -384,9 +386,10 @@ virObjectEventCallbackListAddID(virConnectPtr conn,
     int remoteID = -1;
 
     VIR_DEBUG("conn=%p cblist=%p uuid=%p filter=%p filter_opaque=%p "
-              "klass=%p eventID=%d callback=%p opaque=%p",
-              conn, cbList, uuid, filter, filter_opaque,
-              klass, eventID, callback, opaque);
+              "klass=%p eventID=%d callback=%p opaque=%p "
+              "legacy=%d callbackID=%p serverFilter=%d",
+              conn, cbList, uuid, filter, filter_opaque, klass, eventID,
+              callback, opaque, legacy, callbackID, serverFilter);
 
     /* Check incoming */
     if (!cbList) {
@@ -395,8 +398,7 @@ virObjectEventCallbackListAddID(virConnectPtr conn,
 
     /* check if we already have this callback on our list */
     if (virObjectEventCallbackLookup(conn, cbList, uuid,
-                                     klass, eventID, callback,
-                                     !callbackID,
+                                     klass, eventID, callback, legacy,
                                      serverFilter ? &remoteID : NULL) != -1) {
         virReportError(VIR_ERR_INVALID_ARG, "%s",
                        _("event callback already tracked"));
@@ -406,7 +408,7 @@ virObjectEventCallbackListAddID(virConnectPtr conn,
     if (VIR_ALLOC(event) < 0)
         goto cleanup;
     event->conn = virObjectRef(conn);
-    event->callbackID = cbList->nextID++;
+    *callbackID = event->callbackID = cbList->nextID++;
     event->cb = callback;
     event->klass = klass;
     event->eventID = eventID;
@@ -423,11 +425,7 @@ virObjectEventCallbackListAddID(virConnectPtr conn,
     }
     event->filter = filter;
     event->filter_opaque = filter_opaque;
-
-    if (callbackID)
-        *callbackID = event->callbackID;
-    else
-        event->legacy = true;
+    event->legacy = legacy;
 
     if (VIR_APPEND_ELEMENT(cbList->callbacks, cbList->count, event) < 0)
         goto cleanup;
@@ -833,6 +831,7 @@ virObjectEventStateFlush(virObjectEventStatePtr state)
  * @cb: function to invoke when event occurs
  * @opaque: data blob to pass to @callback
  * @freecb: callback to free @opaque
+ * @legacy: true if callback is tracked by function instead of callbackID
  * @callbackID: filled with callback ID
  * @serverFilter: true if server supports object filtering
  *
@@ -867,6 +866,7 @@ virObjectEventStateRegisterID(virConnectPtr conn,
                               virConnectObjectEventGenericCallback cb,
                               void *opaque,
                               virFreeCallback freecb,
+                              bool legacy,
                               int *callbackID,
                               bool serverFilter)
 {
@@ -889,7 +889,7 @@ virObjectEventStateRegisterID(virConnectPtr conn,
                                           uuid, filter, filter_opaque,
                                           klass, eventID,
                                           cb, opaque, freecb,
-                                          callbackID, serverFilter);
+                                          legacy, callbackID, serverFilter);
 
     if (ret == -1 &&
         state->callbacks->count == 0 &&
@@ -949,6 +949,7 @@ virObjectEventStateDeregisterID(virConnectPtr conn,
  * @klass: the base event class
  * @eventID: the event ID
  * @callback: function registered as a callback
+ * @remoteID: optional output, containing resulting remote id
  *
  * Returns the callbackID of @callback, or -1 with an error issued if the
  * function is not currently registered.  This only finds functions
@@ -960,13 +961,15 @@ virObjectEventStateCallbackID(virConnectPtr conn,
                               virObjectEventStatePtr state,
                               virClassPtr klass,
                               int eventID,
-                              virConnectObjectEventGenericCallback callback)
+                              virConnectObjectEventGenericCallback callback,
+                              int *remoteID)
 {
     int ret = -1;
 
     virObjectEventStateLock(state);
     ret = virObjectEventCallbackLookup(conn, state->callbacks, NULL,
-                                       klass, eventID, callback, true, NULL);
+                                       klass, eventID, callback, true,
+                                       remoteID);
     virObjectEventStateUnlock(state);
 
     if (ret < 0)
index 8e265f94bcdd7ddc703aba2bc419f9bca5379b95..a19a0d3a39db1b4e45d6eb00ba6ba7d3abf3bf0d 100644 (file)
@@ -80,17 +80,19 @@ virObjectEventStateRegisterID(virConnectPtr conn,
                               virConnectObjectEventGenericCallback cb,
                               void *opaque,
                               virFreeCallback freecb,
+                              bool legacy,
                               int *callbackID,
                               bool remoteFilter)
     ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(6)
-    ATTRIBUTE_NONNULL(8);
+    ATTRIBUTE_NONNULL(8) ATTRIBUTE_NONNULL(12);
 
 int
 virObjectEventStateCallbackID(virConnectPtr conn,
                               virObjectEventStatePtr state,
                               virClassPtr klass,
                               int eventID,
-                              virConnectObjectEventGenericCallback callback)
+                              virConnectObjectEventGenericCallback callback,
+                              int *remoteID)
     ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3)
     ATTRIBUTE_NONNULL(5);
 
index 18eb454f58285ce08a42aa824011bd0024bb6a68..b0257c2c1ce631b18ccfe00f82f5dbc14feb316a 100644 (file)
@@ -92,6 +92,7 @@ struct private_data {
     int localUses;              /* Ref count for private data */
     char *hostname;             /* Original hostname */
     bool serverKeepAlive;       /* Does server support keepalive protocol? */
+    bool serverEventFilter;     /* Does server support modern event filtering */
 
     virObjectEventStatePtr eventState;
 };
@@ -890,8 +891,26 @@ doRemoteOpen(virConnectPtr conn,
             goto failed;
     }
 
+    /* Set up events */
     if (!(priv->eventState = virObjectEventStateNew()))
         goto failed;
+    {
+        remote_connect_supports_feature_args args =
+            { VIR_DRV_FEATURE_REMOTE_EVENT_CALLBACK };
+        remote_connect_supports_feature_ret ret = { 0 };
+        int rc;
+
+        rc = call(conn, priv, 0, REMOTE_PROC_CONNECT_SUPPORTS_FEATURE,
+                  (xdrproc_t)xdr_remote_connect_supports_feature_args, (char *) &args,
+                  (xdrproc_t)xdr_remote_connect_supports_feature_ret, (char *) &ret);
+
+        if (rc != -1 && ret.supported) {
+            priv->serverEventFilter = true;
+        } else {
+            VIR_INFO("Avoiding server event filtering since it is not "
+                     "supported by the server");
+        }
+    }
 
     /* Successful. */
     retcode = VIR_DRV_OPEN_SUCCESS;
@@ -4421,14 +4440,19 @@ remoteConnectDomainEventRegister(virConnectPtr conn,
                                  void *opaque,
                                  virFreeCallback freecb)
 {
+    int callbackID;
     int rv = -1;
     struct private_data *priv = conn->privateData;
     int count;
 
     remoteDriverLock(priv);
 
-    if ((count = virDomainEventStateRegister(conn, priv->eventState,
-                                             callback, opaque, freecb)) < 0)
+    if ((count = virDomainEventStateRegisterClient(conn, priv->eventState,
+                                                   NULL,
+                                                   VIR_DOMAIN_EVENT_ID_LIFECYCLE,
+                                                   VIR_DOMAIN_EVENT_CALLBACK(callback),
+                                                   opaque, freecb, true,
+                                                   &callbackID, false)) < 0)
          goto done;
 
     if (count == 1) {
@@ -5245,10 +5269,10 @@ remoteConnectDomainEventRegisterAny(virConnectPtr conn,
 
     remoteDriverLock(priv);
 
-    if ((count = virDomainEventStateRegisterID(conn, priv->eventState,
-                                               dom, eventID,
-                                               callback, opaque, freecb,
-                                               &callbackID)) < 0)
+    if ((count = virDomainEventStateRegisterClient(conn, priv->eventState,
+                                                   dom, eventID, callback,
+                                                   opaque, freecb, false,
+                                                   &callbackID, false)) < 0)
         goto done;
 
     /* If this is the first callback for this eventID, we need to enable