All of lore.kernel.org
 help / color / mirror / Atom feed
From: Luiz Capitulino <lcapitulino@redhat.com>
To: qemu-devel@nongnu.org
Cc: pbonzini@redhat.com, aliguori@us.ibm.com, kraxel@redhat.com,
	hollisb@us.ibm.com
Subject: [Qemu-devel] [PATCH 5/8] Introduce QError
Date: Wed,  4 Nov 2009 18:04:04 -0200	[thread overview]
Message-ID: <1257365047-25895-6-git-send-email-lcapitulino@redhat.com> (raw)
In-Reply-To: <1257365047-25895-1-git-send-email-lcapitulino@redhat.com>

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

- name           A generic error 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  Run-time error data

The qerror_print() function should be used to properly format and
print the stored information to the right place, that is, to stderr
if the Monitor is not running, or to the Monitor's device otherwise.

The following functions are exported:

- qerror_new(): Create a new QError
- qerror_from_info(): Create a new QError from the specified error
                      information
- qerror_print(): Print the specified QError

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

diff --git a/Makefile b/Makefile
index 6fcbcaa..2dfaebd 100644
--- a/Makefile
+++ b/Makefile
@@ -135,7 +135,7 @@ obj-y += buffered_file.o migration.o migration-tcp.o qemu-sockets.o
 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 qjson.o
+obj-y += qint.o qstring.o qdict.o qlist.o qfloat.o qbool.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..7d3137f
--- /dev/null
+++ b/qerror.c
@@ -0,0 +1,235 @@
+/*
+ * 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 "qint.h"
+#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,
+};
+
+/**
+ * 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;
+}
+
+/**
+ * qerror_from_info(): Create a new QError from error information
+ *
+ * The information consists of:
+ *
+ * - name    generic error name
+ * - file    the file name of where the error occurred
+ * - linenr  the line number of where the error occurred
+ * - desc    detailed description (see below)
+ * - fmt     JSON printf-like format for 'specific data'
+ * - va      va_list of all arguments for 'specific data'
+ *
+ * Note that this is a low-level function, it is supposed to be called
+ * by higher-level functions or macros.
+ *
+ * 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%%"
+ *
+ * Return strong reference.
+ */
+QError *qerror_from_info(const char *name, const char *file, int linenr,
+                         const char *desc, const char *fmt, va_list *va)
+{
+    QError *qerr;
+
+    qerr = qerror_new();
+    qerr->name = name;
+    qerr->file = file;
+    qerr->linenr = linenr;
+    qerr->desc = desc;
+    if (fmt) {
+        qerr->data = qobject_from_json_va(fmt, va);
+        assert(qerr->data != NULL);
+    }
+
+    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 qerror_abort(const QError *qerr)
+{
+    fprintf(stderr, " in '%s' at %s:%d\n", qerr->desc, qerr->file,qerr->linenr);
+    abort();
+}
+
+#define ERROR_PREFIX "\n\nqerror: "
+
+static void type_error(const QError *qerr, int c)
+{
+    fprintf(stderr, ERROR_PREFIX "invalid type '%c'", c);
+    qerror_abort(qerr);
+}
+
+static void key_error(const QError *qerr, const char *key)
+{
+    fprintf(stderr, ERROR_PREFIX "key '%s' not found in QDict ", key);
+    fprintf(stderr, "call at %s:%d\n", qerr->file, qerr->linenr);
+    abort();
+}
+
+static void parse_error(const QError *qerror, int c)
+{
+    fprintf(stderr, ERROR_PREFIX "expected '%c'", c);
+    qerror_abort(qerror);
+}
+
+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(qerror->data);
+
+    if (!qdict_haskey(qdict, name)) {
+        key_error(qerror, 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:
+            type_error(qerror, 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->desc != NULL);
+
+    qstring = qstring_new();
+
+    for (p = qerror->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);
+
+    qobject_decref(qerr->data);
+    qemu_free(qerr);
+}
diff --git a/qerror.h b/qerror.h
new file mode 100644
index 0000000..dc39dec
--- /dev/null
+++ b/qerror.h
@@ -0,0 +1,39 @@
+/*
+ * 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 <stdarg.h>
+#include "qobject.h"
+
+typedef struct QError {
+    QObject_HEAD;
+    const char *name;   /* generic name */
+    const char *desc;   /* description */
+    int linenr;         /* line number */
+    const char *file;   /* file name */
+    QObject *data;      /* run-time data */
+} QError;
+
+QError *qerror_new(void);
+QError *qerror_from_info(const char *name, const char *file, int linenr,
+                         const char *desc, const char *fmt, va_list *va);
+void qerror_print(const QError *qerror);
+QError *qobject_to_qerror(const QObject *obj);
+
+/*
+ * Common error names
+ */
+#define QERR_DEV_NFOUND "DeviceNotFound"
+#define QERR_SER_UNAV   "ServiceUnavailable"
+
+#endif /* QERROR_H */
diff --git a/qobject.h b/qobject.h
index 167b607..838dddc 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.143.g8cc62

  parent reply	other threads:[~2009-11-04 20:04 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-11-04 20:03 [Qemu-devel] [RFC 0/8]: QError v2 Luiz Capitulino
2009-11-04 20:04 ` [Qemu-devel] [PATCH 1/8] QJSon: Introduce qobject_from_json_va() Luiz Capitulino
2009-11-04 20:04 ` [Qemu-devel] [PATCH 2/8] QString: Introduce qstring_append_chr() Luiz Capitulino
2009-11-04 20:04 ` [Qemu-devel] [PATCH 3/8] Add qstring_append_chr() unit-test Luiz Capitulino
2009-11-04 20:04 ` [Qemu-devel] [PATCH 4/8] QString: Introduce qstring_append_int() Luiz Capitulino
2009-11-04 20:04 ` Luiz Capitulino [this message]
2009-11-05  9:34   ` [Qemu-devel] Re: [PATCH 5/8] Introduce QError Paolo Bonzini
2009-11-04 20:04 ` [Qemu-devel] [PATCH 6/8] monitor: QError support Luiz Capitulino
2009-11-04 20:04 ` [Qemu-devel] [PATCH 7/8] qdev: Use QError for not found error Luiz Capitulino
2009-11-04 20:04 ` [Qemu-devel] [PATCH 8/8] monitor: do_info_balloon(): use QError Luiz Capitulino
2009-11-11 21:20 ` [Qemu-devel] [RFC 0/8]: QError v2 Anthony Liguori
2009-11-11 23:35   ` Luiz Capitulino
2009-11-12 13:41   ` Luiz Capitulino
2009-11-12 14:44     ` Anthony Liguori
2009-11-12 15:10       ` Luiz Capitulino
2009-11-12 15:26         ` Anthony Liguori
2009-11-18 15:53       ` Markus Armbruster

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1257365047-25895-6-git-send-email-lcapitulino@redhat.com \
    --to=lcapitulino@redhat.com \
    --cc=aliguori@us.ibm.com \
    --cc=hollisb@us.ibm.com \
    --cc=kraxel@redhat.com \
    --cc=pbonzini@redhat.com \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.