qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH 0/9]: QError v3
@ 2009-11-12 20:42 Luiz Capitulino
  2009-11-12 20:42 ` [Qemu-devel] [PATCH 1/9] QJSON: Introduce qobject_from_json_va() Luiz Capitulino
                   ` (8 more replies)
  0 siblings, 9 replies; 12+ messages in thread
From: Luiz Capitulino @ 2009-11-12 20:42 UTC (permalink / raw)
  To: qemu-devel; +Cc: aliguori, kraxel, armbru

 Hi,

 This is a new QError version which implements what has been suggested
by Anthony in this email:

http://lists.gnu.org/archive/html/qemu-devel/2009-11/msg00601.html

 Basically, the error table is back and qemu_error_new() calls are like
this:

qemu_error_new(QERR_DEVICE_NOT_FOUND, driver);

 Thanks.

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [Qemu-devel] [PATCH 1/9] QJSON: Introduce qobject_from_json_va()
  2009-11-12 20:42 [Qemu-devel] [PATCH 0/9]: QError v3 Luiz Capitulino
@ 2009-11-12 20:42 ` Luiz Capitulino
  2009-11-12 21:39   ` Anthony Liguori
  2009-11-12 20:42 ` [Qemu-devel] [PATCH 2/9] QString: Introduce qstring_append_chr() Luiz Capitulino
                   ` (7 subsequent siblings)
  8 siblings, 1 reply; 12+ messages in thread
From: Luiz Capitulino @ 2009-11-12 20:42 UTC (permalink / raw)
  To: qemu-devel; +Cc: aliguori, kraxel, armbru

Accepts a va_list, will be used by QError.

Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
---
 qjson.c |   14 ++++++++++++++
 qjson.h |    2 ++
 2 files changed, 16 insertions(+), 0 deletions(-)

diff --git a/qjson.c b/qjson.c
index 7270909..491b61e 100644
--- a/qjson.c
+++ b/qjson.c
@@ -64,6 +64,20 @@ QObject *qobject_from_jsonf(const char *string, ...)
     return state.result;
 }
 
+QObject *qobject_from_json_va(const char *string, va_list *ap)
+{
+    JSONParsingState state = {};
+
+    state.ap = ap;
+
+    json_message_parser_init(&state.parser, parse_json);
+    json_message_parser_feed(&state.parser, string, strlen(string));
+    json_message_parser_flush(&state.parser);
+    json_message_parser_destroy(&state.parser);
+
+    return state.result;
+}
+
 typedef struct ToJsonIterState
 {
     int count;
diff --git a/qjson.h b/qjson.h
index 7fce742..8b89e41 100644
--- a/qjson.h
+++ b/qjson.h
@@ -14,12 +14,14 @@
 #ifndef QJSON_H
 #define QJSON_H
 
+#include <stdarg.h>
 #include "qobject.h"
 #include "qstring.h"
 
 QObject *qobject_from_json(const char *string);
 QObject *qobject_from_jsonf(const char *string, ...)
     __attribute__((__format__ (__printf__, 1, 2)));
+QObject *qobject_from_json_va(const char *string, va_list *ap);
 
 QString *qobject_to_json(const QObject *obj);
 
-- 
1.6.5.2.155.gbb47

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [Qemu-devel] [PATCH 2/9] QString: Introduce qstring_append_chr()
  2009-11-12 20:42 [Qemu-devel] [PATCH 0/9]: QError v3 Luiz Capitulino
  2009-11-12 20:42 ` [Qemu-devel] [PATCH 1/9] QJSON: Introduce qobject_from_json_va() Luiz Capitulino
@ 2009-11-12 20:42 ` Luiz Capitulino
  2009-11-12 20:42 ` [Qemu-devel] [PATCH 3/9] QString: Introduce qstring_append_int() Luiz Capitulino
                   ` (6 subsequent siblings)
  8 siblings, 0 replies; 12+ messages in thread
From: Luiz Capitulino @ 2009-11-12 20:42 UTC (permalink / raw)
  To: qemu-devel; +Cc: aliguori, kraxel, armbru

It appends a C char to a QString.

Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
---
 qstring.c |   24 +++++++++++++++++++-----
 qstring.h |    1 +
 2 files changed, 20 insertions(+), 5 deletions(-)

diff --git a/qstring.c b/qstring.c
index 441a9e6..e422bd9 100644
--- a/qstring.c
+++ b/qstring.c
@@ -53,25 +53,39 @@ QString *qstring_from_str(const char *str)
     return qstring;
 }
 
-/* qstring_append(): Append a C string to a QString
- */
-void qstring_append(QString *qstring, const char *str)
+static void capacity_increase(QString *qstring, size_t len)
 {
-    size_t len = strlen(str);
-
     if (qstring->capacity < (qstring->length + len)) {
         qstring->capacity += len;
         qstring->capacity *= 2; /* use exponential growth */
 
         qstring->string = qemu_realloc(qstring->string, qstring->capacity + 1);
     }
+}
+
+/* qstring_append(): Append a C string to a QString
+ */
+void qstring_append(QString *qstring, const char *str)
+{
+    size_t len = strlen(str);
 
+    capacity_increase(qstring, len);
     memcpy(qstring->string + qstring->length, str, len);
     qstring->length += len;
     qstring->string[qstring->length] = 0;
 }
 
 /**
+ * qstring_append_chr(): Append a C char to a QString
+ */
+void qstring_append_chr(QString *qstring, int c)
+{
+    capacity_increase(qstring, 1);
+    qstring->string[qstring->length++] = c;
+    qstring->string[qstring->length] = 0;
+}
+
+/**
  * qobject_to_qstring(): Convert a QObject to a QString
  */
 QString *qobject_to_qstring(const QObject *obj)
diff --git a/qstring.h b/qstring.h
index 65905d4..43581de 100644
--- a/qstring.h
+++ b/qstring.h
@@ -14,6 +14,7 @@ QString *qstring_new(void);
 QString *qstring_from_str(const char *str);
 const char *qstring_get_str(const QString *qstring);
 void qstring_append(QString *qstring, const char *str);
+void qstring_append_chr(QString *qstring, int c);
 QString *qobject_to_qstring(const QObject *obj);
 
 #endif /* QSTRING_H */
-- 
1.6.5.2.155.gbb47

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [Qemu-devel] [PATCH 3/9] QString: Introduce qstring_append_int()
  2009-11-12 20:42 [Qemu-devel] [PATCH 0/9]: QError v3 Luiz Capitulino
  2009-11-12 20:42 ` [Qemu-devel] [PATCH 1/9] QJSON: Introduce qobject_from_json_va() Luiz Capitulino
  2009-11-12 20:42 ` [Qemu-devel] [PATCH 2/9] QString: Introduce qstring_append_chr() Luiz Capitulino
@ 2009-11-12 20:42 ` Luiz Capitulino
  2009-11-12 20:42 ` [Qemu-devel] [PATCH 4/9] Add qstring_append_chr() unit-test Luiz Capitulino
                   ` (5 subsequent siblings)
  8 siblings, 0 replies; 12+ messages in thread
From: Luiz Capitulino @ 2009-11-12 20:42 UTC (permalink / raw)
  To: qemu-devel; +Cc: aliguori, kraxel, armbru

Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
---
 qstring.c |    8 ++++++++
 qstring.h |    2 ++
 2 files changed, 10 insertions(+), 0 deletions(-)

diff --git a/qstring.c b/qstring.c
index e422bd9..ad17769 100644
--- a/qstring.c
+++ b/qstring.c
@@ -75,6 +75,14 @@ void qstring_append(QString *qstring, const char *str)
     qstring->string[qstring->length] = 0;
 }
 
+void qstring_append_int(QString *qstring, int64_t value)
+{
+    char num[32];
+
+    snprintf(num, sizeof(num), "%" PRId64, value);
+    qstring_append(qstring, num);
+}
+
 /**
  * qstring_append_chr(): Append a C char to a QString
  */
diff --git a/qstring.h b/qstring.h
index 43581de..c065331 100644
--- a/qstring.h
+++ b/qstring.h
@@ -1,6 +1,7 @@
 #ifndef QSTRING_H
 #define QSTRING_H
 
+#include <stdint.h>
 #include "qobject.h"
 
 typedef struct QString {
@@ -13,6 +14,7 @@ typedef struct QString {
 QString *qstring_new(void);
 QString *qstring_from_str(const char *str);
 const char *qstring_get_str(const QString *qstring);
+void qstring_append_int(QString *qstring, int64_t value);
 void qstring_append(QString *qstring, const char *str);
 void qstring_append_chr(QString *qstring, int c);
 QString *qobject_to_qstring(const QObject *obj);
-- 
1.6.5.2.155.gbb47

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [Qemu-devel] [PATCH 4/9] Add qstring_append_chr() unit-test
  2009-11-12 20:42 [Qemu-devel] [PATCH 0/9]: QError v3 Luiz Capitulino
                   ` (2 preceding siblings ...)
  2009-11-12 20:42 ` [Qemu-devel] [PATCH 3/9] QString: Introduce qstring_append_int() Luiz Capitulino
@ 2009-11-12 20:42 ` Luiz Capitulino
  2009-11-12 20:42 ` [Qemu-devel] [PATCH 5/9] Introduce QError Luiz Capitulino
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 12+ messages in thread
From: Luiz Capitulino @ 2009-11-12 20:42 UTC (permalink / raw)
  To: qemu-devel; +Cc: aliguori, kraxel, armbru

Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
---
 check-qstring.c |   17 +++++++++++++++++
 1 files changed, 17 insertions(+), 0 deletions(-)

diff --git a/check-qstring.c b/check-qstring.c
index ea4dfd0..412038a 100644
--- a/check-qstring.c
+++ b/check-qstring.c
@@ -55,6 +55,22 @@ START_TEST(qstring_get_str_test)
 }
 END_TEST
 
+START_TEST(qstring_append_chr_test)
+{
+    int i;
+    QString *qstring;
+    const char *str = "qstring append char unit-test";
+
+    qstring = qstring_new();
+
+    for (i = 0; str[i]; i++)
+        qstring_append_chr(qstring, str[i]);
+
+    fail_unless(strcmp(str, qstring_get_str(qstring)) == 0);
+    QDECREF(qstring);
+}
+END_TEST
+
 START_TEST(qobject_to_qstring_test)
 {
     QString *qstring;
@@ -78,6 +94,7 @@ static Suite *qstring_suite(void)
     tcase_add_test(qstring_public_tcase, qstring_from_str_test);
     tcase_add_test(qstring_public_tcase, qstring_destroy_test);
     tcase_add_test(qstring_public_tcase, qstring_get_str_test);
+    tcase_add_test(qstring_public_tcase, qstring_append_chr_test);
     tcase_add_test(qstring_public_tcase, qobject_to_qstring_test);
 
     return s;
-- 
1.6.5.2.155.gbb47

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [Qemu-devel] [PATCH 5/9] Introduce QError
  2009-11-12 20:42 [Qemu-devel] [PATCH 0/9]: QError v3 Luiz Capitulino
                   ` (3 preceding siblings ...)
  2009-11-12 20:42 ` [Qemu-devel] [PATCH 4/9] Add qstring_append_chr() unit-test Luiz Capitulino
@ 2009-11-12 20:42 ` Luiz Capitulino
  2009-11-12 20:42 ` [Qemu-devel] [PATCH 6/9] QJSON: Fix compile error Luiz Capitulino
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 12+ messages in thread
From: Luiz Capitulino @ 2009-11-12 20:42 UTC (permalink / raw)
  To: qemu-devel; +Cc: aliguori, kraxel, armbru

QError is a high-level data type which represents an exception
in QEMU, it stores the following error information:

- class          Error class name (eg. "ServiceUnavailable")
- description    A detailed error description, which may contain
                 references to run-time error data
- filename       The file name of where the error occurred
- line number    The exact line number of the error
- run-time data  Any run-time error data

This commit adds the basic interface plus two error classes, one
for 'device not found' errors and another one for 'service unavailable'
errors.

Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
---
 Makefile  |    2 +-
 qerror.c  |  283 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 qerror.h  |   46 ++++++++++
 qobject.h |    1 +
 4 files changed, 331 insertions(+), 1 deletions(-)
 create mode 100644 qerror.c
 create mode 100644 qerror.h

diff --git a/Makefile b/Makefile
index 4998226..98625e7 100644
--- a/Makefile
+++ b/Makefile
@@ -138,7 +138,7 @@ obj-y += qemu-char.o aio.o savevm.o
 obj-y += msmouse.o ps2.o
 obj-y += qdev.o qdev-properties.o
 obj-y += qint.o qstring.o qdict.o qlist.o qfloat.o qbool.o json-lexer.o
-obj-y += json-streamer.o json-parser.o qjson.o
+obj-y += json-streamer.o json-parser.o qjson.o qerror.o
 obj-y += qemu-config.o
 
 obj-$(CONFIG_BRLAPI) += baum.o
diff --git a/qerror.c b/qerror.c
new file mode 100644
index 0000000..91b0f72
--- /dev/null
+++ b/qerror.c
@@ -0,0 +1,283 @@
+/*
+ * QError: QEMU Error data-type.
+ *
+ * Copyright (C) 2009 Red Hat Inc.
+ *
+ * Authors:
+ *  Luiz Capitulino <lcapitulino@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ */
+#include "qjson.h"
+#include "qerror.h"
+#include "qstring.h"
+#include "sysemu.h"
+#include "qemu-common.h"
+
+static void qerror_destroy_obj(QObject *obj);
+
+static const QType qerror_type = {
+    .code = QTYPE_QERROR,
+    .destroy = qerror_destroy_obj,
+};
+
+/**
+ * The 'desc' parameter is a printf-like string, the format of the format
+ * string is:
+ *
+ * %(KEY)TYPE
+ *
+ * Where KEY is a QDict key and TYPE is the type of its value, KEY and
+ * its value must be passed to qerror_from_info().
+ *
+ * Valid types are:
+ *
+ * s  (string)
+ * d  (integer)
+ *
+ * Example:
+ *
+ * "foo error on device: %(device)s slot: %(slot_nr)d"
+ *
+ * A single percent sign can be printed if followed by a second one,
+ * for example:
+ *
+ * "running out of foo: %(foo)d%%"
+ */
+const QErrorStringTable qerror_table[] = {
+    {
+        .error_fmt   = QERR_DEVICE_NOT_FOUND,
+        .desc        = "device \"%(name)s\" not found",
+    },
+    {
+        .error_fmt   = QERR_SERVICE_UNAVAILABLE,
+        .desc        = "%(reason)s",
+    },
+    {}
+};
+
+/**
+ * qerror_new(): Create a new QError
+ *
+ * Return strong reference.
+ */
+QError *qerror_new(void)
+{
+    QError *qerr;
+
+    qerr = qemu_mallocz(sizeof(*qerr));
+    QOBJECT_INIT(qerr, &qerror_type);
+
+    return qerr;
+}
+
+static void qerror_abort(const QError *qerr, const char *fmt, ...)
+{
+    va_list ap;
+
+    fprintf(stderr, "qerror: ");
+
+    va_start(ap, fmt);
+    vfprintf(stderr, fmt, ap);
+    va_end(ap);
+
+    fprintf(stderr, " call at %s:%d\n", qerr->file, qerr->linenr);
+    abort();
+}
+
+static void qerror_set_data(QError *qerr, const char *fmt, va_list *va)
+{
+    QObject *obj;
+
+    obj = qobject_from_json_va(fmt, va);
+    if (!obj) {
+        qerror_abort(qerr, "invalid format '%s'", fmt);
+    }
+    if (qobject_type(obj) != QTYPE_QDICT) {
+        qerror_abort(qerr, "error format is not a QDict '%s'", fmt);
+    }
+
+    qerr->error = qobject_to_qdict(obj);
+
+    obj = qdict_get(qerr->error, "class");
+    if (!obj) {
+        qerror_abort(qerr, "missing 'class' key in '%s'", fmt);
+    }
+    if (qobject_type(obj) != QTYPE_QSTRING) {
+        qerror_abort(qerr, "'class' key value should be a QString");
+    }
+    
+    obj = qdict_get(qerr->error, "data");
+    if (!obj) {
+        qerror_abort(qerr, "missing 'data' key in '%s'", fmt);
+    }
+    if (qobject_type(obj) != QTYPE_QDICT) {
+        qerror_abort(qerr, "'data' key value should be a QDICT");
+    }
+}
+
+static void qerror_set_desc(const char *fmt, QError *qerr)
+{
+    int i;
+
+    // FIXME: inefficient loop
+
+    for (i = 0; qerror_table[i].error_fmt; i++) {
+        if (strcmp(qerror_table[i].error_fmt, fmt) == 0) {
+            qerr->entry = &qerror_table[i];
+            return;
+        }
+    }
+
+    qerror_abort(qerr, "error format '%s' not found", fmt);
+}
+
+/**
+ * qerror_from_info(): Create a new QError from error information
+ *
+ * The information consists of:
+ *
+ * - file   the file name of where the error occurred
+ * - linenr the line number of where the error occurred
+ * - fmt    JSON printf-like dictionary, there must exist keys 'class' and
+ *          'data'
+ * - va     va_list of all arguments specified by fmt
+ *
+ * Return strong reference.
+ */
+QError *qerror_from_info(const char *file, int linenr, const char *fmt,
+                         va_list *va)
+{
+    QError *qerr;
+
+    qerr = qerror_new();
+    qerr->linenr = linenr;
+    qerr->file = file;
+
+    if (!fmt) {
+        qerror_abort(qerr, "QDict not specified");
+    }
+
+    qerror_set_data(qerr, fmt, va);
+    qerror_set_desc(fmt, qerr);
+
+    return qerr;
+}
+
+static char *get_substr(const char *start, const char *end)
+{
+    char *str;
+    size_t length;
+
+    length = end - start + 1;
+    str = qemu_malloc(length + 1);
+    memcpy(str, start, length);
+    str[length] = '\0';
+
+    return str;
+}
+
+static void parse_error(const QError *qerror, int c)
+{
+    qerror_abort(qerror, "expected '%c' in '%s'", c, qerror->entry->desc);
+}
+
+static const char *append_field(QString *qstring, const QError *qerror,
+                                const char *start)
+{
+    int type;
+    char *name;
+    QDict *qdict;
+    const char *end;
+
+    if (*start != '%')
+        parse_error(qerror, '%');
+    start++;
+    if (*start != '(')
+        parse_error(qerror, '(');
+    start++;
+
+    end = strchr(start, ')');
+    if (!end)
+        parse_error(qerror, ')');
+
+    name = get_substr(start, end - 1);
+    qdict = qobject_to_qdict(qdict_get(qerror->error, "data"));
+
+    if (!qdict_haskey(qdict, name)) {
+        qerror_abort(qerror, "key '%s' not found in QDict", name);
+    }
+
+    type = *++end;
+    switch (type) {
+        case 's':
+            qstring_append(qstring, qdict_get_str(qdict, name));
+            break;
+        case 'd':
+            qstring_append_int(qstring, qdict_get_int(qdict, name));
+            break;
+        default:
+            qerror_abort(qerror, "invalid type '%c'", type);
+    }
+
+    qemu_free(name);
+    return ++end;
+}
+
+/**
+ * qerror_print(): Print QError data
+ *
+ * This function will print the member 'desc' of the specified QError object,
+ * it uses qemu_error() for this, so that the output is routed to the right
+ * place (ie. stderr ou Monitor's device).
+ */
+void qerror_print(const QError *qerror)
+{
+    const char *p;
+    QString *qstring;
+
+    assert(qerror->entry != NULL);
+
+    qstring = qstring_new();
+
+    for (p = qerror->entry->desc; *p != '\0';) {
+        if (*p != '%') {
+            qstring_append_chr(qstring, *p++);
+        } else if (*(p + 1) == '%') {
+            qstring_append_chr(qstring, '%');
+            p += 2;
+        } else {
+            p = append_field(qstring, qerror, p);
+        }
+    }
+
+    qemu_error("%s\n", qstring_get_str(qstring));
+    QDECREF(qstring);
+}
+
+/**
+ * qobject_to_qerror(): Convert a QObject into a QError
+ */
+QError *qobject_to_qerror(const QObject *obj)
+{
+    if (qobject_type(obj) != QTYPE_QERROR) {
+        return NULL;
+    }
+
+    return container_of(obj, QError, base);
+}
+
+/**
+ * qerror_destroy_obj(): Free all memory allocated by a QError
+ */
+static void qerror_destroy_obj(QObject *obj)
+{
+    QError *qerr;
+
+    assert(obj != NULL);
+    qerr = qobject_to_qerror(obj);
+
+    QDECREF(qerr->error);
+    qemu_free(qerr);
+}
diff --git a/qerror.h b/qerror.h
new file mode 100644
index 0000000..dc1aa35
--- /dev/null
+++ b/qerror.h
@@ -0,0 +1,46 @@
+/*
+ * QError header file.
+ *
+ * Copyright (C) 2009 Red Hat Inc.
+ *
+ * Authors:
+ *  Luiz Capitulino <lcapitulino@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ */
+#ifndef QERROR_H
+#define QERROR_H
+
+#include "qdict.h"
+#include <stdarg.h>
+
+typedef struct QErrorStringTable {
+    const char *desc;
+    const char *error_fmt;
+} QErrorStringTable;
+
+typedef struct QError {
+    QObject_HEAD;
+    QDict *error;
+    int linenr;
+    const char *file;
+    const QErrorStringTable *entry;
+} QError;
+
+QError *qerror_new(void);
+QError *qerror_from_info(const char *file, int linenr, const char *fmt,
+                         va_list *va);
+void qerror_print(const QError *qerror);
+QError *qobject_to_qerror(const QObject *obj);
+
+/*
+ * QEMU error format list
+ */
+#define QERR_DEVICE_NOT_FOUND \
+        "{ 'class': 'DeviceNotFound', 'data': { 'name': %s } }"
+
+#define QERR_SERVICE_UNAVAILABLE \
+        "{ 'class': 'ServiceUnavailable', 'data': { 'reason': %s } }"
+
+#endif /* QERROR_H */
diff --git a/qobject.h b/qobject.h
index 2270ec1..07de211 100644
--- a/qobject.h
+++ b/qobject.h
@@ -43,6 +43,7 @@ typedef enum {
     QTYPE_QLIST,
     QTYPE_QFLOAT,
     QTYPE_QBOOL,
+    QTYPE_QERROR,
 } qtype_code;
 
 struct QObject;
-- 
1.6.5.2.155.gbb47

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [Qemu-devel] [PATCH 6/9] QJSON: Fix compile error
  2009-11-12 20:42 [Qemu-devel] [PATCH 0/9]: QError v3 Luiz Capitulino
                   ` (4 preceding siblings ...)
  2009-11-12 20:42 ` [Qemu-devel] [PATCH 5/9] Introduce QError Luiz Capitulino
@ 2009-11-12 20:42 ` Luiz Capitulino
  2009-11-12 20:42 ` [Qemu-devel] [PATCH 7/9] monitor: QError support Luiz Capitulino
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 12+ messages in thread
From: Luiz Capitulino @ 2009-11-12 20:42 UTC (permalink / raw)
  To: qemu-devel; +Cc: aliguori, kraxel, armbru

Add QTYPE_QERROR handling in the to_json() switch, otherwise GCC
will complain.

We just abort(), as QError design is not finished yet.

Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
---
 qjson.c |    3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)

diff --git a/qjson.c b/qjson.c
index 491b61e..ca4fe7c 100644
--- a/qjson.c
+++ b/qjson.c
@@ -239,6 +239,9 @@ static void to_json(const QObject *obj, QString *str)
     }
     case QTYPE_NONE:
         break;
+    case QTYPE_QERROR:
+        fprintf(stderr, "qerror can't be emitted yet\n");
+        abort();
     }
 }
 
-- 
1.6.5.2.155.gbb47

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [Qemu-devel] [PATCH 7/9] monitor: QError support
  2009-11-12 20:42 [Qemu-devel] [PATCH 0/9]: QError v3 Luiz Capitulino
                   ` (5 preceding siblings ...)
  2009-11-12 20:42 ` [Qemu-devel] [PATCH 6/9] QJSON: Fix compile error Luiz Capitulino
@ 2009-11-12 20:42 ` Luiz Capitulino
  2009-11-12 20:42 ` [Qemu-devel] [PATCH 8/9] qdev: Use QError for 'device not found' error Luiz Capitulino
  2009-11-12 20:42 ` [Qemu-devel] [PATCH 9/9] monitor: do_info_balloon(): use QError Luiz Capitulino
  8 siblings, 0 replies; 12+ messages in thread
From: Luiz Capitulino @ 2009-11-12 20:42 UTC (permalink / raw)
  To: qemu-devel; +Cc: aliguori, kraxel, armbru

This commit adds QError support in the Monitor.

A QError member is added to the Monitor struct. This new member
stores error information and is also used to check if an error
has occurred when the called handlers returns.

Additionally, a new macro called qemu_error_new() is introduced.
It should be used in pace of qemu_error() to report errors.

When all conversion to qemu_error_new() is done, qemu_error() can
be turned private.

Basically, Monitor's error flow is something like this:

1. An error occurs in the handler, it calls qemu_error_new()
2. qemu_error_new() builds a new QError object and stores it in
   the Monitor struct
3. The handler returns
4. Top level Monitor code checks the Monitor struct and calls
   qerror_print() to print the error

Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
---
 monitor.c |   42 +++++++++++++++++++++++++++++++++++++++++-
 sysemu.h  |    6 ++++++
 2 files changed, 47 insertions(+), 1 deletions(-)

diff --git a/monitor.c b/monitor.c
index 132fb6e..a8fd552 100644
--- a/monitor.c
+++ b/monitor.c
@@ -49,6 +49,7 @@
 #include "qlist.h"
 #include "qdict.h"
 #include "qstring.h"
+#include "qerror.h"
 
 //#define DEBUG
 //#define DEBUG_COMPLETION
@@ -103,6 +104,7 @@ struct Monitor {
     CPUState *mon_cpu;
     BlockDriverCompletionFunc *password_completion_cb;
     void *password_opaque;
+    QError *error;
     QLIST_HEAD(,mon_fd_t) fds;
     QLIST_ENTRY(Monitor) entry;
 };
@@ -3146,6 +3148,18 @@ fail:
     return NULL;
 }
 
+static inline int monitor_has_error(const Monitor *mon)
+{
+    return mon->error != NULL;
+}
+
+static void monitor_print_error(Monitor *mon)
+{
+    qerror_print(mon->error);
+    QDECREF(mon->error);
+    mon->error = NULL;
+}
+
 static void monitor_handle_command(Monitor *mon, const char *cmdline)
 {
     QDict *qdict;
@@ -3171,7 +3185,10 @@ static void monitor_handle_command(Monitor *mon, const char *cmdline)
         cmd->mhandler.cmd(mon, qdict);
     }
 
-   qemu_errors_to_previous();
+    if (monitor_has_error(mon))
+        monitor_print_error(mon);
+
+    qemu_errors_to_previous();
 
 out:
     QDECREF(qdict);
@@ -3622,3 +3639,26 @@ void qemu_error(const char *fmt, ...)
         break;
     }
 }
+
+void qemu_error_full(const char *file, int linenr, const char *fmt, ...)
+{
+    va_list va;
+    QError *qerror;
+
+    assert(qemu_error_sink != NULL);
+
+    va_start(va, fmt);
+    qerror = qerror_from_info(file, linenr, fmt, &va);
+    va_end(va);
+
+    switch (qemu_error_sink->dest) {
+    case ERR_SINK_FILE:
+        qerror_print(qerror);
+        QDECREF(qerror);
+        break;
+    case ERR_SINK_MONITOR:
+        assert(qemu_error_sink->mon->error == NULL);
+        qemu_error_sink->mon->error = qerror;
+        break;
+    }
+}
diff --git a/sysemu.h b/sysemu.h
index 96804b4..5891def 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -7,6 +7,7 @@
 #include "qemu-queue.h"
 #include "qemu-timer.h"
 #include "qdict.h"
+#include "qerror.h"
 
 #ifdef _WIN32
 #include <windows.h>
@@ -71,6 +72,11 @@ void qemu_errors_to_file(FILE *fp);
 void qemu_errors_to_mon(Monitor *mon);
 void qemu_errors_to_previous(void);
 void qemu_error(const char *fmt, ...) __attribute__ ((format(printf, 1, 2)));
+void qemu_error_full(const char *file, int linenr, const char *fmt, ...)
+                     __attribute__ ((format(printf, 3, 4)));
+
+#define qemu_error_new(fmt, ...) \
+    qemu_error_full(__FILE__, __LINE__, fmt, ## __VA_ARGS__)
 
 #ifdef _WIN32
 /* Polling handling */
-- 
1.6.5.2.155.gbb47

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [Qemu-devel] [PATCH 8/9] qdev: Use QError for 'device not found' error
  2009-11-12 20:42 [Qemu-devel] [PATCH 0/9]: QError v3 Luiz Capitulino
                   ` (6 preceding siblings ...)
  2009-11-12 20:42 ` [Qemu-devel] [PATCH 7/9] monitor: QError support Luiz Capitulino
@ 2009-11-12 20:42 ` Luiz Capitulino
  2009-11-12 20:42 ` [Qemu-devel] [PATCH 9/9] monitor: do_info_balloon(): use QError Luiz Capitulino
  8 siblings, 0 replies; 12+ messages in thread
From: Luiz Capitulino @ 2009-11-12 20:42 UTC (permalink / raw)
  To: qemu-devel; +Cc: aliguori, kraxel, armbru

Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
---
 hw/qdev.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/hw/qdev.c b/hw/qdev.c
index d19d531..875ca50 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -29,6 +29,7 @@
 #include "qdev.h"
 #include "sysemu.h"
 #include "monitor.h"
+#include "qerror.h"
 
 static int qdev_hotplug = 0;
 
@@ -176,8 +177,7 @@ DeviceState *qdev_device_add(QemuOpts *opts)
     /* find driver */
     info = qdev_find_info(NULL, driver);
     if (!info) {
-        qemu_error("Device \"%s\" not found.  Try -device '?' for a list.\n",
-                   driver);
+        qemu_error_new(QERR_DEVICE_NOT_FOUND, driver);
         return NULL;
     }
     if (info->no_user) {
-- 
1.6.5.2.155.gbb47

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [Qemu-devel] [PATCH 9/9] monitor: do_info_balloon(): use QError
  2009-11-12 20:42 [Qemu-devel] [PATCH 0/9]: QError v3 Luiz Capitulino
                   ` (7 preceding siblings ...)
  2009-11-12 20:42 ` [Qemu-devel] [PATCH 8/9] qdev: Use QError for 'device not found' error Luiz Capitulino
@ 2009-11-12 20:42 ` Luiz Capitulino
  8 siblings, 0 replies; 12+ messages in thread
From: Luiz Capitulino @ 2009-11-12 20:42 UTC (permalink / raw)
  To: qemu-devel; +Cc: aliguori, kraxel, armbru

Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
---
 monitor.c |    7 ++++---
 1 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/monitor.c b/monitor.c
index a8fd552..76cb187 100644
--- a/monitor.c
+++ b/monitor.c
@@ -1717,10 +1717,11 @@ static void do_info_balloon(Monitor *mon, QObject **ret_data)
 
     actual = qemu_balloon_status();
     if (kvm_enabled() && !kvm_has_sync_mmu())
-        monitor_printf(mon, "Using KVM without synchronous MMU, "
-                       "ballooning disabled\n");
+        qemu_error_new(QERR_SERVICE_UNAVAILABLE,
+                      "Using KVM without synchronous MMU, ballooning disabled");
     else if (actual == 0)
-        monitor_printf(mon, "Ballooning not activated in VM\n");
+        qemu_error_new(QERR_SERVICE_UNAVAILABLE,
+                       "Ballooning not activated in VM");
     else
         *ret_data = QOBJECT(qint_from_int((int)(actual >> 20)));
 }
-- 
1.6.5.2.155.gbb47

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* Re: [Qemu-devel] [PATCH 1/9] QJSON: Introduce qobject_from_json_va()
  2009-11-12 20:42 ` [Qemu-devel] [PATCH 1/9] QJSON: Introduce qobject_from_json_va() Luiz Capitulino
@ 2009-11-12 21:39   ` Anthony Liguori
  2009-11-13 12:31     ` Luiz Capitulino
  0 siblings, 1 reply; 12+ messages in thread
From: Anthony Liguori @ 2009-11-12 21:39 UTC (permalink / raw)
  To: Luiz Capitulino; +Cc: armbru, aliguori, qemu-devel, kraxel

Luiz Capitulino wrote:
> Accepts a va_list, will be used by QError.
>
> Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
> ---
>  qjson.c |   14 ++++++++++++++
>  qjson.h |    2 ++
>  2 files changed, 16 insertions(+), 0 deletions(-)
>
> diff --git a/qjson.c b/qjson.c
> index 7270909..491b61e 100644
> --- a/qjson.c
> +++ b/qjson.c
> @@ -64,6 +64,20 @@ QObject *qobject_from_jsonf(const char *string, ...)
>      return state.result;
>  }
>  
> +QObject *qobject_from_json_va(const char *string, va_list *ap)
> +{
> +    JSONParsingState state = {};
> +
> +    state.ap = ap;
> +
> +    json_message_parser_init(&state.parser, parse_json);
> +    json_message_parser_feed(&state.parser, string, strlen(string));
> +    json_message_parser_flush(&state.parser);
> +    json_message_parser_destroy(&state.parser);
> +
> +    return state.result;
> +}
> +
>   

qobject_from_jsonf() should just call qobject_from_json_va().

>  typedef struct ToJsonIterState
>  {
>      int count;
> diff --git a/qjson.h b/qjson.h
> index 7fce742..8b89e41 100644
> --- a/qjson.h
> +++ b/qjson.h
> @@ -14,12 +14,14 @@
>  #ifndef QJSON_H
>  #define QJSON_H
>  
> +#include <stdarg.h>
>   

qemu-common.h is a better way to get stdarg.h

>  #include "qobject.h"
>  #include "qstring.h"
>  
>  QObject *qobject_from_json(const char *string);
>  QObject *qobject_from_jsonf(const char *string, ...)
>      __attribute__((__format__ (__printf__, 1, 2)));
> +QObject *qobject_from_json_va(const char *string, va_list *ap);
>  
>  QString *qobject_to_json(const QObject *obj);
>  
>   

Regards,

Anthony Liguori

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [Qemu-devel] [PATCH 1/9] QJSON: Introduce qobject_from_json_va()
  2009-11-12 21:39   ` Anthony Liguori
@ 2009-11-13 12:31     ` Luiz Capitulino
  0 siblings, 0 replies; 12+ messages in thread
From: Luiz Capitulino @ 2009-11-13 12:31 UTC (permalink / raw)
  To: Anthony Liguori; +Cc: armbru, aliguori, qemu-devel, kraxel

On Thu, 12 Nov 2009 15:39:14 -0600
Anthony Liguori <anthony@codemonkey.ws> wrote:

> Luiz Capitulino wrote:
> > Accepts a va_list, will be used by QError.
> >
> > Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
> > ---
> >  qjson.c |   14 ++++++++++++++
> >  qjson.h |    2 ++
> >  2 files changed, 16 insertions(+), 0 deletions(-)
> >
> > diff --git a/qjson.c b/qjson.c
> > index 7270909..491b61e 100644
> > --- a/qjson.c
> > +++ b/qjson.c
> > @@ -64,6 +64,20 @@ QObject *qobject_from_jsonf(const char *string, ...)
> >      return state.result;
> >  }
> >  
> > +QObject *qobject_from_json_va(const char *string, va_list *ap)
> > +{
> > +    JSONParsingState state = {};
> > +
> > +    state.ap = ap;
> > +
> > +    json_message_parser_init(&state.parser, parse_json);
> > +    json_message_parser_feed(&state.parser, string, strlen(string));
> > +    json_message_parser_flush(&state.parser);
> > +    json_message_parser_destroy(&state.parser);
> > +
> > +    return state.result;
> > +}
> > +
> >   
> 
> qobject_from_jsonf() should just call qobject_from_json_va().

 Right.

> >  typedef struct ToJsonIterState
> >  {
> >      int count;
> > diff --git a/qjson.h b/qjson.h
> > index 7fce742..8b89e41 100644
> > --- a/qjson.h
> > +++ b/qjson.h
> > @@ -14,12 +14,14 @@
> >  #ifndef QJSON_H
> >  #define QJSON_H
> >  
> > +#include <stdarg.h>
> >   
> 
> qemu-common.h is a better way to get stdarg.h

 Why? I usually don't include qemu-common.h when all I need
are one or two headers.

^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2009-11-13 12:31 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-11-12 20:42 [Qemu-devel] [PATCH 0/9]: QError v3 Luiz Capitulino
2009-11-12 20:42 ` [Qemu-devel] [PATCH 1/9] QJSON: Introduce qobject_from_json_va() Luiz Capitulino
2009-11-12 21:39   ` Anthony Liguori
2009-11-13 12:31     ` Luiz Capitulino
2009-11-12 20:42 ` [Qemu-devel] [PATCH 2/9] QString: Introduce qstring_append_chr() Luiz Capitulino
2009-11-12 20:42 ` [Qemu-devel] [PATCH 3/9] QString: Introduce qstring_append_int() Luiz Capitulino
2009-11-12 20:42 ` [Qemu-devel] [PATCH 4/9] Add qstring_append_chr() unit-test Luiz Capitulino
2009-11-12 20:42 ` [Qemu-devel] [PATCH 5/9] Introduce QError Luiz Capitulino
2009-11-12 20:42 ` [Qemu-devel] [PATCH 6/9] QJSON: Fix compile error Luiz Capitulino
2009-11-12 20:42 ` [Qemu-devel] [PATCH 7/9] monitor: QError support Luiz Capitulino
2009-11-12 20:42 ` [Qemu-devel] [PATCH 8/9] qdev: Use QError for 'device not found' error Luiz Capitulino
2009-11-12 20:42 ` [Qemu-devel] [PATCH 9/9] monitor: do_info_balloon(): use QError Luiz Capitulino

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).