* [Qemu-devel] [PATCH 00/13]: QError v5
@ 2009-11-19 1:05 Luiz Capitulino
2009-11-19 1:05 ` [Qemu-devel] [PATCH 01/13] QJSON: Introduce qobject_from_jsonv() Luiz Capitulino
` (13 more replies)
0 siblings, 14 replies; 15+ messages in thread
From: Luiz Capitulino @ 2009-11-19 1:05 UTC (permalink / raw)
To: qemu-devel; +Cc: aliguori, kraxel, armbru
Hi,
This new QError version addresses the comments from the last submission.
Anthony, please note that my conversion series submitted yesterday:
http://lists.gnu.org/archive/html/qemu-devel/2009-11/msg01007.html
Doesn't depend on QError and can be merged independently of it.
changelog
---------
v4 -> v5
- Better series split
- New KVM missing capability error
- Better error messages
- Minor improvements in QError
v3 -> v4
- Change the license to LGPL
- Add qstring_from_substr()
- qobject_from_ functions are wrappers of qobject_from_jsonv()
- Drop the type specifier from 'desc'
- Minor changes
v0 -> v3
- Big design changes
^ permalink raw reply [flat|nested] 15+ messages in thread
* [Qemu-devel] [PATCH 01/13] QJSON: Introduce qobject_from_jsonv()
2009-11-19 1:05 [Qemu-devel] [PATCH 00/13]: QError v5 Luiz Capitulino
@ 2009-11-19 1:05 ` Luiz Capitulino
2009-11-19 1:05 ` [Qemu-devel] [PATCH 02/13] QString: Introduce qstring_append_chr() Luiz Capitulino
` (12 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Luiz Capitulino @ 2009-11-19 1:05 UTC (permalink / raw)
To: qemu-devel; +Cc: aliguori, kraxel, armbru
It accepts a va_list and will be used by QError. Also simplifies
the code a little, as the other qobject_from_() functions can
use it.
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
---
qjson.c | 21 +++++++++++----------
qjson.h | 2 ++
2 files changed, 13 insertions(+), 10 deletions(-)
diff --git a/qjson.c b/qjson.c
index 7270909..12e6cf0 100644
--- a/qjson.c
+++ b/qjson.c
@@ -34,10 +34,12 @@ static void parse_json(JSONMessageParser *parser, QList *tokens)
s->result = json_parser_parse(tokens, s->ap);
}
-QObject *qobject_from_json(const char *string)
+QObject *qobject_from_jsonv(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);
@@ -46,22 +48,21 @@ QObject *qobject_from_json(const char *string)
return state.result;
}
+QObject *qobject_from_json(const char *string)
+{
+ return qobject_from_jsonv(string, NULL);
+}
+
QObject *qobject_from_jsonf(const char *string, ...)
{
- JSONParsingState state = {};
+ QObject *obj;
va_list ap;
va_start(ap, string);
- state.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);
-
+ obj = qobject_from_jsonv(string, &ap);
va_end(ap);
- return state.result;
+ return obj;
}
typedef struct ToJsonIterState
diff --git a/qjson.h b/qjson.h
index 7fce742..7afec2e 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_jsonv(const char *string, va_list *ap);
QString *qobject_to_json(const QObject *obj);
--
1.6.5.3.148.g785c5
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [Qemu-devel] [PATCH 02/13] QString: Introduce qstring_append_chr()
2009-11-19 1:05 [Qemu-devel] [PATCH 00/13]: QError v5 Luiz Capitulino
2009-11-19 1:05 ` [Qemu-devel] [PATCH 01/13] QJSON: Introduce qobject_from_jsonv() Luiz Capitulino
@ 2009-11-19 1:05 ` Luiz Capitulino
2009-11-19 1:05 ` [Qemu-devel] [PATCH 03/13] QString: Introduce qstring_append_int() Luiz Capitulino
` (11 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Luiz Capitulino @ 2009-11-19 1:05 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.3.148.g785c5
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [Qemu-devel] [PATCH 03/13] QString: Introduce qstring_append_int()
2009-11-19 1:05 [Qemu-devel] [PATCH 00/13]: QError v5 Luiz Capitulino
2009-11-19 1:05 ` [Qemu-devel] [PATCH 01/13] QJSON: Introduce qobject_from_jsonv() Luiz Capitulino
2009-11-19 1:05 ` [Qemu-devel] [PATCH 02/13] QString: Introduce qstring_append_chr() Luiz Capitulino
@ 2009-11-19 1:05 ` Luiz Capitulino
2009-11-19 1:05 ` [Qemu-devel] [PATCH 04/13] QString: Introduce qstring_from_substr() Luiz Capitulino
` (10 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Luiz Capitulino @ 2009-11-19 1:05 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.3.148.g785c5
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [Qemu-devel] [PATCH 04/13] QString: Introduce qstring_from_substr()
2009-11-19 1:05 [Qemu-devel] [PATCH 00/13]: QError v5 Luiz Capitulino
` (2 preceding siblings ...)
2009-11-19 1:05 ` [Qemu-devel] [PATCH 03/13] QString: Introduce qstring_append_int() Luiz Capitulino
@ 2009-11-19 1:05 ` Luiz Capitulino
2009-11-19 1:05 ` [Qemu-devel] [PATCH 05/13] utests: Add qstring_append_chr() unit-test Luiz Capitulino
` (9 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Luiz Capitulino @ 2009-11-19 1:05 UTC (permalink / raw)
To: qemu-devel; +Cc: aliguori, kraxel, armbru
Note that we can now write qstring_from_str() as a wrapper.
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
---
qstring.c | 20 +++++++++++++++-----
qstring.h | 1 +
2 files changed, 16 insertions(+), 5 deletions(-)
diff --git a/qstring.c b/qstring.c
index ad17769..740a106 100644
--- a/qstring.c
+++ b/qstring.c
@@ -31,21 +31,21 @@ QString *qstring_new(void)
}
/**
- * qstring_from_str(): Create a new QString from a regular C string
+ * qstring_from_substr(): Create a new QString from a C string substring
*
- * Return strong reference.
+ * Return string reference
*/
-QString *qstring_from_str(const char *str)
+QString *qstring_from_substr(const char *str, int start, int end)
{
QString *qstring;
qstring = qemu_malloc(sizeof(*qstring));
- qstring->length = strlen(str);
+ qstring->length = end - start + 1;
qstring->capacity = qstring->length;
qstring->string = qemu_malloc(qstring->capacity + 1);
- memcpy(qstring->string, str, qstring->length);
+ memcpy(qstring->string, str + start, qstring->length);
qstring->string[qstring->length] = 0;
QOBJECT_INIT(qstring, &qstring_type);
@@ -53,6 +53,16 @@ QString *qstring_from_str(const char *str)
return qstring;
}
+/**
+ * qstring_from_str(): Create a new QString from a regular C string
+ *
+ * Return strong reference.
+ */
+QString *qstring_from_str(const char *str)
+{
+ return qstring_from_substr(str, 0, strlen(str) - 1);
+}
+
static void capacity_increase(QString *qstring, size_t len)
{
if (qstring->capacity < (qstring->length + len)) {
diff --git a/qstring.h b/qstring.h
index c065331..6aaa7d5 100644
--- a/qstring.h
+++ b/qstring.h
@@ -13,6 +13,7 @@ typedef struct QString {
QString *qstring_new(void);
QString *qstring_from_str(const char *str);
+QString *qstring_from_substr(const char *str, int start, int end);
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);
--
1.6.5.3.148.g785c5
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [Qemu-devel] [PATCH 05/13] utests: Add qstring_append_chr() unit-test
2009-11-19 1:05 [Qemu-devel] [PATCH 00/13]: QError v5 Luiz Capitulino
` (3 preceding siblings ...)
2009-11-19 1:05 ` [Qemu-devel] [PATCH 04/13] QString: Introduce qstring_from_substr() Luiz Capitulino
@ 2009-11-19 1:05 ` Luiz Capitulino
2009-11-19 1:05 ` [Qemu-devel] [PATCH 06/13] utests: Add qstring_from_substr() unit-test Luiz Capitulino
` (8 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Luiz Capitulino @ 2009-11-19 1:05 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.3.148.g785c5
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [Qemu-devel] [PATCH 06/13] utests: Add qstring_from_substr() unit-test
2009-11-19 1:05 [Qemu-devel] [PATCH 00/13]: QError v5 Luiz Capitulino
` (4 preceding siblings ...)
2009-11-19 1:05 ` [Qemu-devel] [PATCH 05/13] utests: Add qstring_append_chr() unit-test Luiz Capitulino
@ 2009-11-19 1:05 ` Luiz Capitulino
2009-11-19 1:05 ` [Qemu-devel] [PATCH 07/13] Introduce QError Luiz Capitulino
` (7 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Luiz Capitulino @ 2009-11-19 1:05 UTC (permalink / raw)
To: qemu-devel; +Cc: aliguori, kraxel, armbru
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
---
check-qstring.c | 14 ++++++++++++++
1 files changed, 14 insertions(+), 0 deletions(-)
diff --git a/check-qstring.c b/check-qstring.c
index 412038a..c308a63 100644
--- a/check-qstring.c
+++ b/check-qstring.c
@@ -71,6 +71,19 @@ START_TEST(qstring_append_chr_test)
}
END_TEST
+START_TEST(qstring_from_substr_test)
+{
+ QString *qs;
+
+ qs = qstring_from_substr("virtualization", 3, 9);
+ fail_unless(qs != NULL);
+ fail_unless(strcmp(qstring_get_str(qs), "tualiza") == 0);
+
+ QDECREF(qs);
+}
+END_TEST
+
+
START_TEST(qobject_to_qstring_test)
{
QString *qstring;
@@ -95,6 +108,7 @@ static Suite *qstring_suite(void)
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, qstring_from_substr_test);
tcase_add_test(qstring_public_tcase, qobject_to_qstring_test);
return s;
--
1.6.5.3.148.g785c5
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [Qemu-devel] [PATCH 07/13] Introduce QError
2009-11-19 1:05 [Qemu-devel] [PATCH 00/13]: QError v5 Luiz Capitulino
` (5 preceding siblings ...)
2009-11-19 1:05 ` [Qemu-devel] [PATCH 06/13] utests: Add qstring_from_substr() unit-test Luiz Capitulino
@ 2009-11-19 1:05 ` Luiz Capitulino
2009-11-19 1:05 ` [Qemu-devel] [PATCH 08/13] monitor: QError support Luiz Capitulino
` (6 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Luiz Capitulino @ 2009-11-19 1:05 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 can 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
- function The function name of where the error occurred
- run-time data Any run-time error data
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
---
Makefile | 2 +-
qerror.c | 260 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
qerror.h | 42 ++++++++++
qjson.c | 2 +
qobject.h | 1 +
5 files changed, 306 insertions(+), 1 deletions(-)
create mode 100644 qerror.c
create mode 100644 qerror.h
diff --git a/Makefile b/Makefile
index d770e2a..c0b65b6 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 block-migration.o
obj-$(CONFIG_BRLAPI) += baum.o
diff --git a/qerror.c b/qerror.c
new file mode 100644
index 0000000..10b0939
--- /dev/null
+++ b/qerror.c
@@ -0,0 +1,260 @@
+/*
+ * 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 LGPL, version 2.1 or later.
+ * See the COPYING.LIB 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)
+ *
+ * Where KEY is a QDict key, which has to be passed to qerror_from_info().
+ *
+ * Example:
+ *
+ * "foo error on device: %(device) slot: %(slot_nr)"
+ *
+ * A single percent sign can be printed if followed by a second one,
+ * for example:
+ *
+ * "running out of foo: %(foo)%%"
+ */
+const QErrorStringTable qerror_table[] = {
+ {}
+};
+
+/**
+ * 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: bad call in function '%s':\n", qerr->func);
+ fprintf(stderr, "qerror: -> ");
+
+ va_start(ap, fmt);
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+
+ fprintf(stderr, "\nqerror: 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_jsonv(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(QError *qerr, const char *fmt)
+{
+ 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
+ * - func the function name 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 *func,
+ const char *fmt, va_list *va)
+{
+ QError *qerr;
+
+ qerr = qerror_new();
+ qerr->linenr = linenr;
+ qerr->file = file;
+ qerr->func = func;
+
+ if (!fmt) {
+ qerror_abort(qerr, "QDict not specified");
+ }
+
+ qerror_set_data(qerr, fmt, va);
+ qerror_set_desc(qerr, fmt);
+
+ return qerr;
+}
+
+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 *outstr, const QError *qerror,
+ const char *start)
+{
+ QObject *obj;
+ QDict *qdict;
+ QString *key_qs;
+ const char *end, *key;
+
+ if (*start != '%')
+ parse_error(qerror, '%');
+ start++;
+ if (*start != '(')
+ parse_error(qerror, '(');
+ start++;
+
+ end = strchr(start, ')');
+ if (!end)
+ parse_error(qerror, ')');
+
+ key_qs = qstring_from_substr(start, 0, end - start - 1);
+ key = qstring_get_str(key_qs);
+
+ qdict = qobject_to_qdict(qdict_get(qerror->error, "data"));
+ obj = qdict_get(qdict, key);
+ if (!obj) {
+ qerror_abort(qerror, "key '%s' not found in QDict", key);
+ }
+
+ switch (qobject_type(obj)) {
+ case QTYPE_QSTRING:
+ qstring_append(outstr, qdict_get_str(qdict, key));
+ break;
+ case QTYPE_QINT:
+ qstring_append_int(outstr, qdict_get_int(qdict, key));
+ break;
+ default:
+ qerror_abort(qerror, "invalid type '%c'", qobject_type(obj));
+ }
+
+ QDECREF(key_qs);
+ 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 or 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..01703ee
--- /dev/null
+++ b/qerror.h
@@ -0,0 +1,42 @@
+/*
+ * 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 LGPL, version 2.1 or later.
+ * See the COPYING.LIB 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 char *func;
+ const QErrorStringTable *entry;
+} QError;
+
+QError *qerror_new(void);
+QError *qerror_from_info(const char *file, int linenr, const char *func,
+ const char *fmt, va_list *va);
+void qerror_print(const QError *qerror);
+QError *qobject_to_qerror(const QObject *obj);
+
+/*
+ * QError class list
+ */
+
+#endif /* QERROR_H */
diff --git a/qjson.c b/qjson.c
index 12e6cf0..60c904d 100644
--- a/qjson.c
+++ b/qjson.c
@@ -224,6 +224,8 @@ static void to_json(const QObject *obj, QString *str)
}
break;
}
+ case QTYPE_QERROR:
+ /* XXX: should QError be emitted? */
case QTYPE_NONE:
break;
}
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.3.148.g785c5
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [Qemu-devel] [PATCH 08/13] monitor: QError support
2009-11-19 1:05 [Qemu-devel] [PATCH 00/13]: QError v5 Luiz Capitulino
` (6 preceding siblings ...)
2009-11-19 1:05 ` [Qemu-devel] [PATCH 07/13] Introduce QError Luiz Capitulino
@ 2009-11-19 1:05 ` Luiz Capitulino
2009-11-19 1:05 ` [Qemu-devel] [PATCH 09/13] QError: Add QERR_DEVICE_NOT_FOUND Luiz Capitulino
` (5 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Luiz Capitulino @ 2009-11-19 1:05 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 handler returns.
Additionally, a new macro called qemu_error_new() is introduced.
It builds on top of the QemuErrorSink API and should be used in
place of qemu_error().
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 | 43 ++++++++++++++++++++++++++++++++++++++++++-
sysemu.h | 7 +++++++
2 files changed, 49 insertions(+), 1 deletions(-)
diff --git a/monitor.c b/monitor.c
index 3286ba2..da05bf4 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;
};
@@ -224,6 +226,11 @@ static inline int monitor_handler_ported(const mon_cmd_t *cmd)
return cmd->user_print != NULL;
}
+static inline int monitor_has_error(const Monitor *mon)
+{
+ return mon->error != NULL;
+}
+
static void monitor_print_qobject(Monitor *mon, const QObject *data)
{
switch (qobject_type(data)) {
@@ -3168,6 +3175,13 @@ fail:
return 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;
@@ -3193,7 +3207,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);
@@ -3644,3 +3661,27 @@ void qemu_error(const char *fmt, ...)
break;
}
}
+
+void qemu_error_internal(const char *file, int linenr, const char *func,
+ const char *fmt, ...)
+{
+ va_list va;
+ QError *qerror;
+
+ assert(qemu_error_sink != NULL);
+
+ va_start(va, fmt);
+ qerror = qerror_from_info(file, linenr, func, 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 b1887ef..70a2b04 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,12 @@ 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_internal(const char *file, int linenr, const char *func,
+ const char *fmt, ...)
+ __attribute__ ((format(printf, 4, 5)));
+
+#define qemu_error_new(fmt, ...) \
+ qemu_error_internal(__FILE__, __LINE__, __func__, fmt, ## __VA_ARGS__)
#ifdef _WIN32
/* Polling handling */
--
1.6.5.3.148.g785c5
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [Qemu-devel] [PATCH 09/13] QError: Add QERR_DEVICE_NOT_FOUND
2009-11-19 1:05 [Qemu-devel] [PATCH 00/13]: QError v5 Luiz Capitulino
` (7 preceding siblings ...)
2009-11-19 1:05 ` [Qemu-devel] [PATCH 08/13] monitor: QError support Luiz Capitulino
@ 2009-11-19 1:05 ` Luiz Capitulino
2009-11-19 1:05 ` [Qemu-devel] [PATCH 10/13] qdev: Use QError for 'device not found' error Luiz Capitulino
` (4 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Luiz Capitulino @ 2009-11-19 1:05 UTC (permalink / raw)
To: qemu-devel; +Cc: aliguori, kraxel, armbru
New class for device not found errors.
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
---
qerror.c | 4 ++++
qerror.h | 2 ++
2 files changed, 6 insertions(+), 0 deletions(-)
diff --git a/qerror.c b/qerror.c
index 10b0939..a12e7f7 100644
--- a/qerror.c
+++ b/qerror.c
@@ -40,6 +40,10 @@ static const QType qerror_type = {
* "running out of foo: %(foo)%%"
*/
const QErrorStringTable qerror_table[] = {
+ {
+ .error_fmt = QERR_DEVICE_NOT_FOUND,
+ .desc = "The %(device) device has not been found",
+ },
{}
};
diff --git a/qerror.h b/qerror.h
index 01703ee..413acc6 100644
--- a/qerror.h
+++ b/qerror.h
@@ -38,5 +38,7 @@ QError *qobject_to_qerror(const QObject *obj);
/*
* QError class list
*/
+#define QERR_DEVICE_NOT_FOUND \
+ "{ 'class': 'DeviceNotFound', 'data': { 'device': %s } }"
#endif /* QERROR_H */
--
1.6.5.3.148.g785c5
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [Qemu-devel] [PATCH 10/13] qdev: Use QError for 'device not found' error
2009-11-19 1:05 [Qemu-devel] [PATCH 00/13]: QError v5 Luiz Capitulino
` (8 preceding siblings ...)
2009-11-19 1:05 ` [Qemu-devel] [PATCH 09/13] QError: Add QERR_DEVICE_NOT_FOUND Luiz Capitulino
@ 2009-11-19 1:05 ` Luiz Capitulino
2009-11-19 1:05 ` [Qemu-devel] [PATCH 11/13] QError: Add QERR_DEVICE_NOT_ACTIVE Luiz Capitulino
` (3 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Luiz Capitulino @ 2009-11-19 1:05 UTC (permalink / raw)
To: qemu-devel; +Cc: aliguori, kraxel, armbru
Please, note that we will lose the "Try -device '?' for a list"
hint as it's qdev specific.
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.3.148.g785c5
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [Qemu-devel] [PATCH 11/13] QError: Add QERR_DEVICE_NOT_ACTIVE
2009-11-19 1:05 [Qemu-devel] [PATCH 00/13]: QError v5 Luiz Capitulino
` (9 preceding siblings ...)
2009-11-19 1:05 ` [Qemu-devel] [PATCH 10/13] qdev: Use QError for 'device not found' error Luiz Capitulino
@ 2009-11-19 1:05 ` Luiz Capitulino
2009-11-19 1:05 ` [Qemu-devel] [PATCH 12/13] QError: Add QERR_KVM_MISSING_CAP Luiz Capitulino
` (2 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Luiz Capitulino @ 2009-11-19 1:05 UTC (permalink / raw)
To: qemu-devel; +Cc: aliguori, kraxel, armbru
New class for device not active errors.
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
---
qerror.c | 4 ++++
qerror.h | 3 +++
2 files changed, 7 insertions(+), 0 deletions(-)
diff --git a/qerror.c b/qerror.c
index a12e7f7..0c0a510 100644
--- a/qerror.c
+++ b/qerror.c
@@ -44,6 +44,10 @@ const QErrorStringTable qerror_table[] = {
.error_fmt = QERR_DEVICE_NOT_FOUND,
.desc = "The %(device) device has not been found",
},
+ {
+ .error_fmt = QERR_DEVICE_NOT_ACTIVE,
+ .desc = "The %(device) device has not been activated by the guest",
+ },
{}
};
diff --git a/qerror.h b/qerror.h
index 413acc6..c1be8b9 100644
--- a/qerror.h
+++ b/qerror.h
@@ -41,4 +41,7 @@ QError *qobject_to_qerror(const QObject *obj);
#define QERR_DEVICE_NOT_FOUND \
"{ 'class': 'DeviceNotFound', 'data': { 'device': %s } }"
+#define QERR_DEVICE_NOT_ACTIVE \
+ "{ 'class': 'DeviceNotActive', 'data': { 'device': %s } }"
+
#endif /* QERROR_H */
--
1.6.5.3.148.g785c5
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [Qemu-devel] [PATCH 12/13] QError: Add QERR_KVM_MISSING_CAP
2009-11-19 1:05 [Qemu-devel] [PATCH 00/13]: QError v5 Luiz Capitulino
` (10 preceding siblings ...)
2009-11-19 1:05 ` [Qemu-devel] [PATCH 11/13] QError: Add QERR_DEVICE_NOT_ACTIVE Luiz Capitulino
@ 2009-11-19 1:05 ` Luiz Capitulino
2009-11-19 1:05 ` [Qemu-devel] [PATCH 13/13] monitor: do_info_balloon(): Use QError Luiz Capitulino
2009-11-19 13:59 ` [Qemu-devel] [PATCH 00/13]: QError v5 Markus Armbruster
13 siblings, 0 replies; 15+ messages in thread
From: Luiz Capitulino @ 2009-11-19 1:05 UTC (permalink / raw)
To: qemu-devel; +Cc: aliguori, kraxel, armbru
New class for KVM unavailable features errors.
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
---
qerror.c | 4 ++++
qerror.h | 3 +++
2 files changed, 7 insertions(+), 0 deletions(-)
diff --git a/qerror.c b/qerror.c
index 0c0a510..d8b125e 100644
--- a/qerror.c
+++ b/qerror.c
@@ -48,6 +48,10 @@ const QErrorStringTable qerror_table[] = {
.error_fmt = QERR_DEVICE_NOT_ACTIVE,
.desc = "The %(device) device has not been activated by the guest",
},
+ {
+ .error_fmt = QERR_KVM_MISSING_CAP,
+ .desc = "Using KVM without %(capability), %(feature) unavailable",
+ },
{}
};
diff --git a/qerror.h b/qerror.h
index c1be8b9..6c100af 100644
--- a/qerror.h
+++ b/qerror.h
@@ -44,4 +44,7 @@ QError *qobject_to_qerror(const QObject *obj);
#define QERR_DEVICE_NOT_ACTIVE \
"{ 'class': 'DeviceNotActive', 'data': { 'device': %s } }"
+#define QERR_KVM_MISSING_CAP \
+ "{ 'class': 'KVMMissingCap', 'data': { 'capability': %s, 'feature': %s } }"
+
#endif /* QERROR_H */
--
1.6.5.3.148.g785c5
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [Qemu-devel] [PATCH 13/13] monitor: do_info_balloon(): Use QError
2009-11-19 1:05 [Qemu-devel] [PATCH 00/13]: QError v5 Luiz Capitulino
` (11 preceding siblings ...)
2009-11-19 1:05 ` [Qemu-devel] [PATCH 12/13] QError: Add QERR_KVM_MISSING_CAP Luiz Capitulino
@ 2009-11-19 1:05 ` Luiz Capitulino
2009-11-19 13:59 ` [Qemu-devel] [PATCH 00/13]: QError v5 Markus Armbruster
13 siblings, 0 replies; 15+ messages in thread
From: Luiz Capitulino @ 2009-11-19 1:05 UTC (permalink / raw)
To: qemu-devel; +Cc: aliguori, kraxel, armbru
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
---
monitor.c | 5 ++---
1 files changed, 2 insertions(+), 3 deletions(-)
diff --git a/monitor.c b/monitor.c
index da05bf4..549e98b 100644
--- a/monitor.c
+++ b/monitor.c
@@ -1722,10 +1722,9 @@ 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_KVM_MISSING_CAP, "synchronous MMU", "balloon");
else if (actual == 0)
- monitor_printf(mon, "Ballooning not activated in VM\n");
+ qemu_error_new(QERR_DEVICE_NOT_ACTIVE, "balloon");
else
*ret_data = QOBJECT(qint_from_int((int)(actual >> 20)));
}
--
1.6.5.3.148.g785c5
^ permalink raw reply related [flat|nested] 15+ messages in thread
* Re: [Qemu-devel] [PATCH 00/13]: QError v5
2009-11-19 1:05 [Qemu-devel] [PATCH 00/13]: QError v5 Luiz Capitulino
` (12 preceding siblings ...)
2009-11-19 1:05 ` [Qemu-devel] [PATCH 13/13] monitor: do_info_balloon(): Use QError Luiz Capitulino
@ 2009-11-19 13:59 ` Markus Armbruster
13 siblings, 0 replies; 15+ messages in thread
From: Markus Armbruster @ 2009-11-19 13:59 UTC (permalink / raw)
To: Luiz Capitulino; +Cc: aliguori, qemu-devel, kraxel
As far as I can see, this series addresses the review comments regarding
the current QError implementation. I'm still concerned about QError
design, and my concerns are being discussed. I hope we can wrap that up
soon and move on.
^ permalink raw reply [flat|nested] 15+ messages in thread
end of thread, other threads:[~2009-11-19 13:59 UTC | newest]
Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-11-19 1:05 [Qemu-devel] [PATCH 00/13]: QError v5 Luiz Capitulino
2009-11-19 1:05 ` [Qemu-devel] [PATCH 01/13] QJSON: Introduce qobject_from_jsonv() Luiz Capitulino
2009-11-19 1:05 ` [Qemu-devel] [PATCH 02/13] QString: Introduce qstring_append_chr() Luiz Capitulino
2009-11-19 1:05 ` [Qemu-devel] [PATCH 03/13] QString: Introduce qstring_append_int() Luiz Capitulino
2009-11-19 1:05 ` [Qemu-devel] [PATCH 04/13] QString: Introduce qstring_from_substr() Luiz Capitulino
2009-11-19 1:05 ` [Qemu-devel] [PATCH 05/13] utests: Add qstring_append_chr() unit-test Luiz Capitulino
2009-11-19 1:05 ` [Qemu-devel] [PATCH 06/13] utests: Add qstring_from_substr() unit-test Luiz Capitulino
2009-11-19 1:05 ` [Qemu-devel] [PATCH 07/13] Introduce QError Luiz Capitulino
2009-11-19 1:05 ` [Qemu-devel] [PATCH 08/13] monitor: QError support Luiz Capitulino
2009-11-19 1:05 ` [Qemu-devel] [PATCH 09/13] QError: Add QERR_DEVICE_NOT_FOUND Luiz Capitulino
2009-11-19 1:05 ` [Qemu-devel] [PATCH 10/13] qdev: Use QError for 'device not found' error Luiz Capitulino
2009-11-19 1:05 ` [Qemu-devel] [PATCH 11/13] QError: Add QERR_DEVICE_NOT_ACTIVE Luiz Capitulino
2009-11-19 1:05 ` [Qemu-devel] [PATCH 12/13] QError: Add QERR_KVM_MISSING_CAP Luiz Capitulino
2009-11-19 1:05 ` [Qemu-devel] [PATCH 13/13] monitor: do_info_balloon(): Use QError Luiz Capitulino
2009-11-19 13:59 ` [Qemu-devel] [PATCH 00/13]: QError v5 Markus Armbruster
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).