[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH v2] Revised: Add object_property_get_child().
From: |
Alexander Barabash |
Subject: |
[Qemu-devel] [PATCH v2] Revised: Add object_property_get_child(). |
Date: |
Sun, 19 Feb 2012 18:04:06 +0200 |
User-agent: |
Mozilla/5.0 (X11; Linux x86_64; rv:9.0) Gecko/20111229 Thunderbird/9.0 |
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 <address@hidden>
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<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 +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;
}
- [Qemu-devel] [PATCH] Add object_property_get_child()., Alexander Barabash, 2012/02/16
- Re: [Qemu-devel] [PATCH] Add object_property_get_child()., Peter Maydell, 2012/02/16
- Re: [Qemu-devel] [PATCH] Add object_property_get_child()., Paolo Bonzini, 2012/02/17
- Re: [Qemu-devel] [PATCH] Add object_property_get_child()., Paolo Bonzini, 2012/02/20
- Re: [Qemu-devel] [PATCH] Add object_property_get_child()., Alexander Barabash, 2012/02/20
- Re: [Qemu-devel] [PATCH] Add object_property_get_child()., Paolo Bonzini, 2012/02/20