docs/kbase/internals/qemu-event-handlers.rst | 13 +- meson.build | 2 + src/qemu/meson.build | 9 + src/qemu/qemu_monitor_event.gperf | 68 ++++++++ src/qemu/qemu_monitor_json.c | 171 +++++-------------- src/qemu/qemu_monitor_json.h | 45 +++++ 6 files changed, 170 insertions(+), 138 deletions(-) create mode 100644 src/qemu/qemu_monitor_event.gperf
Currently, monitor event names are looked up using binary search which has
O(log(n)) time complexity. This can be optimized even further with a
compile-time static hash table generated by the gperf tool. As gperf ensures
perfect hashing, lookup times are guaranteed to be O(1).
This patch also makes gperf a requirement for compiling libvirt if the QEMU
driver is enabled.
Signed-off-by: Rayhan Faizel <rayhan.faizel@gmail.com>
---
docs/kbase/internals/qemu-event-handlers.rst | 13 +-
meson.build | 2 +
src/qemu/meson.build | 9 +
src/qemu/qemu_monitor_event.gperf | 68 ++++++++
src/qemu/qemu_monitor_json.c | 171 +++++--------------
src/qemu/qemu_monitor_json.h | 45 +++++
6 files changed, 170 insertions(+), 138 deletions(-)
create mode 100644 src/qemu/qemu_monitor_event.gperf
diff --git a/docs/kbase/internals/qemu-event-handlers.rst b/docs/kbase/internals/qemu-event-handlers.rst
index 3589c4c48c..5ec11e28bd 100644
--- a/docs/kbase/internals/qemu-event-handlers.rst
+++ b/docs/kbase/internals/qemu-event-handlers.rst
@@ -23,16 +23,15 @@ QEMU monitor events
Any event emitted by qemu is received by
``qemu_monitor_json.c:qemuMonitorJSONIOProcessEvent()``. It looks up the
-event by name in the table ``eventHandlers`` (in the same file), which
-should have an entry like this for each event that libvirt
-understands::
+event by name from a hash-table, generated at compile-time by ``gperf``
+based on a list of entries defined in ``qemu_monitor_event.gperf``.
+``qemu_monitor_event.gperf`` should should have an entry like this
+for each event that libvirt understands::
- { "NIC_RX_FILTER_CHANGED", qemuMonitorJSONHandleNicRxFilterChanged, },
-
-NB: This table is searched with bsearch, so it *must* be alphabetically sorted.
+ "NIC_RX_FILTER_CHANGED", qemuMonitorJSONHandleNicRxFilterChanged
``qemuMonitorJSONIOProcessEvent`` calls the function listed in
-``eventHandlers``, e.g.::
+``qemu_monitor_event.gperf``, e.g.::
qemu_monitor_json.c:qemuMonitorJSONHandleNicRxFilterChanged()
diff --git a/meson.build b/meson.build
index e8b0094b91..03f1f0d56d 100644
--- a/meson.build
+++ b/meson.build
@@ -1708,6 +1708,8 @@ if not get_option('driver_qemu').disabled()
qemu_slirp_path = '/usr/bin/slirp-helper'
endif
conf.set_quoted('QEMU_SLIRP_HELPER', qemu_slirp_path)
+
+ gperf_prog = find_program('gperf')
endif
endif
diff --git a/src/qemu/meson.build b/src/qemu/meson.build
index 907893d431..2440476a7b 100644
--- a/src/qemu/meson.build
+++ b/src/qemu/meson.build
@@ -88,11 +88,20 @@ qemu_shim_sources = files(
'qemu_shim.c',
)
+qemu_driver_gperf_sources = []
+
+qemu_driver_gperf_sources += custom_target(
+ 'qemu_monitor_event.c',
+ input : 'qemu_monitor_event.gperf',
+ output : 'qemu_monitor_event.c',
+ command : [gperf_prog, '@INPUT@', '--output-file', '@OUTPUT@'])
+
if conf.has('WITH_QEMU')
qemu_driver_impl = static_library(
'virt_driver_qemu_impl',
[
qemu_driver_sources,
+ qemu_driver_gperf_sources,
qemu_dtrace_gen_headers,
],
dependencies: [
diff --git a/src/qemu/qemu_monitor_event.gperf b/src/qemu/qemu_monitor_event.gperf
new file mode 100644
index 0000000000..de2f958b9e
--- /dev/null
+++ b/src/qemu/qemu_monitor_event.gperf
@@ -0,0 +1,68 @@
+/*
+ * qemu_monitor_event.gperf: QEMU Monitor Event Lookup Table
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+%{
+#include "qemu_monitor_json.h"
+%}
+qemuEventHandler;
+%null_strings
+%define initializer-suffix ,NULL
+%language=ANSI-C
+%define slot-name type
+%define lookup-function-name qemu_monitor_event_lookup
+%define hash-function-name qemu_monitor_event_hash
+%readonly-tables
+%omit-struct-type
+%struct-type
+%%
+"ACPI_DEVICE_OST", qemuMonitorJSONHandleAcpiOstInfo
+"BALLOON_CHANGE", qemuMonitorJSONHandleBalloonChange
+"BLOCK_IO_ERROR", qemuMonitorJSONHandleIOError
+"BLOCK_WRITE_THRESHOLD", qemuMonitorJSONHandleBlockThreshold
+"DEVICE_DELETED", qemuMonitorJSONHandleDeviceDeleted
+"DEVICE_TRAY_MOVED", qemuMonitorJSONHandleTrayChange
+"DEVICE_UNPLUG_GUEST_ERROR", qemuMonitorJSONHandleDeviceUnplugErr
+"DUMP_COMPLETED", qemuMonitorJSONHandleDumpCompleted
+"GUEST_CRASHLOADED", qemuMonitorJSONHandleGuestCrashloaded
+"GUEST_PANICKED", qemuMonitorJSONHandleGuestPanic
+"JOB_STATUS_CHANGE", qemuMonitorJSONHandleJobStatusChange
+"MEMORY_DEVICE_SIZE_CHANGE", qemuMonitorJSONHandleMemoryDeviceSizeChange
+"MEMORY_FAILURE", qemuMonitorJSONHandleMemoryFailure
+"MIGRATION", qemuMonitorJSONHandleMigrationStatus
+"MIGRATION_PASS", qemuMonitorJSONHandleMigrationPass
+"NETDEV_STREAM_DISCONNECTED", qemuMonitorJSONHandleNetdevStreamDisconnected
+"NIC_RX_FILTER_CHANGED", qemuMonitorJSONHandleNicRxFilterChanged
+"PR_MANAGER_STATUS_CHANGED", qemuMonitorJSONHandlePRManagerStatusChanged
+"RDMA_GID_STATUS_CHANGED", qemuMonitorJSONHandleRdmaGidStatusChanged
+"RESET", qemuMonitorJSONHandleReset
+"RESUME", qemuMonitorJSONHandleResume
+"RTC_CHANGE", qemuMonitorJSONHandleRTCChange
+"SHUTDOWN", qemuMonitorJSONHandleShutdown
+"SPICE_CONNECTED", qemuMonitorJSONHandleSPICEConnect
+"SPICE_DISCONNECTED", qemuMonitorJSONHandleSPICEDisconnect
+"SPICE_INITIALIZED", qemuMonitorJSONHandleSPICEInitialize
+"SPICE_MIGRATE_COMPLETED", qemuMonitorJSONHandleSpiceMigrated
+"STOP", qemuMonitorJSONHandleStop
+"SUSPEND", qemuMonitorJSONHandlePMSuspend
+"SUSPEND_DISK", qemuMonitorJSONHandlePMSuspendDisk
+"VNC_CONNECTED", qemuMonitorJSONHandleVNCConnect
+"VNC_DISCONNECTED", qemuMonitorJSONHandleVNCDisconnect
+"VNC_INITIALIZED", qemuMonitorJSONHandleVNCInitialize
+"VSERPORT_CHANGE", qemuMonitorJSONHandleSerialChange
+"WAKEUP", qemuMonitorJSONHandlePMWakeup
+"WATCHDOG", qemuMonitorJSONHandleWatchdog
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
index eb84a3d938..93df4490ad 100644
--- a/src/qemu/qemu_monitor_json.c
+++ b/src/qemu/qemu_monitor_json.c
@@ -49,102 +49,12 @@ VIR_LOG_INIT("qemu.qemu_monitor_json");
#define LINE_ENDING "\r\n"
-static void qemuMonitorJSONHandleShutdown(qemuMonitor *mon, virJSONValue *data);
-static void qemuMonitorJSONHandleReset(qemuMonitor *mon, virJSONValue *data);
-static void qemuMonitorJSONHandleStop(qemuMonitor *mon, virJSONValue *data);
-static void qemuMonitorJSONHandleResume(qemuMonitor *mon, virJSONValue *data);
-static void qemuMonitorJSONHandleRTCChange(qemuMonitor *mon, virJSONValue *data);
-static void qemuMonitorJSONHandleWatchdog(qemuMonitor *mon, virJSONValue *data);
-static void qemuMonitorJSONHandleIOError(qemuMonitor *mon, virJSONValue *data);
-static void qemuMonitorJSONHandleVNCConnect(qemuMonitor *mon, virJSONValue *data);
-static void qemuMonitorJSONHandleVNCInitialize(qemuMonitor *mon, virJSONValue *data);
-static void qemuMonitorJSONHandleVNCDisconnect(qemuMonitor *mon, virJSONValue *data);
-static void qemuMonitorJSONHandleSPICEConnect(qemuMonitor *mon, virJSONValue *data);
-static void qemuMonitorJSONHandleSPICEInitialize(qemuMonitor *mon, virJSONValue *data);
-static void qemuMonitorJSONHandleSPICEDisconnect(qemuMonitor *mon, virJSONValue *data);
-static void qemuMonitorJSONHandleTrayChange(qemuMonitor *mon, virJSONValue *data);
-static void qemuMonitorJSONHandlePMWakeup(qemuMonitor *mon, virJSONValue *data);
-static void qemuMonitorJSONHandlePMSuspend(qemuMonitor *mon, virJSONValue *data);
-static void qemuMonitorJSONHandleJobStatusChange(qemuMonitor *mon, virJSONValue *data);
-static void qemuMonitorJSONHandleBalloonChange(qemuMonitor *mon, virJSONValue *data);
-static void qemuMonitorJSONHandlePMSuspendDisk(qemuMonitor *mon, virJSONValue *data);
-static void qemuMonitorJSONHandleGuestCrashloaded(qemuMonitor *mon, virJSONValue *data);
-static void qemuMonitorJSONHandleGuestPanic(qemuMonitor *mon, virJSONValue *data);
-static void qemuMonitorJSONHandleDeviceDeleted(qemuMonitor *mon, virJSONValue *data);
-static void qemuMonitorJSONHandleNicRxFilterChanged(qemuMonitor *mon, virJSONValue *data);
-static void qemuMonitorJSONHandleSerialChange(qemuMonitor *mon, virJSONValue *data);
-static void qemuMonitorJSONHandleSpiceMigrated(qemuMonitor *mon, virJSONValue *data);
-static void qemuMonitorJSONHandleMigrationStatus(qemuMonitor *mon, virJSONValue *data);
-static void qemuMonitorJSONHandleMigrationPass(qemuMonitor *mon, virJSONValue *data);
-static void qemuMonitorJSONHandleAcpiOstInfo(qemuMonitor *mon, virJSONValue *data);
-static void qemuMonitorJSONHandleBlockThreshold(qemuMonitor *mon, virJSONValue *data);
-static void qemuMonitorJSONHandleDumpCompleted(qemuMonitor *mon, virJSONValue *data);
-static void qemuMonitorJSONHandlePRManagerStatusChanged(qemuMonitor *mon, virJSONValue *data);
-static void qemuMonitorJSONHandleRdmaGidStatusChanged(qemuMonitor *mon, virJSONValue *data);
-static void qemuMonitorJSONHandleMemoryFailure(qemuMonitor *mon, virJSONValue *data);
-static void qemuMonitorJSONHandleMemoryDeviceSizeChange(qemuMonitor *mon, virJSONValue *data);
-static void qemuMonitorJSONHandleDeviceUnplugErr(qemuMonitor *mon, virJSONValue *data);
-static void qemuMonitorJSONHandleNetdevStreamDisconnected(qemuMonitor *mon, virJSONValue *data);
-
-typedef struct {
- const char *type;
- void (*handler)(qemuMonitor *mon, virJSONValue *data);
-} qemuEventHandler;
-
-static qemuEventHandler eventHandlers[] = {
- { "ACPI_DEVICE_OST", qemuMonitorJSONHandleAcpiOstInfo, },
- { "BALLOON_CHANGE", qemuMonitorJSONHandleBalloonChange, },
- { "BLOCK_IO_ERROR", qemuMonitorJSONHandleIOError, },
- { "BLOCK_WRITE_THRESHOLD", qemuMonitorJSONHandleBlockThreshold, },
- { "DEVICE_DELETED", qemuMonitorJSONHandleDeviceDeleted, },
- { "DEVICE_TRAY_MOVED", qemuMonitorJSONHandleTrayChange, },
- { "DEVICE_UNPLUG_GUEST_ERROR", qemuMonitorJSONHandleDeviceUnplugErr, },
- { "DUMP_COMPLETED", qemuMonitorJSONHandleDumpCompleted, },
- { "GUEST_CRASHLOADED", qemuMonitorJSONHandleGuestCrashloaded, },
- { "GUEST_PANICKED", qemuMonitorJSONHandleGuestPanic, },
- { "JOB_STATUS_CHANGE", qemuMonitorJSONHandleJobStatusChange, },
- { "MEMORY_DEVICE_SIZE_CHANGE", qemuMonitorJSONHandleMemoryDeviceSizeChange, },
- { "MEMORY_FAILURE", qemuMonitorJSONHandleMemoryFailure, },
- { "MIGRATION", qemuMonitorJSONHandleMigrationStatus, },
- { "MIGRATION_PASS", qemuMonitorJSONHandleMigrationPass, },
- { "NETDEV_STREAM_DISCONNECTED", qemuMonitorJSONHandleNetdevStreamDisconnected, },
- { "NIC_RX_FILTER_CHANGED", qemuMonitorJSONHandleNicRxFilterChanged, },
- { "PR_MANAGER_STATUS_CHANGED", qemuMonitorJSONHandlePRManagerStatusChanged, },
- { "RDMA_GID_STATUS_CHANGED", qemuMonitorJSONHandleRdmaGidStatusChanged, },
- { "RESET", qemuMonitorJSONHandleReset, },
- { "RESUME", qemuMonitorJSONHandleResume, },
- { "RTC_CHANGE", qemuMonitorJSONHandleRTCChange, },
- { "SHUTDOWN", qemuMonitorJSONHandleShutdown, },
- { "SPICE_CONNECTED", qemuMonitorJSONHandleSPICEConnect, },
- { "SPICE_DISCONNECTED", qemuMonitorJSONHandleSPICEDisconnect, },
- { "SPICE_INITIALIZED", qemuMonitorJSONHandleSPICEInitialize, },
- { "SPICE_MIGRATE_COMPLETED", qemuMonitorJSONHandleSpiceMigrated, },
- { "STOP", qemuMonitorJSONHandleStop, },
- { "SUSPEND", qemuMonitorJSONHandlePMSuspend, },
- { "SUSPEND_DISK", qemuMonitorJSONHandlePMSuspendDisk, },
- { "VNC_CONNECTED", qemuMonitorJSONHandleVNCConnect, },
- { "VNC_DISCONNECTED", qemuMonitorJSONHandleVNCDisconnect, },
- { "VNC_INITIALIZED", qemuMonitorJSONHandleVNCInitialize, },
- { "VSERPORT_CHANGE", qemuMonitorJSONHandleSerialChange, },
- { "WAKEUP", qemuMonitorJSONHandlePMWakeup, },
- { "WATCHDOG", qemuMonitorJSONHandleWatchdog, },
- /* We use bsearch, so keep this list sorted. */
-};
-
-static int
-qemuMonitorEventCompare(const void *key, const void *elt)
-{
- const char *type = key;
- const qemuEventHandler *handler = elt;
- return strcmp(type, handler->type);
-}
-
static int
qemuMonitorJSONIOProcessEvent(qemuMonitor *mon,
virJSONValue *obj)
{
const char *type;
- qemuEventHandler *handler;
+ const qemuEventHandler *handler;
virJSONValue *data;
g_autofree char *details = NULL;
virJSONValue *timestamp;
@@ -171,8 +81,7 @@ qemuMonitorJSONIOProcessEvent(qemuMonitor *mon,
}
qemuMonitorEmitEvent(mon, type, seconds, micros, details);
- handler = bsearch(type, eventHandlers, G_N_ELEMENTS(eventHandlers),
- sizeof(eventHandlers[0]), qemuMonitorEventCompare);
+ handler = qemu_monitor_event_lookup(type, strlen(type));
if (handler) {
VIR_DEBUG("handle %s handler=%p data=%p", type,
handler->handler, data);
@@ -543,7 +452,7 @@ qemuMonitorJSONMakeCommand(const char *cmdname,
}
-static void qemuMonitorJSONHandleShutdown(qemuMonitor *mon, virJSONValue *data)
+void qemuMonitorJSONHandleShutdown(qemuMonitor *mon, virJSONValue *data)
{
bool guest = false;
virTristateBool guest_initiated = VIR_TRISTATE_BOOL_ABSENT;
@@ -554,17 +463,17 @@ static void qemuMonitorJSONHandleShutdown(qemuMonitor *mon, virJSONValue *data)
qemuMonitorEmitShutdown(mon, guest_initiated);
}
-static void qemuMonitorJSONHandleReset(qemuMonitor *mon, virJSONValue *data G_GNUC_UNUSED)
+void qemuMonitorJSONHandleReset(qemuMonitor *mon, virJSONValue *data G_GNUC_UNUSED)
{
qemuMonitorEmitReset(mon);
}
-static void qemuMonitorJSONHandleStop(qemuMonitor *mon, virJSONValue *data G_GNUC_UNUSED)
+void qemuMonitorJSONHandleStop(qemuMonitor *mon, virJSONValue *data G_GNUC_UNUSED)
{
qemuMonitorEmitStop(mon);
}
-static void qemuMonitorJSONHandleResume(qemuMonitor *mon, virJSONValue *data G_GNUC_UNUSED)
+void qemuMonitorJSONHandleResume(qemuMonitor *mon, virJSONValue *data G_GNUC_UNUSED)
{
qemuMonitorEmitResume(mon);
}
@@ -635,7 +544,7 @@ qemuMonitorJSONGuestPanicExtractInfo(virJSONValue *data)
}
-static void
+void
qemuMonitorJSONHandleGuestPanic(qemuMonitor *mon,
virJSONValue *data)
{
@@ -649,7 +558,7 @@ qemuMonitorJSONHandleGuestPanic(qemuMonitor *mon,
}
-static void qemuMonitorJSONHandleRTCChange(qemuMonitor *mon, virJSONValue *data)
+void qemuMonitorJSONHandleRTCChange(qemuMonitor *mon, virJSONValue *data)
{
long long offset = 0;
if (virJSONValueObjectGetNumberLong(data, "offset", &offset) < 0) {
@@ -665,7 +574,7 @@ VIR_ENUM_IMPL(qemuMonitorWatchdogAction,
"none", "pause", "reset", "poweroff", "shutdown", "debug", "inject-nmi",
);
-static void qemuMonitorJSONHandleWatchdog(qemuMonitor *mon, virJSONValue *data)
+void qemuMonitorJSONHandleWatchdog(qemuMonitor *mon, virJSONValue *data)
{
const char *action;
int actionID;
@@ -689,7 +598,7 @@ VIR_ENUM_IMPL(qemuMonitorIOErrorAction,
);
-static void
+void
qemuMonitorJSONHandleIOError(qemuMonitor *mon, virJSONValue *data)
{
const char *device;
@@ -802,19 +711,19 @@ qemuMonitorJSONHandleGraphicsVNC(qemuMonitor *mon,
authScheme, x509dname, saslUsername);
}
-static void qemuMonitorJSONHandleVNCConnect(qemuMonitor *mon, virJSONValue *data)
+void qemuMonitorJSONHandleVNCConnect(qemuMonitor *mon, virJSONValue *data)
{
qemuMonitorJSONHandleGraphicsVNC(mon, data, VIR_DOMAIN_EVENT_GRAPHICS_CONNECT);
}
-static void qemuMonitorJSONHandleVNCInitialize(qemuMonitor *mon, virJSONValue *data)
+void qemuMonitorJSONHandleVNCInitialize(qemuMonitor *mon, virJSONValue *data)
{
qemuMonitorJSONHandleGraphicsVNC(mon, data, VIR_DOMAIN_EVENT_GRAPHICS_INITIALIZE);
}
-static void qemuMonitorJSONHandleVNCDisconnect(qemuMonitor *mon, virJSONValue *data)
+void qemuMonitorJSONHandleVNCDisconnect(qemuMonitor *mon, virJSONValue *data)
{
qemuMonitorJSONHandleGraphicsVNC(mon, data, VIR_DOMAIN_EVENT_GRAPHICS_DISCONNECT);
}
@@ -884,24 +793,24 @@ qemuMonitorJSONHandleGraphicsSPICE(qemuMonitor *mon,
}
-static void qemuMonitorJSONHandleSPICEConnect(qemuMonitor *mon, virJSONValue *data)
+void qemuMonitorJSONHandleSPICEConnect(qemuMonitor *mon, virJSONValue *data)
{
qemuMonitorJSONHandleGraphicsSPICE(mon, data, VIR_DOMAIN_EVENT_GRAPHICS_CONNECT);
}
-static void qemuMonitorJSONHandleSPICEInitialize(qemuMonitor *mon, virJSONValue *data)
+void qemuMonitorJSONHandleSPICEInitialize(qemuMonitor *mon, virJSONValue *data)
{
qemuMonitorJSONHandleGraphicsSPICE(mon, data, VIR_DOMAIN_EVENT_GRAPHICS_INITIALIZE);
}
-static void qemuMonitorJSONHandleSPICEDisconnect(qemuMonitor *mon, virJSONValue *data)
+void qemuMonitorJSONHandleSPICEDisconnect(qemuMonitor *mon, virJSONValue *data)
{
qemuMonitorJSONHandleGraphicsSPICE(mon, data, VIR_DOMAIN_EVENT_GRAPHICS_DISCONNECT);
}
-static void
+void
qemuMonitorJSONHandleJobStatusChange(qemuMonitor *mon,
virJSONValue *data)
{
@@ -924,7 +833,7 @@ qemuMonitorJSONHandleJobStatusChange(qemuMonitor *mon,
}
-static void
+void
qemuMonitorJSONHandleTrayChange(qemuMonitor *mon,
virJSONValue *data)
{
@@ -955,14 +864,14 @@ qemuMonitorJSONHandleTrayChange(qemuMonitor *mon,
qemuMonitorEmitTrayChange(mon, devAlias, devid, reason);
}
-static void
+void
qemuMonitorJSONHandlePMWakeup(qemuMonitor *mon,
virJSONValue *data G_GNUC_UNUSED)
{
qemuMonitorEmitPMWakeup(mon);
}
-static void
+void
qemuMonitorJSONHandlePMSuspend(qemuMonitor *mon,
virJSONValue *data G_GNUC_UNUSED)
{
@@ -970,7 +879,7 @@ qemuMonitorJSONHandlePMSuspend(qemuMonitor *mon,
}
-static void
+void
qemuMonitorJSONHandleBalloonChange(qemuMonitor *mon,
virJSONValue *data)
{
@@ -983,14 +892,14 @@ qemuMonitorJSONHandleBalloonChange(qemuMonitor *mon,
qemuMonitorEmitBalloonChange(mon, actual);
}
-static void
+void
qemuMonitorJSONHandlePMSuspendDisk(qemuMonitor *mon,
virJSONValue *data G_GNUC_UNUSED)
{
qemuMonitorEmitPMSuspendDisk(mon);
}
-static void
+void
qemuMonitorJSONHandleDeviceDeleted(qemuMonitor *mon, virJSONValue *data)
{
const char *device;
@@ -1004,7 +913,7 @@ qemuMonitorJSONHandleDeviceDeleted(qemuMonitor *mon, virJSONValue *data)
}
-static void
+void
qemuMonitorJSONHandleDeviceUnplugErr(qemuMonitor *mon, virJSONValue *data)
{
const char *device;
@@ -1021,7 +930,7 @@ qemuMonitorJSONHandleDeviceUnplugErr(qemuMonitor *mon, virJSONValue *data)
}
-static void
+void
qemuMonitorJSONHandleNetdevStreamDisconnected(qemuMonitor *mon, virJSONValue *data)
{
const char *name;
@@ -1035,7 +944,7 @@ qemuMonitorJSONHandleNetdevStreamDisconnected(qemuMonitor *mon, virJSONValue *da
}
-static void
+void
qemuMonitorJSONHandleNicRxFilterChanged(qemuMonitor *mon, virJSONValue *data)
{
const char *name;
@@ -1049,7 +958,7 @@ qemuMonitorJSONHandleNicRxFilterChanged(qemuMonitor *mon, virJSONValue *data)
}
-static void
+void
qemuMonitorJSONHandleSerialChange(qemuMonitor *mon,
virJSONValue *data)
{
@@ -1070,7 +979,7 @@ qemuMonitorJSONHandleSerialChange(qemuMonitor *mon,
}
-static void
+void
qemuMonitorJSONHandleSpiceMigrated(qemuMonitor *mon,
virJSONValue *data G_GNUC_UNUSED)
{
@@ -1078,7 +987,7 @@ qemuMonitorJSONHandleSpiceMigrated(qemuMonitor *mon,
}
-static void
+void
qemuMonitorJSONHandleMemoryDeviceSizeChange(qemuMonitor *mon,
virJSONValue *data)
{
@@ -1100,7 +1009,7 @@ qemuMonitorJSONHandleMemoryDeviceSizeChange(qemuMonitor *mon,
}
-static void
+void
qemuMonitorJSONHandleMemoryFailure(qemuMonitor *mon,
virJSONValue *data)
{
@@ -1147,7 +1056,7 @@ qemuMonitorJSONHandleMemoryFailure(qemuMonitor *mon,
}
-static void
+void
qemuMonitorJSONHandleMigrationStatus(qemuMonitor *mon,
virJSONValue *data)
{
@@ -1168,7 +1077,7 @@ qemuMonitorJSONHandleMigrationStatus(qemuMonitor *mon,
}
-static void
+void
qemuMonitorJSONHandleMigrationPass(qemuMonitor *mon,
virJSONValue *data)
{
@@ -1183,7 +1092,7 @@ qemuMonitorJSONHandleMigrationPass(qemuMonitor *mon,
}
-static void
+void
qemuMonitorJSONHandleAcpiOstInfo(qemuMonitor *mon, virJSONValue *data)
{
virJSONValue *info;
@@ -1220,7 +1129,7 @@ qemuMonitorJSONHandleAcpiOstInfo(qemuMonitor *mon, virJSONValue *data)
}
-static void
+void
qemuMonitorJSONHandleBlockThreshold(qemuMonitor *mon, virJSONValue *data)
{
const char *nodename;
@@ -1280,7 +1189,7 @@ qemuMonitorJSONExtractDumpStats(virJSONValue *result,
}
-static void
+void
qemuMonitorJSONHandleDumpCompleted(qemuMonitor *mon,
virJSONValue *data)
{
@@ -1302,8 +1211,8 @@ qemuMonitorJSONHandleDumpCompleted(qemuMonitor *mon,
}
-static void qemuMonitorJSONHandlePRManagerStatusChanged(qemuMonitor *mon,
- virJSONValue *data)
+void qemuMonitorJSONHandlePRManagerStatusChanged(qemuMonitor *mon,
+ virJSONValue *data)
{
const char *name;
bool connected;
@@ -1323,8 +1232,8 @@ static void qemuMonitorJSONHandlePRManagerStatusChanged(qemuMonitor *mon,
}
-static void qemuMonitorJSONHandleRdmaGidStatusChanged(qemuMonitor *mon,
- virJSONValue *data)
+void qemuMonitorJSONHandleRdmaGidStatusChanged(qemuMonitor *mon,
+ virJSONValue *data)
{
const char *netdev;
bool gid_status;
@@ -1357,7 +1266,7 @@ static void qemuMonitorJSONHandleRdmaGidStatusChanged(qemuMonitor *mon,
}
-static void
+void
qemuMonitorJSONHandleGuestCrashloaded(qemuMonitor *mon,
virJSONValue *data)
{
diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h
index 9684660d86..5bd4b21b7d 100644
--- a/src/qemu/qemu_monitor_json.h
+++ b/src/qemu/qemu_monitor_json.h
@@ -27,6 +27,51 @@
#include "cpu/cpu.h"
#include "util/virgic.h"
+typedef struct {
+ const char *type;
+ void (*handler)(qemuMonitor *mon, virJSONValue *data);
+} qemuEventHandler;
+
+const qemuEventHandler *
+qemu_monitor_event_lookup(const char *str, size_t len);
+
+void qemuMonitorJSONHandleShutdown(qemuMonitor *mon, virJSONValue *data);
+void qemuMonitorJSONHandleReset(qemuMonitor *mon, virJSONValue *data);
+void qemuMonitorJSONHandleStop(qemuMonitor *mon, virJSONValue *data);
+void qemuMonitorJSONHandleResume(qemuMonitor *mon, virJSONValue *data);
+void qemuMonitorJSONHandleRTCChange(qemuMonitor *mon, virJSONValue *data);
+void qemuMonitorJSONHandleWatchdog(qemuMonitor *mon, virJSONValue *data);
+void qemuMonitorJSONHandleIOError(qemuMonitor *mon, virJSONValue *data);
+void qemuMonitorJSONHandleVNCConnect(qemuMonitor *mon, virJSONValue *data);
+void qemuMonitorJSONHandleVNCInitialize(qemuMonitor *mon, virJSONValue *data);
+void qemuMonitorJSONHandleVNCDisconnect(qemuMonitor *mon, virJSONValue *data);
+void qemuMonitorJSONHandleSPICEConnect(qemuMonitor *mon, virJSONValue *data);
+void qemuMonitorJSONHandleSPICEInitialize(qemuMonitor *mon, virJSONValue *data);
+void qemuMonitorJSONHandleSPICEDisconnect(qemuMonitor *mon, virJSONValue *data);
+void qemuMonitorJSONHandleTrayChange(qemuMonitor *mon, virJSONValue *data);
+void qemuMonitorJSONHandlePMWakeup(qemuMonitor *mon, virJSONValue *data);
+void qemuMonitorJSONHandlePMSuspend(qemuMonitor *mon, virJSONValue *data);
+void qemuMonitorJSONHandleJobStatusChange(qemuMonitor *mon, virJSONValue *data);
+void qemuMonitorJSONHandleBalloonChange(qemuMonitor *mon, virJSONValue *data);
+void qemuMonitorJSONHandlePMSuspendDisk(qemuMonitor *mon, virJSONValue *data);
+void qemuMonitorJSONHandleGuestCrashloaded(qemuMonitor *mon, virJSONValue *data);
+void qemuMonitorJSONHandleGuestPanic(qemuMonitor *mon, virJSONValue *data);
+void qemuMonitorJSONHandleDeviceDeleted(qemuMonitor *mon, virJSONValue *data);
+void qemuMonitorJSONHandleNicRxFilterChanged(qemuMonitor *mon, virJSONValue *data);
+void qemuMonitorJSONHandleSerialChange(qemuMonitor *mon, virJSONValue *data);
+void qemuMonitorJSONHandleSpiceMigrated(qemuMonitor *mon, virJSONValue *data);
+void qemuMonitorJSONHandleMigrationStatus(qemuMonitor *mon, virJSONValue *data);
+void qemuMonitorJSONHandleMigrationPass(qemuMonitor *mon, virJSONValue *data);
+void qemuMonitorJSONHandleAcpiOstInfo(qemuMonitor *mon, virJSONValue *data);
+void qemuMonitorJSONHandleBlockThreshold(qemuMonitor *mon, virJSONValue *data);
+void qemuMonitorJSONHandleDumpCompleted(qemuMonitor *mon, virJSONValue *data);
+void qemuMonitorJSONHandlePRManagerStatusChanged(qemuMonitor *mon, virJSONValue *data);
+void qemuMonitorJSONHandleRdmaGidStatusChanged(qemuMonitor *mon, virJSONValue *data);
+void qemuMonitorJSONHandleMemoryFailure(qemuMonitor *mon, virJSONValue *data);
+void qemuMonitorJSONHandleMemoryDeviceSizeChange(qemuMonitor *mon, virJSONValue *data);
+void qemuMonitorJSONHandleDeviceUnplugErr(qemuMonitor *mon, virJSONValue *data);
+void qemuMonitorJSONHandleNetdevStreamDisconnected(qemuMonitor *mon, virJSONValue *data);
+
int
qemuMonitorJSONIOProcessLine(qemuMonitor *mon,
const char *line,
--
2.34.1
On Tue, May 21, 2024 at 17:36:48 +0530, Rayhan Faizel wrote: > Currently, monitor event names are looked up using binary search which has > O(log(n)) time complexity. This can be optimized even further with a > compile-time static hash table generated by the gperf tool. As gperf ensures > perfect hashing, lookup times are guaranteed to be O(1). As a first point I'd like to ask if you are seeing any specific performance problems with the existing code and ideally elaborate in which cases. This is a non-trivial change and with a justification in this commit message I'm not really convinced that it's needed. Unless QEMU would be firing a massive amount of events it is unlikely that the lookup of the event will even have measurable impact. It's also very likely that the lookup of the event handler is overshadowed by the complexity of the actual handler, thus is the impact even measurable? > This patch also makes gperf a requirement for compiling libvirt if the QEMU > driver is enabled. Based on the above question I'm not persuaded that this is really justified at this point. Note that such change will also require update to the .spec. file libvirt ships in the repo. > > Signed-off-by: Rayhan Faizel <rayhan.faizel@gmail.com> > --- > docs/kbase/internals/qemu-event-handlers.rst | 13 +- > meson.build | 2 + > src/qemu/meson.build | 9 + > src/qemu/qemu_monitor_event.gperf | 68 ++++++++ > src/qemu/qemu_monitor_json.c | 171 +++++-------------- > src/qemu/qemu_monitor_json.h | 45 +++++ > 6 files changed, 170 insertions(+), 138 deletions(-) > create mode 100644 src/qemu/qemu_monitor_event.gperf
© 2016 - 2024 Red Hat, Inc.