From: Alexander Barabash <alexander_barabash@mentor.com>
To: Paolo Bonzini <pbonzini@redhat.com>
Cc: qemu-devel <qemu-devel@nongnu.org>
Subject: Re: [Qemu-devel] [PATCH] Add object_property_get_child().
Date: Sun, 19 Feb 2012 14:36:22 +0200 [thread overview]
Message-ID: <4F40ECC6.8000603@mentor.com> (raw)
In-Reply-To: <4F3E2945.3000603@redhat.com>
On 02/17/2012 12:17 PM, Paolo Bonzini wrote:
> Besides the non-triviality of the patch, how is this different from
> object_property_get_link? Perhaps we should just rename that one to
> object_property_get_obj, or add a function that is just a synonym.
As for the patch's (non-)triviality, I just wanted to check what counts
as trivial here.
I agree that was a bit over-reaching.
The proposed object_property_get_child() may return either
the direct child with the specified name in the composition tree,
or the value of the link with the specified name, as
object_property_get_link() indeed does.
It has exactly the same semantics as:
Object *object_property_get_child(Object *obj, const char *name,
struct Error **errp)
{
Object * result;
bool ambigious;
gchar *child_path;
/* If name contains a '/' in it, report an error and return NULL. */
child_path = g_strdup_printf("%s/%s",
object_get_canonical_path(obj), name);
result = object_resolve_path(child_path, &ambigious);
g_free(child_path);
if (result == NULL) {
/* Report an error. */
return NULL;
}
if (ambigious) {
/* Report an error. */
return NULL;
}
return result;
}
but does it in a more straightforward way.
>
>> + */
>> +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/qom/object.c b/qom/object.c
>> index 2de6eaf..61e775b 100644
>> --- a/qom/object.c
>> +++ b/qom/object.c
>> @@ -297,12 +297,86 @@ 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. */
> Why do you need it at all?
I think this is needed to avoid replicating code and have an easy tool
to report
object's path in errors.
>
>> + 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 Object *object_property_extract_child(ObjectProperty *prop,
>> + bool *p_is_invalid_type)
>> +{
>> + if (p_is_invalid_type != NULL) {
>> + *p_is_invalid_type = false;
>> + }
>> + if (object_property_is_child(prop)) {
>> + return (Object *)prop->opaque;
>> + } else if (object_property_is_link(prop)) {
>> + if (prop->opaque != NULL) {
>> + return *(Object **)prop->opaque;
>> + } else {
>> + return NULL;
>> + }
>> + } else {
>> + if (p_is_invalid_type != NULL) {
>> + *p_is_invalid_type = true;
>> + }
>> + return NULL;
>> + }
>> +}
>> +
> object_property_get_child should never be on a fast path. We should
> avoid as much as possible peeking in the opaque. Instead, you should
> just use a visitor like object_property_get_link does.
I am not sure what do you mean by "should never be on a fast path".
Anyway, I did not add any peeking in the opaque. I just moved the code
from object_resolve_abs_path() into a subroutine. Fairly enough, we could
avoid looking into the link property's opaque by calling
object_property_get_link()
instead. I'll prepare a revision of the patch to this end.
>
> Everything starting here should be a separate patch. But if you remove
> object_property_extract_child, I doubt it makes as much sense to
> refactor this.
Obviously, the refactoring was needed to add code. If we don't,
no refactoring is required.
>
>> 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 +873,27 @@ Object *object_get_root(void)
>> return root;
>> }
>>
>> +Object *object_property_get_child(Object *obj, const char *name,
>> + struct Error **errp) {
>> + Object *result = NULL;
>> + ObjectProperty *prop = object_property_find(obj, name);
>> + bool is_invalid_type;
>> +
>> + if (prop == NULL) {
>> + REPORT_OBJECT_ERROR(errp, QERR_OBJECT_PROPERTY_NOT_FOUND, obj,
>> name);
>> + return NULL;
>> + }
>> +
>> + result = object_property_extract_child(prop,&is_invalid_type);
>> + if (is_invalid_type) {
>> + REPORT_OBJECT_ERROR(errp, QERR_OBJECT_PROPERTY_INVALID_TYPE,
>> + obj, name, "child");
>> + return NULL;
>> + }
>> +
>> + return result;
>> +}
>> +
>> static void object_get_child_property(Object *obj, Visitor *v, void
>> *opaque,
>> const char *name, Error **errp)
>> {
>> @@ -829,7 +924,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 +976,7 @@ static void object_set_link_property(Object *obj,
>> Visitor *v, void *opaque,
>> if (strcmp(path, "") != 0) {
>> Object *target;
>>
>> - /* Go from link<FOO> 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 +1004,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 +1031,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;
>> }
>>
>> @@ -980,15 +1079,7 @@ static Object *object_resolve_abs_path(Object
>> *parent,
>> 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_extract_child(prop, NULL);
>>
>> if (!child) {
>> return NULL;
>> @@ -1010,7 +1101,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;
>> }
>>
>>
>>
>>
> Paolo
Alex
next prev parent reply other threads:[~2012-02-19 12:36 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-02-16 17:39 [Qemu-devel] [PATCH] Add object_property_get_child() Alexander Barabash
2012-02-16 18:16 ` Peter Maydell
2012-02-17 10:17 ` Paolo Bonzini
2012-02-19 12:36 ` Alexander Barabash [this message]
2012-02-19 16:04 ` [Qemu-devel] [PATCH v2] Revised: " Alexander Barabash
2012-02-19 17:14 ` Andreas Färber
2012-02-19 18:30 ` Peter Maydell
2012-02-20 15:06 ` Alexander Barabash
2012-02-20 11:14 ` Alexander Barabash
2012-02-20 9:11 ` [Qemu-devel] [PATCH] " Paolo Bonzini
2012-02-20 11:13 ` Alexander Barabash
2012-02-20 11:33 ` Paolo Bonzini
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=4F40ECC6.8000603@mentor.com \
--to=alexander_barabash@mentor.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 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).