[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [XEN PATCH 09/11] tools/libxenstat: Use json-c when available
From: Anthony PERARD <anthony.perard@xxxxxxxxxx> This is mainly a copy of the existing code in yajl and use json-c instead. Signed-off-by: Anthony PERARD <anthony.perard@xxxxxxxxxx> --- tools/libs/stat/Makefile | 3 +- tools/libs/stat/xenstat_qmp.c | 126 ++++++++++++++++++++++++++++++++-- 2 files changed, 121 insertions(+), 8 deletions(-) diff --git a/tools/libs/stat/Makefile b/tools/libs/stat/Makefile index a968eaff48..3f13cf07be 100644 --- a/tools/libs/stat/Makefile +++ b/tools/libs/stat/Makefile @@ -24,7 +24,8 @@ OBJS-$(CONFIG_SunOS) += xenstat_solaris.o OBJS-$(CONFIG_NetBSD) += xenstat_netbsd.o OBJS-$(CONFIG_FreeBSD) += xenstat_freebsd.o -LDLIBS-y += -lyajl +LDLIBS-y += $(YAJL_LIBS) +LDLIBS-y += $(LIBJSONC_LIBS) LDLIBS-$(CONFIG_SunOS) += -lkstat LDLIBS += $(LDLIBS-y) diff --git a/tools/libs/stat/xenstat_qmp.c b/tools/libs/stat/xenstat_qmp.c index 9909b9727e..21e321fffa 100644 --- a/tools/libs/stat/xenstat_qmp.c +++ b/tools/libs/stat/xenstat_qmp.c @@ -24,6 +24,10 @@ #include "xenstat_priv.h" +#ifdef HAVE_LIBJSONC +#include <json-c/json.h> + +#elif defined(HAVE_LIBYAJL) #ifdef HAVE_YAJL_YAJL_VERSION_H # include <yajl/yajl_version.h> #endif @@ -32,11 +36,13 @@ #if defined(YAJL_MAJOR) && (YAJL_MAJOR > 1) # define HAVE_YAJL_V2 1 #endif +#endif #ifdef HAVE_YAJL_V2 - #include <yajl/yajl_tree.h> +#endif +#if defined(HAVE_LIBJSONC) || defined(HAVE_YAJL_V2) static unsigned char *qmp_query(int, const char *); enum query_blockstats { @@ -76,9 +82,10 @@ enum query_block { "type": 'str' }]} */ -static char *qmp_get_block_image(xenstat_node *node, char *qmp_devname, int qfd) +static char *qmp_get_block_image(xenstat_node *node, const char *qmp_devname, int qfd) { - char *tmp, *file = NULL; + const char *tmp; + char *file = NULL; const char *query_block_cmd = "{ \"execute\": \"query-block\" }"; static const char *const qblock[] = { [ QMP_BLOCK_RETURN ] = "return", @@ -88,13 +95,56 @@ static char *qmp_get_block_image(xenstat_node *node, char *qmp_devname, int qfd) }; const char *ptr[] = {0, 0}; unsigned char *qmp_stats; - yajl_val info, ret_obj, dev_obj, n; int i; if ((qmp_stats = qmp_query(qfd, query_block_cmd)) == NULL) return NULL; +#ifdef HAVE_LIBJSONC + json_object *jso; + enum json_tokener_error error; + jso = json_tokener_parse_verbose((const char *)qmp_stats, &error); + free(qmp_stats); + if (jso == NULL) + return NULL; + + ptr[0] = qblock[QMP_BLOCK_RETURN]; /* "return" */ + json_object *ret_jso = json_object_object_get(jso, ptr[0]); + if (ret_jso == NULL) + goto done; + + for (i=0; i<json_object_array_length(ret_jso); i++) { + json_object *n = json_object_array_get_idx(ret_jso, i); + + ptr[0] = qblock[QMP_BLOCK_DEVICE]; /* "device" */ + json_object *dev_jso = json_object_object_get(n, ptr[0]); + if (dev_jso) { + tmp = json_object_get_string(dev_jso); + if (!tmp || strcmp(qmp_devname, tmp)) + continue; + } else { + continue; + } + + ptr[0] = qblock[QMP_INSERTED]; /* "inserted" */ + n = json_object_object_get(n, ptr[0]); + if (n) { + ptr[0] = qblock[QMP_FILE]; /* "file" */ + n = json_object_object_get(n, ptr[0]); + if (n && json_object_is_type(n, json_type_string)) { + tmp = json_object_get_string(n); + file = malloc(strlen(tmp)+1); + if (file != NULL) + strcpy(file, tmp); + goto done; + } + } + } +done: + json_object_put(jso); +#elif defined(HAVE_LIBYAJL) /* Use libyajl version 2.0.3 or newer for the tree parser feature with bug fixes */ + yajl_val info, ret_obj, dev_obj, n; info = yajl_tree_parse((char *)qmp_stats, NULL, 0); free(qmp_stats); if (info == NULL) @@ -132,12 +182,13 @@ static char *qmp_get_block_image(xenstat_node *node, char *qmp_devname, int qfd) } done: yajl_tree_free(info); +#endif return file; } /* Given a QMP device name, lookup the associated xenstore qdisk device id */ -static void lookup_xenstore_devid(xenstat_node * node, unsigned int domid, char *qmp_devname, +static void lookup_xenstore_devid(xenstat_node * node, unsigned int domid, const char *qmp_devname, int qfd, unsigned int *dev, unsigned int *sector_size) { char **dev_ids, *tmp, *ptr, *image, path[80]; @@ -191,7 +242,7 @@ static void lookup_xenstore_devid(xenstat_node * node, unsigned int domid, char /* Parse the stats buffer which contains I/O data for all the disks belonging to domid */ static void qmp_parse_stats(xenstat_node *node, unsigned int domid, unsigned char *stats_buf, int qfd) { - char *qmp_devname; + const char *qmp_devname; static const char *const qstats[] = { [ QMP_STATS_RETURN ] = "return", [ QMP_STATS_DEVICE ] = "device", @@ -202,12 +253,72 @@ static void qmp_parse_stats(xenstat_node *node, unsigned int domid, unsigned cha [ QMP_WR_OPERATIONS ] = "wr_operations", }; const char *ptr[] = {0, 0}; - yajl_val info, ret_obj, stats_obj, n; xenstat_vbd vbd; xenstat_domain *domain; unsigned int sector_size = 512; int i, j; +#ifdef HAVE_LIBJSONC + json_object *jso, *ret_jso, *stats_obj, *n; + enum json_tokener_error error; + + jso = json_tokener_parse_verbose((const char *)stats_buf, &error); + if (jso == NULL) + return; + + ptr[0] = qstats[QMP_STATS_RETURN]; /* "return" */ + ret_jso = json_object_object_get(jso, ptr[0]); + if (ret_jso == NULL) + goto done; + + /* Array of devices */ + for (i=0; i<json_object_array_length(ret_jso); i++) { + memset(&vbd, 0, sizeof(xenstat_vbd)); + qmp_devname = NULL; + stats_obj = json_object_array_get_idx(ret_jso, i); + + ptr[0] = qstats[QMP_STATS_DEVICE]; /* "device" */ + n = json_object_object_get(stats_obj, ptr[0]); + if (n) + qmp_devname = json_object_get_string(n); + + ptr[0] = qstats[QMP_STATS]; /* "stats" */ + stats_obj = json_object_object_get(stats_obj, ptr[0]); + if (stats_obj && json_object_is_type(stats_obj, json_type_object)) { + for (j=3; j<7; j++) { + ptr[0] = qstats[j]; + n = json_object_object_get(stats_obj, ptr[0]); + if (n && json_object_is_type(n, json_type_int)) { + switch(j) { + case QMP_RD_BYTES: /* "rd_bytes" */ + vbd.rd_sects = json_object_get_int64(n) / sector_size; + break; + case QMP_WR_BYTES: /* "wr_bytes" */ + vbd.wr_sects = json_object_get_int64(n) / sector_size; + break; + case QMP_RD_OPERATIONS: /* "rd_operations" */ + vbd.rd_reqs = json_object_get_int64(n); + break; + case QMP_WR_OPERATIONS: /* "wr_operations" */ + vbd.wr_reqs = json_object_get_int64(n); + break; + } + } + } + /* With the QMP device name, lookup the xenstore qdisk device ID and set vdb.dev */ + if (qmp_devname) + lookup_xenstore_devid(node, domid, qmp_devname, qfd, &vbd.dev, §or_size); + if ((domain = xenstat_node_domain(node, domid)) == NULL) + continue; + if ((xenstat_save_vbd(domain, &vbd)) == NULL) + goto done; + } + } +done: + json_object_put(jso); +#elif defined(HAVE_LIBYAJL) + yajl_val info, ret_obj, stats_obj, n; + /* Use libyajl version 2.0.3 or newer for the tree parser feature */ if ((info = yajl_tree_parse((char *)stats_buf, NULL, 0)) == NULL) return; @@ -260,6 +371,7 @@ static void qmp_parse_stats(xenstat_node *node, unsigned int domid, unsigned cha } done: yajl_tree_free(info); +#endif } /* Write a command via the QMP. Returns number of bytes written */ -- Anthony PERARD
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |