qemu-devel
[Top][All Lists]
Advanced

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

[Qemu-devel] [RFC 2/3] monitor: let QMPEventFuncEmit take a monitor arg


From: Peter Xu
Subject: [Qemu-devel] [RFC 2/3] monitor: let QMPEventFuncEmit take a monitor arg
Date: Wed, 4 Jul 2018 17:10:37 +0800

Let the QMPEventFuncEmit to take an extra Monitor* argument to allow
send events to specific monitor in follow-up patches.

Now we make the throttling of the events be per-monitor too.  There will
be a relatively complex scenario where we have an event for both
per-monitor and to-all-monitors, please refer to the comments in the
code for some details.

No functional change yet.

Signed-off-by: Peter Xu <address@hidden>
---
 include/qapi/qmp-event.h |  6 +++++-
 monitor.c                | 27 +++++++++++++++++++++++----
 tests/test-qmp-event.c   |  2 +-
 scripts/qapi/events.py   |  2 +-
 4 files changed, 30 insertions(+), 7 deletions(-)

diff --git a/include/qapi/qmp-event.h b/include/qapi/qmp-event.h
index 23e588ccf8..89ddfefe5a 100644
--- a/include/qapi/qmp-event.h
+++ b/include/qapi/qmp-event.h
@@ -14,7 +14,11 @@
 #ifndef QMP_EVENT_H
 #define QMP_EVENT_H
 
-typedef void (*QMPEventFuncEmit)(unsigned event, QDict *dict);
+/*
+ * Send an @event to the monitor specified in @mon.  If @mon is NULL,
+ * then send the event to all the available monitors.
+ */
+typedef void (*QMPEventFuncEmit)(Monitor *mon, unsigned event, QDict *dict);
 
 void qmp_event_set_func_emit(QMPEventFuncEmit emit);
 
diff --git a/monitor.c b/monitor.c
index 94ae7f1c79..48b5f0e21b 100644
--- a/monitor.c
+++ b/monitor.c
@@ -200,6 +200,7 @@ typedef struct {
  * instance.
  */
 typedef struct MonitorQAPIEventState {
+    Monitor *mon;       /* The monitor to emit the event; NULL to all */
     QAPIEvent event;    /* Throttling state for this event type and... */
     QDict *data;        /* ... data, see qapi_event_throttle_equal() */
     QEMUTimer *timer;   /* Timer for handling delayed events */
@@ -673,11 +674,11 @@ static void monitor_qapi_event_emit(Monitor *mon, 
QAPIEvent event,
 static void monitor_qapi_event_handler(void *opaque);
 
 /*
- * Queue a new event for emission to Monitor instances,
+ * Queue a new event for emission to one Monitor instance or all,
  * applying any rate limiting if required.
  */
 static void
-monitor_qapi_event_queue(QAPIEvent event, QDict *qdict)
+monitor_qapi_event_queue(Monitor *mon, QAPIEvent event, QDict *qdict)
 {
     MonitorQAPIEventConf *evconf;
     MonitorQAPIEventState *evstate;
@@ -693,7 +694,8 @@ monitor_qapi_event_queue(QAPIEvent event, QDict *qdict)
         monitor_qapi_event_emit(NULL, event, qdict);
     } else {
         QDict *data = qobject_to(QDict, qdict_get(qdict, "data"));
-        MonitorQAPIEventState key = { .event = event, .data = data };
+        MonitorQAPIEventState key = { .mon = mon, .event = event,
+                                      .data = data };
 
         evstate = g_hash_table_lookup(monitor_qapi_event_state, &key);
         assert(!evstate || timer_pending(evstate->timer));
@@ -715,9 +717,10 @@ monitor_qapi_event_queue(QAPIEvent event, QDict *qdict)
              */
             int64_t now = qemu_clock_get_ns(monitor_get_event_clock());
 
-            monitor_qapi_event_emit(NULL, event, qdict);
+            monitor_qapi_event_emit(mon, event, qdict);
 
             evstate = g_new(MonitorQAPIEventState, 1);
+            evstate->mon = mon;
             evstate->event = event;
             evstate->data = qobject_ref(data);
             evstate->qdict = NULL;
@@ -787,6 +790,22 @@ static gboolean qapi_event_throttle_equal(const void *a, 
const void *b)
         return FALSE;
     }
 
+    /*
+     * We do event throttling per-monitor.  It's still possible that
+     * we have one event that are both throttled by one per-monitor
+     * MonitorQAPIEventState, and another global MonitorQAPIEventState
+     * for the same event, but it's not a big problem since one event
+     * should either be for per-monitor or for globally, so generally
+     * we should not have this happened.  Even if it happens, the
+     * worst case is that we'll double the throttle for that specific
+     * monitor to receive the events, so it might receive the events
+     * in 2*rate speed, that'll still keep it away from event
+     * flooding.  It'll only be the rate that will be inaccurate.
+     */
+    if (eva->mon != evb->mon) {
+        return FALSE;
+    }
+
     if (eva->event == QAPI_EVENT_VSERPORT_CHANGE) {
         return !strcmp(qdict_get_str(eva->data, "id"),
                        qdict_get_str(evb->data, "id"));
diff --git a/tests/test-qmp-event.c b/tests/test-qmp-event.c
index 9cddd72adb..8d59d4898e 100644
--- a/tests/test-qmp-event.c
+++ b/tests/test-qmp-event.c
@@ -95,7 +95,7 @@ static bool qdict_cmp_simple(QDict *a, QDict *b)
 
 /* This function is hooked as final emit function, which can verify the
    correctness. */
-static void event_test_emit(test_QAPIEvent event, QDict *d)
+static void event_test_emit(Monitor *mon, test_QAPIEvent event, QDict *d)
 {
     QDict *t;
     int64_t s, ms;
diff --git a/scripts/qapi/events.py b/scripts/qapi/events.py
index 3953dc9837..fec0168af7 100644
--- a/scripts/qapi/events.py
+++ b/scripts/qapi/events.py
@@ -121,7 +121,7 @@ def gen_event_send(name, arg_type, boxed, event_enum_name):
 ''')
 
     ret += mcgen('''
-    emit(%(c_enum)s, qmp);
+    emit(NULL, %(c_enum)s, qmp);
 
 ''',
                  c_enum=c_enum_const(event_enum_name, name))
-- 
2.17.1




reply via email to

[Prev in Thread] Current Thread [Next in Thread]