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