From mboxrd@z Thu Jan 1 00:00:00 1970 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 Message-ID: <4F411D76.9020105@mentor.com> Date: Sun, 19 Feb 2012 18:04:06 +0200 From: Alexander Barabash MIME-Version: 1.0 References: <4F3D3F67.9050506@mentor.com> <4F3E2945.3000603@redhat.com> <4F40ECC6.8000603@mentor.com> In-Reply-To: <4F40ECC6.8000603@mentor.com> Content-Type: text/plain; charset="ISO-8859-1"; format=flowed Content-Transfer-Encoding: 7bit Subject: [Qemu-devel] [PATCH v2] Revised: Add object_property_get_child(). List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel Cc: Paolo Bonzini 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 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) { - 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; }