[libvirt] [PATCH 3/6] Introduce wait filtering (v2)

Anthony Liguori aliguori at us.ibm.com
Wed Apr 8 18:34:59 UTC 2009


This patch allows the wait command to be take a class mask that is used to
filter which events are waited for.  Because of limitations in the monitor
callbacks, this required splitting wait into two commands: wait and poll.  This
allows us to introduce the -x option to treat the mask as an exclusion mask.

Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/monitor.c b/monitor.c
index 94c14b2..1a7d026 100644
--- a/monitor.c
+++ b/monitor.c
@@ -1746,8 +1746,12 @@ static const mon_cmd_t mon_cmds[] = {
                                "acl allow vnc.username fred\n"
                                "acl deny vnc.username bob\n"
                                "acl reset vnc.username\n" },
-    { "wait", "-d", do_wait,
-      "[-d]", "wait for an asynchronous event (use -d to poll event)" },
+    { "wait", "-xs?", do_wait,
+      "[-x] [mask]",
+      "wait for an asynchronous event (-x to make mask exclusive, mask specifies the event classes to wait for)" },
+    { "poll", "-xs?", do_poll,
+      "[-x] [mask]",
+      "poll for an asynchronous event (-x to make mask exclusive, mask specifies the event classes to poll for)" },
     { NULL, NULL, },
 };
 
diff --git a/wait.c b/wait.c
index 8f6cbad..ebc156a 100644
--- a/wait.c
+++ b/wait.c
@@ -30,6 +30,8 @@ typedef struct PendingWaiter
 {
     Monitor *mon;
     int polling;
+    int exclusive;
+    char *mask;
     TAILQ_ENTRY(PendingWaiter) node;
 } PendingWaiter;
 
@@ -50,6 +52,12 @@ static void free_event(WaitEvent *e)
     qemu_free(e);
 }
 
+static void free_waiter(PendingWaiter *w)
+{
+    qemu_free(w->mask);
+    qemu_free(w);
+}
+
 static void dispatch_event(PendingWaiter *w, WaitEvent *e)
 {
     monitor_printf(w->mon, "%ld.%06ld: %s: %s\n",
@@ -81,6 +89,41 @@ static void remove_stale_events(void)
     }
 }
 
+static int find_string(const char *haystack, const char *needle)
+{
+    const char *p;
+    int clen = strlen(needle);
+
+    p = haystack;
+    while (p && strlen(p) >= clen) {
+        if (memcmp(p, needle, clen) == 0 &&
+            (p[clen] == 0 || p[clen] == ' ')) {
+            return 1;
+        }
+
+        p = strchr(p, ' ');
+        if (p)
+            p++;
+    }
+
+    return 0;
+}
+
+static int event_in_mask(PendingWaiter *w, WaitEvent *e)
+{
+    int ret;
+
+    if (e->class == NULL)
+        ret = 1;
+    else
+        ret = find_string(w->mask, e->class);
+
+    if (w->exclusive)
+        ret = !ret;
+
+    return ret;
+}
+
 static int try_to_process_events(void)
 {
     int processed_events = 0;
@@ -92,15 +135,21 @@ static int try_to_process_events(void)
         e = TAILQ_FIRST(&pending_events);
         TAILQ_REMOVE(&pending_events, e, node);
 
-        w = TAILQ_FIRST(&pending_waiters);
-        TAILQ_REMOVE(&pending_waiters, w, node);
+        TAILQ_FOREACH(w, &pending_waiters, node) {
+            if (event_in_mask(w, e))
+                break;
+        }
 
-        dispatch_event(w, e);
+        if (w) {
+            TAILQ_REMOVE(&pending_waiters, w, node);
 
-        free_event(e);
-        qemu_free(w);
+            dispatch_event(w, e);
 
-        processed_events = 1;
+            free_event(e);
+            free_waiter(w);
+
+            processed_events = 1;
+        }
     }
 
     remove_stale_events();
@@ -125,13 +174,17 @@ void qemu_notify_event(const char *class, const char *name, const char *details)
     try_to_process_events();
 }
 
-void do_wait(Monitor *mon, int polling)
+static void wait_with_mask(Monitor *mon, int polling, int exclusive,
+                           const char *mask)
 {
     PendingWaiter *w;
 
     w = qemu_mallocz(sizeof(*w));
     w->mon = mon;
     w->polling = polling;
+    w->exclusive = exclusive;
+    if (mask && strlen(mask))
+        w->mask = qemu_strdup(mask);
 
     TAILQ_INSERT_TAIL(&pending_waiters, w, node);
 
@@ -140,6 +193,16 @@ void do_wait(Monitor *mon, int polling)
 
     if (!try_to_process_events() && w->polling) {
         TAILQ_REMOVE(&pending_waiters, w, node);
-        qemu_free(w);
+        free_waiter(w);
     }
 }
+
+void do_wait(Monitor *mon, int exclusive, const char *mask)
+{
+    wait_with_mask(mon, 0, exclusive, mask);
+}
+
+void do_poll(Monitor *mon, int exclusive, const char *mask)
+{
+    wait_with_mask(mon, 1, exclusive, mask);
+}
diff --git a/wait.h b/wait.h
index 3fb455f..0942823 100644
--- a/wait.h
+++ b/wait.h
@@ -18,6 +18,7 @@
 
 void qemu_notify_event(const char *class, const char *name,
                        const char *details);
-void do_wait(Monitor *mon, int polling);
+void do_wait(Monitor *mon, int exclusive, const char *mask);
+void do_poll(Monitor *mon, int exclusive, const char *mask);
 
 #endif




More information about the libvir-list mailing list