34b321
From 88ee76fed6344de6cede3bfbb3873423e9a90333 Mon Sep 17 00:00:00 2001
34b321
From: Markus Armbruster <armbru@redhat.com>
34b321
Date: Wed, 27 Jul 2016 07:35:09 +0200
34b321
Subject: [PATCH 11/16] qjson: store tokens in a GQueue
34b321
34b321
RH-Author: Markus Armbruster <armbru@redhat.com>
34b321
Message-id: <1469604913-12442-13-git-send-email-armbru@redhat.com>
34b321
Patchwork-id: 71478
34b321
O-Subject: [RHEL-7.3 qemu-kvm PATCH v2 11/15] qjson: store tokens in a GQueue
34b321
Bugzilla: 1276036
34b321
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
34b321
RH-Acked-by: John Snow <jsnow@redhat.com>
34b321
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
34b321
34b321
From: Paolo Bonzini <pbonzini@redhat.com>
34b321
34b321
Even though we still have the "streamer" concept, the tokens can now
34b321
be deleted as they are read.  While doing so convert from QList to
34b321
GQueue, since the next step will make tokens not a QObject and we
34b321
will have to do the conversion anyway.
34b321
34b321
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
34b321
Message-Id: <1448300659-23559-4-git-send-email-pbonzini@redhat.com>
34b321
Signed-off-by: Markus Armbruster <armbru@redhat.com>
34b321
Reviewed-by: Eric Blake <eblake@redhat.com>
34b321
(cherry picked from commit 95385fe9ace7db156b924da6b6f5c9082b68ba68)
34b321
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
34b321
34b321
Conflicts:
34b321
	monitor.c
34b321
34b321
Trivial context difference because we lack a small cleanup part of the
34b321
(fairly invasive) series b821cbe..489653b.
34b321
34b321
Signed-off-by: Markus Armbruster <armbru@redhat.com>
34b321
---
34b321
 include/qapi/qmp/json-parser.h   |  4 +--
34b321
 include/qapi/qmp/json-streamer.h |  8 ++---
34b321
 monitor.c                        |  2 +-
34b321
 qga/main.c                       |  2 +-
34b321
 qobject/json-parser.c            | 65 +++++++++++++---------------------------
34b321
 qobject/json-streamer.c          | 25 +++++++++-------
34b321
 qobject/qjson.c                  |  2 +-
34b321
 tests/libqtest.c                 |  2 +-
34b321
 8 files changed, 45 insertions(+), 65 deletions(-)
34b321
34b321
diff --git a/include/qapi/qmp/json-parser.h b/include/qapi/qmp/json-parser.h
34b321
index 44d88f3..fea89f8 100644
34b321
--- a/include/qapi/qmp/json-parser.h
34b321
+++ b/include/qapi/qmp/json-parser.h
34b321
@@ -18,7 +18,7 @@
34b321
 #include "qapi/qmp/qlist.h"
34b321
 #include "qapi/error.h"
34b321
 
34b321
-QObject *json_parser_parse(QList *tokens, va_list *ap);
34b321
-QObject *json_parser_parse_err(QList *tokens, va_list *ap, Error **errp);
34b321
+QObject *json_parser_parse(GQueue *tokens, va_list *ap);
34b321
+QObject *json_parser_parse_err(GQueue *tokens, va_list *ap, Error **errp);
34b321
 
34b321
 #endif
34b321
diff --git a/include/qapi/qmp/json-streamer.h b/include/qapi/qmp/json-streamer.h
34b321
index e901144..e9f2937 100644
34b321
--- a/include/qapi/qmp/json-streamer.h
34b321
+++ b/include/qapi/qmp/json-streamer.h
34b321
@@ -15,21 +15,21 @@
34b321
 #define QEMU_JSON_STREAMER_H
34b321
 
34b321
 #include <stdint.h>
34b321
-#include "qapi/qmp/qlist.h"
34b321
+#include "glib-compat.h"
34b321
 #include "qapi/qmp/json-lexer.h"
34b321
 
34b321
 typedef struct JSONMessageParser
34b321
 {
34b321
-    void (*emit)(struct JSONMessageParser *parser, QList *tokens);
34b321
+    void (*emit)(struct JSONMessageParser *parser, GQueue *tokens);
34b321
     JSONLexer lexer;
34b321
     int brace_count;
34b321
     int bracket_count;
34b321
-    QList *tokens;
34b321
+    GQueue *tokens;
34b321
     uint64_t token_size;
34b321
 } JSONMessageParser;
34b321
 
34b321
 void json_message_parser_init(JSONMessageParser *parser,
34b321
-                              void (*func)(JSONMessageParser *, QList *));
34b321
+                              void (*func)(JSONMessageParser *, GQueue *));
34b321
 
34b321
 int json_message_parser_feed(JSONMessageParser *parser,
34b321
                              const char *buffer, size_t size);
34b321
diff --git a/monitor.c b/monitor.c
34b321
index 33c5bc8..1b28ff3 100644
34b321
--- a/monitor.c
34b321
+++ b/monitor.c
34b321
@@ -4514,7 +4514,7 @@ static void qmp_call_cmd(Monitor *mon, const mon_cmd_t *cmd,
34b321
     qobject_decref(data);
34b321
 }
34b321
 
34b321
-static void handle_qmp_command(JSONMessageParser *parser, QList *tokens)
34b321
+static void handle_qmp_command(JSONMessageParser *parser, GQueue *tokens)
34b321
 {
34b321
     int err;
34b321
     QObject *obj;
34b321
diff --git a/qga/main.c b/qga/main.c
34b321
index 0e04e73..7e8f9a0 100644
34b321
--- a/qga/main.c
34b321
+++ b/qga/main.c
34b321
@@ -569,7 +569,7 @@ static void process_command(GAState *s, QDict *req)
34b321
 }
34b321
 
34b321
 /* handle requests/control events coming in over the channel */
34b321
-static void process_event(JSONMessageParser *parser, QList *tokens)
34b321
+static void process_event(JSONMessageParser *parser, GQueue *tokens)
34b321
 {
34b321
     GAState *s = container_of(parser, GAState, parser);
34b321
     QObject *obj;
34b321
diff --git a/qobject/json-parser.c b/qobject/json-parser.c
34b321
index b242fba..6e5e257 100644
34b321
--- a/qobject/json-parser.c
34b321
+++ b/qobject/json-parser.c
34b321
@@ -27,11 +27,8 @@
34b321
 typedef struct JSONParserContext
34b321
 {
34b321
     Error *err;
34b321
-    struct {
34b321
-        QObject **buf;
34b321
-        size_t pos;
34b321
-        size_t count;
34b321
-    } tokens;
34b321
+    QObject *current;
34b321
+    GQueue *buf;
34b321
 } JSONParserContext;
34b321
 
34b321
 #define BUG_ON(cond) assert(!(cond))
34b321
@@ -244,56 +241,34 @@ out:
34b321
     return NULL;
34b321
 }
34b321
 
34b321
+/* Note: unless the token object returned by parser_context_peek_token
34b321
+ * or parser_context_pop_token is explicitly incref'd, it will be
34b321
+ * deleted as soon as parser_context_pop_token is called again.
34b321
+ */
34b321
 static QObject *parser_context_pop_token(JSONParserContext *ctxt)
34b321
 {
34b321
-    QObject *token;
34b321
-    g_assert(ctxt->tokens.pos < ctxt->tokens.count);
34b321
-    token = ctxt->tokens.buf[ctxt->tokens.pos];
34b321
-    ctxt->tokens.pos++;
34b321
-    return token;
34b321
+    qobject_decref(ctxt->current);
34b321
+    assert(!g_queue_is_empty(ctxt->buf));
34b321
+    ctxt->current = g_queue_pop_head(ctxt->buf);
34b321
+    return ctxt->current;
34b321
 }
34b321
 
34b321
-/* Note: parser_context_{peek|pop}_token do not increment the
34b321
- * token object's refcount. In both cases the references will continue
34b321
- * to be tracked and cleaned up in parser_context_free(), so do not
34b321
- * attempt to free the token object.
34b321
- */
34b321
 static QObject *parser_context_peek_token(JSONParserContext *ctxt)
34b321
 {
34b321
-    QObject *token;
34b321
-    g_assert(ctxt->tokens.pos < ctxt->tokens.count);
34b321
-    token = ctxt->tokens.buf[ctxt->tokens.pos];
34b321
-    return token;
34b321
-}
34b321
-
34b321
-static void tokens_append_from_iter(QObject *obj, void *opaque)
34b321
-{
34b321
-    JSONParserContext *ctxt = opaque;
34b321
-    g_assert(ctxt->tokens.pos < ctxt->tokens.count);
34b321
-    ctxt->tokens.buf[ctxt->tokens.pos++] = obj;
34b321
-    qobject_incref(obj);
34b321
+    assert(!g_queue_is_empty(ctxt->buf));
34b321
+    return g_queue_peek_head(ctxt->buf);
34b321
 }
34b321
 
34b321
-static JSONParserContext *parser_context_new(QList *tokens)
34b321
+static JSONParserContext *parser_context_new(GQueue *tokens)
34b321
 {
34b321
     JSONParserContext *ctxt;
34b321
-    size_t count;
34b321
 
34b321
     if (!tokens) {
34b321
         return NULL;
34b321
     }
34b321
 
34b321
-    count = qlist_size(tokens);
34b321
-    if (count == 0) {
34b321
-        return NULL;
34b321
-    }
34b321
-
34b321
     ctxt = g_malloc0(sizeof(JSONParserContext));
34b321
-    ctxt->tokens.pos = 0;
34b321
-    ctxt->tokens.count = count;
34b321
-    ctxt->tokens.buf = g_malloc(count * sizeof(QObject *));
34b321
-    qlist_iter(tokens, tokens_append_from_iter, ctxt);
34b321
-    ctxt->tokens.pos = 0;
34b321
+    ctxt->buf = tokens;
34b321
 
34b321
     return ctxt;
34b321
 }
34b321
@@ -301,12 +276,12 @@ static JSONParserContext *parser_context_new(QList *tokens)
34b321
 /* to support error propagation, ctxt->err must be freed separately */
34b321
 static void parser_context_free(JSONParserContext *ctxt)
34b321
 {
34b321
-    int i;
34b321
     if (ctxt) {
34b321
-        for (i = 0; i < ctxt->tokens.count; i++) {
34b321
-            qobject_decref(ctxt->tokens.buf[i]);
34b321
+        while (!g_queue_is_empty(ctxt->buf)) {
34b321
+            parser_context_pop_token(ctxt);
34b321
         }
34b321
-        g_free(ctxt->tokens.buf);
34b321
+        qobject_decref(ctxt->current);
34b321
+        g_queue_free(ctxt->buf);
34b321
         g_free(ctxt);
34b321
     }
34b321
 }
34b321
@@ -597,12 +572,12 @@ static QObject *parse_value(JSONParserContext *ctxt, va_list *ap)
34b321
     }
34b321
 }
34b321
 
34b321
-QObject *json_parser_parse(QList *tokens, va_list *ap)
34b321
+QObject *json_parser_parse(GQueue *tokens, va_list *ap)
34b321
 {
34b321
     return json_parser_parse_err(tokens, ap, NULL);
34b321
 }
34b321
 
34b321
-QObject *json_parser_parse_err(QList *tokens, va_list *ap, Error **errp)
34b321
+QObject *json_parser_parse_err(GQueue *tokens, va_list *ap, Error **errp)
34b321
 {
34b321
     JSONParserContext *ctxt = parser_context_new(tokens);
34b321
     QObject *result;
34b321
diff --git a/qobject/json-streamer.c b/qobject/json-streamer.c
34b321
index 7292f3a..f7a3e78 100644
34b321
--- a/qobject/json-streamer.c
34b321
+++ b/qobject/json-streamer.c
34b321
@@ -22,6 +22,14 @@
34b321
 #define MAX_TOKEN_SIZE (64ULL << 20)
34b321
 #define MAX_NESTING (1ULL << 10)
34b321
 
34b321
+static void json_message_free_tokens(JSONMessageParser *parser)
34b321
+{
34b321
+    if (parser->tokens) {
34b321
+        g_queue_free(parser->tokens);
34b321
+        parser->tokens = NULL;
34b321
+    }
34b321
+}
34b321
+
34b321
 static void json_message_process_token(JSONLexer *lexer, GString *input,
34b321
                                        JSONTokenType type, int x, int y)
34b321
 {
34b321
@@ -53,7 +61,7 @@ static void json_message_process_token(JSONLexer *lexer, GString *input,
34b321
 
34b321
     parser->token_size += input->len;
34b321
 
34b321
-    qlist_append(parser->tokens, dict);
34b321
+    g_queue_push_tail(parser->tokens, dict);
34b321
 
34b321
     if (type == JSON_ERROR) {
34b321
         goto out_emit_bad;
34b321
@@ -77,27 +85,24 @@ out_emit_bad:
34b321
      * Clear out token list and tell the parser to emit an error
34b321
      * indication by passing it a NULL list
34b321
      */
34b321
-    QDECREF(parser->tokens);
34b321
-    parser->tokens = NULL;
34b321
+    json_message_free_tokens(parser);
34b321
 out_emit:
34b321
     /* send current list of tokens to parser and reset tokenizer */
34b321
     parser->brace_count = 0;
34b321
     parser->bracket_count = 0;
34b321
+    /* parser->emit takes ownership of parser->tokens.  */
34b321
     parser->emit(parser, parser->tokens);
34b321
-    if (parser->tokens) {
34b321
-        QDECREF(parser->tokens);
34b321
-    }
34b321
-    parser->tokens = qlist_new();
34b321
+    parser->tokens = g_queue_new();
34b321
     parser->token_size = 0;
34b321
 }
34b321
 
34b321
 void json_message_parser_init(JSONMessageParser *parser,
34b321
-                              void (*func)(JSONMessageParser *, QList *))
34b321
+                              void (*func)(JSONMessageParser *, GQueue *))
34b321
 {
34b321
     parser->emit = func;
34b321
     parser->brace_count = 0;
34b321
     parser->bracket_count = 0;
34b321
-    parser->tokens = qlist_new();
34b321
+    parser->tokens = g_queue_new();
34b321
     parser->token_size = 0;
34b321
 
34b321
     json_lexer_init(&parser->lexer, json_message_process_token);
34b321
@@ -117,5 +122,5 @@ int json_message_parser_flush(JSONMessageParser *parser)
34b321
 void json_message_parser_destroy(JSONMessageParser *parser)
34b321
 {
34b321
     json_lexer_destroy(&parser->lexer);
34b321
-    QDECREF(parser->tokens);
34b321
+    json_message_free_tokens(parser);
34b321
 }
34b321
diff --git a/qobject/qjson.c b/qobject/qjson.c
34b321
index 6cf2511..fdc274a 100644
34b321
--- a/qobject/qjson.c
34b321
+++ b/qobject/qjson.c
34b321
@@ -28,7 +28,7 @@ typedef struct JSONParsingState
34b321
     QObject *result;
34b321
 } JSONParsingState;
34b321
 
34b321
-static void parse_json(JSONMessageParser *parser, QList *tokens)
34b321
+static void parse_json(JSONMessageParser *parser, GQueue *tokens)
34b321
 {
34b321
     JSONParsingState *s = container_of(parser, JSONParsingState, parser);
34b321
     s->result = json_parser_parse(tokens, s->ap);
34b321
diff --git a/tests/libqtest.c b/tests/libqtest.c
34b321
index 359d571..69b7cd6 100644
34b321
--- a/tests/libqtest.c
34b321
+++ b/tests/libqtest.c
34b321
@@ -299,7 +299,7 @@ typedef struct {
34b321
     QDict *response;
34b321
 } QMPResponseParser;
34b321
 
34b321
-static void qmp_response(JSONMessageParser *parser, QList *tokens)
34b321
+static void qmp_response(JSONMessageParser *parser, GQueue *tokens)
34b321
 {
34b321
     QMPResponseParser *qmp = container_of(parser, QMPResponseParser, parser);
34b321
     QObject *obj;
34b321
-- 
34b321
1.8.3.1
34b321