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@xxxxxxxxxx> 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 -- Libvir-list mailing list Libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list