aboutsummaryrefslogtreecommitdiff
path: root/monitor/qmp-cmds.c
diff options
context:
space:
mode:
Diffstat (limited to 'monitor/qmp-cmds.c')
-rw-r--r--monitor/qmp-cmds.c155
1 files changed, 155 insertions, 0 deletions
diff --git a/monitor/qmp-cmds.c b/monitor/qmp-cmds.c
index 1ebb89f46c..7314cd813d 100644
--- a/monitor/qmp-cmds.c
+++ b/monitor/qmp-cmds.c
@@ -35,6 +35,7 @@
#include "qapi/qapi-commands-control.h"
#include "qapi/qapi-commands-machine.h"
#include "qapi/qapi-commands-misc.h"
+#include "qapi/qapi-commands-stats.h"
#include "qapi/qapi-commands-ui.h"
#include "qapi/type-helpers.h"
#include "qapi/qmp/qerror.h"
@@ -43,6 +44,7 @@
#include "hw/acpi/acpi_dev_interface.h"
#include "hw/intc/intc.h"
#include "hw/rdma/rdma.h"
+#include "monitor/stats.h"
NameInfo *qmp_query_name(Error **errp)
{
@@ -441,3 +443,156 @@ HumanReadableText *qmp_x_query_irq(Error **errp)
return human_readable_text_from_str(buf);
}
+
+typedef struct StatsCallbacks {
+ StatsProvider provider;
+ StatRetrieveFunc *stats_cb;
+ SchemaRetrieveFunc *schemas_cb;
+ QTAILQ_ENTRY(StatsCallbacks) next;
+} StatsCallbacks;
+
+static QTAILQ_HEAD(, StatsCallbacks) stats_callbacks =
+ QTAILQ_HEAD_INITIALIZER(stats_callbacks);
+
+void add_stats_callbacks(StatsProvider provider,
+ StatRetrieveFunc *stats_fn,
+ SchemaRetrieveFunc *schemas_fn)
+{
+ StatsCallbacks *entry = g_new(StatsCallbacks, 1);
+ entry->provider = provider;
+ entry->stats_cb = stats_fn;
+ entry->schemas_cb = schemas_fn;
+
+ QTAILQ_INSERT_TAIL(&stats_callbacks, entry, next);
+}
+
+static bool invoke_stats_cb(StatsCallbacks *entry,
+ StatsResultList **stats_results,
+ StatsFilter *filter, StatsRequest *request,
+ Error **errp)
+{
+ strList *targets = NULL;
+ strList *names = NULL;
+ ERRP_GUARD();
+
+ if (request) {
+ if (request->provider != entry->provider) {
+ return true;
+ }
+ if (request->has_names && !request->names) {
+ return true;
+ }
+ names = request->has_names ? request->names : NULL;
+ }
+
+ switch (filter->target) {
+ case STATS_TARGET_VM:
+ break;
+ case STATS_TARGET_VCPU:
+ if (filter->u.vcpu.has_vcpus) {
+ if (!filter->u.vcpu.vcpus) {
+ /* No targets allowed? Return no statistics. */
+ return true;
+ }
+ targets = filter->u.vcpu.vcpus;
+ }
+ break;
+ default:
+ abort();
+ }
+
+ entry->stats_cb(stats_results, filter->target, names, targets, errp);
+ if (*errp) {
+ qapi_free_StatsResultList(*stats_results);
+ *stats_results = NULL;
+ return false;
+ }
+ return true;
+}
+
+StatsResultList *qmp_query_stats(StatsFilter *filter, Error **errp)
+{
+ StatsResultList *stats_results = NULL;
+ StatsCallbacks *entry;
+ StatsRequestList *request;
+
+ QTAILQ_FOREACH(entry, &stats_callbacks, next) {
+ if (filter->has_providers) {
+ for (request = filter->providers; request; request = request->next) {
+ if (!invoke_stats_cb(entry, &stats_results, filter,
+ request->value, errp)) {
+ break;
+ }
+ }
+ } else {
+ if (!invoke_stats_cb(entry, &stats_results, filter, NULL, errp)) {
+ break;
+ }
+ }
+ }
+
+ return stats_results;
+}
+
+StatsSchemaList *qmp_query_stats_schemas(bool has_provider,
+ StatsProvider provider,
+ Error **errp)
+{
+ StatsSchemaList *stats_results = NULL;
+ StatsCallbacks *entry;
+ ERRP_GUARD();
+
+ QTAILQ_FOREACH(entry, &stats_callbacks, next) {
+ if (!has_provider || provider == entry->provider) {
+ entry->schemas_cb(&stats_results, errp);
+ if (*errp) {
+ qapi_free_StatsSchemaList(stats_results);
+ return NULL;
+ }
+ }
+ }
+
+ return stats_results;
+}
+
+void add_stats_entry(StatsResultList **stats_results, StatsProvider provider,
+ const char *qom_path, StatsList *stats_list)
+{
+ StatsResult *entry = g_new0(StatsResult, 1);
+
+ entry->provider = provider;
+ if (qom_path) {
+ entry->has_qom_path = true;
+ entry->qom_path = g_strdup(qom_path);
+ }
+ entry->stats = stats_list;
+
+ QAPI_LIST_PREPEND(*stats_results, entry);
+}
+
+void add_stats_schema(StatsSchemaList **schema_results,
+ StatsProvider provider, StatsTarget target,
+ StatsSchemaValueList *stats_list)
+{
+ StatsSchema *entry = g_new0(StatsSchema, 1);
+
+ entry->provider = provider;
+ entry->target = target;
+ entry->stats = stats_list;
+ QAPI_LIST_PREPEND(*schema_results, entry);
+}
+
+bool apply_str_list_filter(const char *string, strList *list)
+{
+ strList *str_list = NULL;
+
+ if (!list) {
+ return true;
+ }
+ for (str_list = list; str_list; str_list = str_list->next) {
+ if (g_str_equal(string, str_list->value)) {
+ return true;
+ }
+ }
+ return false;
+}