From patchwork Sun Feb 19 16:04:06 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexander Barabash X-Patchwork-Id: 142061 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 EA2C0B6EF3 for ; Mon, 20 Feb 2012 03:04:04 +1100 (EST) Received: from localhost ([::1]:42597 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Rz9Ey-0000wq-Rn for incoming@patchwork.ozlabs.org; Sun, 19 Feb 2012 11:03:56 -0500 Received: from eggs.gnu.org ([140.186.70.92]:59291) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Rz9Er-0000wk-GL for qemu-devel@nongnu.org; Sun, 19 Feb 2012 11:03:50 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Rz9Ep-0000wS-PI for qemu-devel@nongnu.org; Sun, 19 Feb 2012 11:03:49 -0500 Received: from relay1.mentorg.com ([192.94.38.131]:59794) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Rz9Ep-0000wC-EB for qemu-devel@nongnu.org; Sun, 19 Feb 2012 11:03:47 -0500 Received: from svr-orw-exc-10.mgc.mentorg.com ([147.34.98.58]) by relay1.mentorg.com with esmtp id 1Rz9Em-0004X4-Lk from Alexander_Barabash@mentor.com ; Sun, 19 Feb 2012 08:03:44 -0800 Received: from SVR-IES-FEM-01.mgc.mentorg.com ([137.202.0.104]) by SVR-ORW-EXC-10.mgc.mentorg.com with Microsoft SMTPSVC(6.0.3790.4675); Sun, 19 Feb 2012 08:03:46 -0800 Received: from [137.202.52.68] (137.202.0.76) by SVR-IES-FEM-01.mgc.mentorg.com (137.202.0.104) with Microsoft SMTP Server id 14.1.289.1; Sun, 19 Feb 2012 16:03:42 +0000 Message-ID: <4F411D76.9020105@mentor.com> Date: Sun, 19 Feb 2012 18:04:06 +0200 From: Alexander Barabash User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:9.0) Gecko/20111229 Thunderbird/9.0 MIME-Version: 1.0 To: qemu-devel References: <4F3D3F67.9050506@mentor.com> <4F3E2945.3000603@redhat.com> <4F40ECC6.8000603@mentor.com> In-Reply-To: <4F40ECC6.8000603@mentor.com> X-OriginalArrivalTime: 19 Feb 2012 16:03:46.0396 (UTC) FILETIME=[0F7109C0:01CCEF20] X-detected-operating-system: by eggs.gnu.org: Solaris 10 (beta) X-Received-From: 192.94.38.131 Cc: Paolo Bonzini Subject: [Qemu-devel] [PATCH v2] Revised: Add object_property_get_child(). 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 Add object_property_get_child(). Adding a direct accessor to a child property. In the existing implementation, object_property_get() must be used, with with a visitor, implementing the 'type_str' callback, receiving the child's canonical path. In the new implementation, the child is returned directly. For link properties, object_property_get_link() is used to resolve the link. Also, in the new implementation, object_property_get_child() is used as a subroutine of object_resolve_abs_path(). This changes the way object_resolve_abs_path() operates, moving away from directly peeking the property's 'opaque' field to using object_property_get_link(). Thus, in the mew implementation link properties are resolved in the same way, as they are when an absolute path is resolved. Errors relevant to the operation, QERR_OBJECT_PROPERTY_NOT_FOUND and QERR_OBJECT_PROPERTY_INVALID_TYPE were added. Also, in the new implementation, some common sense refactoring was done in the file 'qom/object.c' in the code extracting child and link properties. Signed-off-by: Alexander Barabash - if (!strstart(prop->type, "child<", NULL)) { + if (!object_property_is_child(prop)) { continue; } @@ -799,6 +851,29 @@ Object *object_get_root(void) return root; } +Object *object_property_get_child(Object *obj, const char *name, + struct Error **errp) { + Object *result; + ObjectProperty *prop = object_property_find(obj, name); + + if (prop == NULL) { + REPORT_OBJECT_ERROR(errp, QERR_OBJECT_PROPERTY_NOT_FOUND, obj, name); + return NULL; + } + + if (object_property_is_child(prop)) { + result = (Object *)prop->opaque; + } else if (object_property_is_link(prop)) { + result = object_property_get_link(obj, name, errp); + } else { + result = NULL; + REPORT_OBJECT_ERROR(errp, QERR_OBJECT_PROPERTY_INVALID_TYPE, + obj, name, "child/link"); + } + + return result; +} + static void object_get_child_property(Object *obj, Visitor *v, void *opaque, const char *name, Error **errp) { @@ -829,7 +904,10 @@ void object_property_add_child(Object *obj, const char *name, */ assert(!object_is_type(obj, type_interface)); - type = g_strdup_printf("child<%s>", object_get_typename(OBJECT(child))); + type = g_strdup_printf(CHILD_PROPERTY_TYPE_PREFIX + "%s" + CHILD_PROPERTY_TYPE_SUFFIX, + object_get_typename(OBJECT(child))); object_property_add(obj, name, type, object_get_child_property, NULL, object_finalize_child_property, child, errp); @@ -878,8 +956,7 @@ static void object_set_link_property(Object *obj, Visitor *v, void *opaque, if (strcmp(path, "") != 0) { Object *target; - /* Go from link to FOO. */ - target_type = g_strndup(&type[5], strlen(type) - 6); + target_type = link_type_to_type(type); target = object_resolve_path_type(path, target_type, &ambiguous); if (ambiguous) { @@ -907,7 +984,9 @@ void object_property_add_link(Object *obj, const char *name, { gchar *full_type; - full_type = g_strdup_printf("link<%s>", type); + full_type = g_strdup_printf(LINK_PROPERTY_TYPE_PREFIX + "%s" + LINK_PROPERTY_TYPE_SUFFIX, type); object_property_add(obj, name, full_type, object_get_link_property, @@ -932,7 +1011,7 @@ gchar *object_get_canonical_path(Object *obj) g_assert(obj->parent != NULL); QTAILQ_FOREACH(prop, &obj->parent->properties, node) { - if (!strstart(prop->type, "child<", NULL)) { + if (!object_property_is_child(prop)) { continue; } @@ -964,7 +1043,6 @@ static Object *object_resolve_abs_path(Object *parent, const char *typename, int index) { - ObjectProperty *prop; Object *child; if (parts[index] == NULL) { @@ -975,20 +1053,7 @@ static Object *object_resolve_abs_path(Object *parent, return object_resolve_abs_path(parent, parts, typename, index + 1); } - prop = object_property_find(parent, parts[index]); - if (prop == NULL) { - return NULL; - } - - child = NULL; - if (strstart(prop->type, "link<", NULL)) { - Object **pchild = prop->opaque; - if (*pchild) { - child = *pchild; - } - } else if (strstart(prop->type, "child<", NULL)) { - child = prop->opaque; - } + child = object_property_get_child(parent, parts[index], NULL); if (!child) { return NULL; @@ -1010,7 +1075,7 @@ static Object *object_resolve_partial_path(Object *parent, QTAILQ_FOREACH(prop, &parent->properties, node) { Object *found; - if (!strstart(prop->type, "child<", NULL)) { + if (!object_property_is_child(prop)) { continue; } diff --git a/include/qemu/object.h b/include/qemu/object.h index ba2409d..001521d 100644 --- a/include/qemu/object.h +++ b/include/qemu/object.h @@ -711,6 +711,21 @@ int64_t object_property_get_int(Object *obj, const char *name, struct Error **errp); /** + * object_property_get_child: + * @obj: the object + * @name: the name of the property + * @errp: returns an error if this function fails + * + * Returns: if this a child property, the value of the property, or NULL if + * an error occurs (including when the property value is not a child property). + * + * Result's reference count does not change. + * Therefore, he caller is responsible for referencing the result. + */ +Object *object_property_get_child(Object *obj, const char *name, + struct Error **errp); + +/** * object_property_set: * @obj: the object * @v: the visitor that will be used to write the property value. This should diff --git a/qerror.h b/qerror.h index e26c635..45e4468 100644 --- a/qerror.h +++ b/qerror.h @@ -178,6 +178,12 @@ QError *qobject_to_qerror(const QObject *obj); #define QERR_NOT_SUPPORTED \ "{ 'class': 'NotSupported', 'data': {} }" +#define QERR_OBJECT_PROPERTY_NOT_FOUND \ + "{ 'class': 'ObjectPropertyNotFound', 'data': { 'object': %s, 'property': %s } }" + +#define QERR_OBJECT_PROPERTY_INVALID_TYPE \ + "{ 'class': 'ObjectPropertyInvalidType', 'data': { 'object': %s, 'property': %s, 'expected_type': %s } }" + #define QERR_OPEN_FILE_FAILED \ "{ 'class': 'OpenFileFailed', 'data': { 'filename': %s } }" diff --git a/qom/object.c b/qom/object.c index 2de6eaf..ddd19e1 100644 --- a/qom/object.c +++ b/qom/object.c @@ -297,12 +297,64 @@ static void object_property_del_all(Object *obj) } } +/* + * To ensure correct format checking, + * this function should be used only via REPORT_OBJECT_ERROR() macro. + * + * The first argument after 'obj' should be of type 'const char *'. + * It is ignored, and replaced by the canonical path of 'obj'. + */ +static void report_object_error(Error **errp, const char *fmt, Object *obj, ...) + GCC_FMT_ATTR(2, 4); +static void report_object_error(Error **errp, const char *fmt, Object *obj, ...) +{ + gchar *path; + va_list ap; + + if (errp != NULL) { + path = object_get_canonical_path(obj); + va_start(ap, obj); + va_arg(ap, const char *); /* Ignore the dummy string. */ + error_set(errp, fmt, path, &ap); + va_end(ap); + g_free(path); + } +} +#define REPORT_OBJECT_ERROR(errp, fmt, obj, ...) \ + do { \ + report_object_error(errp, fmt, obj, "", ## __VA_ARGS__); \ + } while (0) + +#define CHILD_PROPERTY_TYPE_PREFIX "child<" +#define CHILD_PROPERTY_TYPE_SUFFIX ">" +#define LINK_PROPERTY_TYPE_PREFIX "link<" +#define LINK_PROPERTY_TYPE_SUFFIX ">" + +static bool object_property_is_child(ObjectProperty *prop) +{ + return (strstart(prop->type, CHILD_PROPERTY_TYPE_PREFIX, NULL) != 0); +} + +static bool object_property_is_link(ObjectProperty *prop) +{ + return (strstart(prop->type, LINK_PROPERTY_TYPE_PREFIX, NULL) != 0); +} + +/* Go from LINK_PROPERTY_TYPE_PREFIX FOO LINK_PROPERTY_TYPE_SUFFIX to FOO. */ +static gchar *link_type_to_type(const gchar *type) +{ + return g_strndup(&type[sizeof(LINK_PROPERTY_TYPE_PREFIX) - 1], + strlen(type) + - (sizeof(LINK_PROPERTY_TYPE_PREFIX) - 1) + - (sizeof(LINK_PROPERTY_TYPE_SUFFIX) - 1)); +} + static void object_property_del_child(Object *obj, Object *child, Error **errp) { ObjectProperty *prop; QTAILQ_FOREACH(prop, &obj->properties, node) {