qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
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

  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).