From patchwork Wed Jun 1 17:14:49 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michael Roth X-Patchwork-Id: 98225 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [140.186.70.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id DDB9FB6F97 for ; Thu, 2 Jun 2011 03:23:10 +1000 (EST) Received: from localhost ([::1]:40443 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1QRp8M-0001b3-0k for incoming@patchwork.ozlabs.org; Wed, 01 Jun 2011 13:23:06 -0400 Received: from eggs.gnu.org ([140.186.70.92]:36099) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1QRp2x-0001Vv-L6 for qemu-devel@nongnu.org; Wed, 01 Jun 2011 13:20:51 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1QRp2Y-0007R8-TN for qemu-devel@nongnu.org; Wed, 01 Jun 2011 13:17:31 -0400 Received: from mout.perfora.net ([74.208.4.195]:52230) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1QRp2Y-0007QG-L9 for qemu-devel@nongnu.org; Wed, 01 Jun 2011 13:17:06 -0400 Received: from localhost.localdomain ([32.97.110.59]) by mrelay.perfora.net (node=mrus4) with ESMTP (Nemesis) id 0Lwrnk-1PYqun3Rhw-016Spt; Wed, 01 Jun 2011 13:17:04 -0400 From: Michael Roth To: qemu-devel@nongnu.org Date: Wed, 1 Jun 2011 12:14:49 -0500 Message-Id: <1306948500-15086-4-git-send-email-mdroth@linux.vnet.ibm.com> X-Mailer: git-send-email 1.7.0.4 In-Reply-To: <1306948500-15086-1-git-send-email-mdroth@linux.vnet.ibm.com> References: <1306948500-15086-1-git-send-email-mdroth@linux.vnet.ibm.com> X-Provags-ID: V02:K0:65hxpiOlhZlFwm7AWDL4y3PT+FfZMgZza5PNe1OiAoZ bFuKTRTtB6eJydQOw0onte9X7vujRrvsJCpgEUubVhmoepo7vG DooOn6b2MwfNimxk9bVV4BZG5jD9Iv73NVBxWVz2ZTTZhATBqh tIgbwWHVslwgh6kcrPLRC4sA2lDuCr423psRSyqTydlm4XXE/z R0LuA47dNtbv22h57OdUGBS359CCNleXph8lb0u8SY= X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 74.208.4.195 Cc: aliguori@linux.vnet.ibm.com, Jes.Sorensen@redhat.com, agl@linux.vnet.ibm.com, mdroth@linux.vnet.ibm.com, lcapitulino@redhat.com Subject: [Qemu-devel] [PATCH v1][ 03/14] Introduce the new error framework X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org From: Luiz Capitulino New error-handling framework that allows for exception-like error propagation. Signed-off-by: Luiz Capitulino Signed-off-by: Michael Roth --- Makefile.objs | 2 +- error.c | 140 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ error.h | 70 ++++++++++++++++++++++++++++ error_int.h | 29 ++++++++++++ 4 files changed, 240 insertions(+), 1 deletions(-) create mode 100644 error.c create mode 100644 error.h create mode 100644 error_int.h diff --git a/Makefile.objs b/Makefile.objs index 90838f6..0f7bb52 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -59,7 +59,7 @@ fsdev-obj-$(CONFIG_VIRTFS) += $(addprefix fsdev/, $(fsdev-nested-y)) # system emulation, i.e. a single QEMU executable should support all # CPUs and machines. -common-obj-y = $(block-obj-y) blockdev.o +common-obj-y = $(block-obj-y) blockdev.o error.o common-obj-y += $(net-obj-y) common-obj-y += $(qobject-obj-y) common-obj-$(CONFIG_LINUX) += $(fsdev-obj-$(CONFIG_LINUX)) diff --git a/error.c b/error.c new file mode 100644 index 0000000..867eec2 --- /dev/null +++ b/error.c @@ -0,0 +1,140 @@ +/* + * QEMU Error Objects + * + * Copyright IBM, Corp. 2011 + * + * Authors: + * Anthony Liguori + * + * This work is licensed under the terms of the GNU LGPL, version 2. See + * the COPYING.LIB file in the top-level directory. + */ +#include "error.h" +#include "error_int.h" +#include "qemu-objects.h" +#include "qerror.h" +#include + +struct Error +{ + QDict *obj; + const char *fmt; + char *msg; +}; + +void error_set(Error **errp, const char *fmt, ...) +{ + Error *err; + va_list ap; + + if (errp == NULL) { + return; + } + + err = qemu_mallocz(sizeof(*err)); + + va_start(ap, fmt); + err->obj = qobject_to_qdict(qobject_from_jsonv(fmt, &ap)); + va_end(ap); + err->fmt = fmt; + + *errp = err; +} + +bool error_is_set(Error **errp) +{ + return (errp && *errp); +} + +const char *error_get_pretty(Error *err) +{ + if (err->msg == NULL) { + QString *str; + str = qerror_format(err->fmt, err->obj); + err->msg = qemu_strdup(qstring_get_str(str)); + QDECREF(str); + } + + return err->msg; +} + +const char *error_get_field(Error *err, const char *field) +{ + if (strcmp(field, "class") == 0) { + return qdict_get_str(err->obj, field); + } else { + QDict *dict = qdict_get_qdict(err->obj, "data"); + return qdict_get_str(dict, field); + } +} + +QDict *error_get_data(Error *err) +{ + QDict *data = qdict_get_qdict(err->obj, "data"); + QINCREF(data); + return data; +} + +void error_set_field(Error *err, const char *field, const char *value) +{ + QDict *dict = qdict_get_qdict(err->obj, "data"); + return qdict_put(dict, field, qstring_from_str(value)); +} + +void error_free(Error *err) +{ + if (err) { + QDECREF(err->obj); + qemu_free(err->msg); + qemu_free(err); + } +} + +bool error_is_type(Error *err, const char *fmt) +{ + const char *error_class; + char *ptr; + char *end; + + ptr = strstr(fmt, "'class': '"); + assert(ptr != NULL); + ptr += strlen("'class': '"); + + end = strchr(ptr, '\''); + assert(end != NULL); + + error_class = error_get_field(err, "class"); + if (strlen(error_class) != end - ptr) { + return false; + } + + return strncmp(ptr, error_class, end - ptr) == 0; +} + +void error_propagate(Error **dst_err, Error *local_err) +{ + if (dst_err) { + *dst_err = local_err; + } else if (local_err) { + error_free(local_err); + } +} + +QObject *error_get_qobject(Error *err) +{ + QINCREF(err->obj); + return QOBJECT(err->obj); +} + +void error_set_qobject(Error **errp, QObject *obj) +{ + Error *err; + if (errp == NULL) { + return; + } + err = qemu_mallocz(sizeof(*err)); + err->obj = qobject_to_qdict(obj); + qobject_incref(obj); + + *errp = err; +} diff --git a/error.h b/error.h new file mode 100644 index 0000000..003c855 --- /dev/null +++ b/error.h @@ -0,0 +1,70 @@ +/* + * QEMU Error Objects + * + * Copyright IBM, Corp. 2011 + * + * Authors: + * Anthony Liguori + * + * This work is licensed under the terms of the GNU LGPL, version 2. See + * the COPYING.LIB file in the top-level directory. + */ +#ifndef ERROR_H +#define ERROR_H + +#include + +/** + * A class representing internal errors within QEMU. An error has a string + * typename and optionally a set of named string parameters. + */ +typedef struct Error Error; + +/** + * Set an indirect pointer to an error given a printf-style format parameter. + * Currently, qerror.h defines these error formats. This function is not + * meant to be used outside of QEMU. + */ +void error_set(Error **err, const char *fmt, ...) + __attribute__((format(printf, 2, 3))); + +/** + * Returns true if an indirect pointer to an error is pointing to a valid + * error object. + */ +bool error_is_set(Error **err); + +/** + * Get a human readable representation of an error object. + */ +const char *error_get_pretty(Error *err); + +/** + * Get an individual named error field. + */ +const char *error_get_field(Error *err, const char *field); + +/** + * Get an individual named error field. + */ +void error_set_field(Error *err, const char *field, const char *value); + +/** + * Propagate an error to an indirect pointer to an error. This function will + * always transfer ownership of the error reference and handles the case where + * dst_err is NULL correctly. + */ +void error_propagate(Error **dst_err, Error *local_err); + +/** + * Free an error object. + */ +void error_free(Error *err); + +/** + * Determine if an error is of a speific type (based on the qerror format). + * Non-QEMU users should get the `class' field to identify the error type. + */ +bool error_is_type(Error *err, const char *fmt); + +#endif diff --git a/error_int.h b/error_int.h new file mode 100644 index 0000000..5e39424 --- /dev/null +++ b/error_int.h @@ -0,0 +1,29 @@ +/* + * QEMU Error Objects + * + * Copyright IBM, Corp. 2011 + * + * Authors: + * Anthony Liguori + * + * This work is licensed under the terms of the GNU LGPL, version 2. See + * the COPYING.LIB file in the top-level directory. + */ +#ifndef QEMU_ERROR_INT_H +#define QEMU_ERROR_INT_H + +#include "qemu-common.h" +#include "qobject.h" +#include "qdict.h" +#include "error.h" + +/** + * Internal QEMU functions for working with Error. + * + * These are used to convert QErrors to Errors + */ +QDict *error_get_data(Error *err); +QObject *error_get_qobject(Error *err); +void error_set_qobject(Error **errp, QObject *obj); + +#endif