diff options
author | Michal Schmidt <mschmidt@redhat.com> | 2012-01-16 00:23:59 +0100 |
---|---|---|
committer | Michal Schmidt <mschmidt@redhat.com> | 2012-01-16 13:34:42 +0100 |
commit | d200735e13c52dcfe36c0e066f9f6c2fbfb85a9c (patch) | |
tree | c8ba5a460ecd34fe1f60a09da6c09c43648a2f6b /src/dbus-common.c | |
parent | 595ed347a87e69893c5e72168fc2e94a7cb09e73 (diff) |
dbus: more efficient implementation of properties
The way the various properties[] arrays are initialized is inefficient:
- only the .data members change at runtime, yet the whole arrays of
properties with all the fields are constructed on the stack one by
one by the code.
- there's duplication, eg. the properties of "org.freedesktop.systemd1.Unit"
are repeated in several unit types.
Fix it by moving the information about properties into static const
sections. Instead of storing the .data directly in the property, store
a constant offset from a run-time base.
The small arrays of struct BusBoundProperties bind together the constant
information with the right runtime information (the base pointer).
On my system the code shrinks by 60 KB, data increases by 10 KB.
Diffstat (limited to 'src/dbus-common.c')
-rw-r--r-- | src/dbus-common.c | 170 |
1 files changed, 99 insertions, 71 deletions
diff --git a/src/dbus-common.c b/src/dbus-common.c index 40754e1e0d..50daedcf58 100644 --- a/src/dbus-common.c +++ b/src/dbus-common.c @@ -259,7 +259,7 @@ DBusHandlerResult bus_default_message_handler( DBusMessage *message, const char *introspection, const char *interfaces, - const BusProperty *properties) { + const BusBoundProperties *bound_properties) { DBusError error; DBusMessage *reply = NULL; @@ -278,9 +278,12 @@ DBusHandlerResult bus_default_message_handler( if (!dbus_message_append_args(reply, DBUS_TYPE_STRING, &introspection, DBUS_TYPE_INVALID)) goto oom; - } else if (dbus_message_is_method_call(message, "org.freedesktop.DBus.Properties", "Get") && properties) { + } else if (dbus_message_is_method_call(message, "org.freedesktop.DBus.Properties", "Get") && bound_properties) { const char *interface, *property; + const BusBoundProperties *bp; const BusProperty *p; + void *data; + DBusMessageIter iter, sub; if (!dbus_message_get_args( message, @@ -290,43 +293,51 @@ DBusHandlerResult bus_default_message_handler( DBUS_TYPE_INVALID)) return bus_send_error_reply(c, message, &error, -EINVAL); - for (p = properties; p->property; p++) - if (streq(p->interface, interface) && streq(p->property, property)) - break; + for (bp = bound_properties; bp->interface; bp++) { + if (!streq(bp->interface, interface)) + continue; - if (p->property) { - DBusMessageIter iter, sub; + for (p = bp->properties; p->property; p++) + if (streq(p->property, property)) + goto get_prop; + } - if (!(reply = dbus_message_new_method_return(message))) - goto oom; + /* no match */ + if (!nulstr_contains(interfaces, interface)) + dbus_set_error_const(&error, DBUS_ERROR_UNKNOWN_INTERFACE, "Unknown interface"); + else + dbus_set_error_const(&error, DBUS_ERROR_UNKNOWN_PROPERTY, "Unknown property"); - dbus_message_iter_init_append(reply, &iter); + return bus_send_error_reply(c, message, &error, -EINVAL); - if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT, p->signature, &sub)) - goto oom; - - if ((r = p->append(&sub, property, (void*) p->data)) < 0) { +get_prop: + reply = dbus_message_new_method_return(message); + if (!reply) + goto oom; - if (r == -ENOMEM) - goto oom; + dbus_message_iter_init_append(reply, &iter); - dbus_message_unref(reply); - return bus_send_error_reply(c, message, NULL, r); - } + if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT, p->signature, &sub)) + goto oom; - if (!dbus_message_iter_close_container(&iter, &sub)) + data = (char*)bp->base + p->offset; + if (p->indirect) + data = *(void**)data; + r = p->append(&sub, property, data); + if (r < 0) { + if (r == -ENOMEM) goto oom; - } else { - if (!nulstr_contains(interfaces, interface)) - dbus_set_error_const(&error, DBUS_ERROR_UNKNOWN_INTERFACE, "Unknown interface"); - else - dbus_set_error_const(&error, DBUS_ERROR_UNKNOWN_PROPERTY, "Unknown property"); - return bus_send_error_reply(c, message, &error, -EINVAL); + dbus_message_unref(reply); + return bus_send_error_reply(c, message, NULL, r); } - } else if (dbus_message_is_method_call(message, "org.freedesktop.DBus.Properties", "GetAll") && properties) { + if (!dbus_message_iter_close_container(&iter, &sub)) + goto oom; + + } else if (dbus_message_is_method_call(message, "org.freedesktop.DBus.Properties", "GetAll") && bound_properties) { const char *interface; + const BusBoundProperties *bp; const BusProperty *p; DBusMessageIter iter, sub, sub2, sub3; @@ -350,36 +361,46 @@ DBusHandlerResult bus_default_message_handler( if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "{sv}", &sub)) goto oom; - for (p = properties; p->property; p++) { - if (interface[0] && !streq(p->interface, interface)) + for (bp = bound_properties; bp->interface; bp++) { + if (interface[0] && !streq(bp->interface, interface)) continue; - if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_DICT_ENTRY, NULL, &sub2) || - !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &p->property) || - !dbus_message_iter_open_container(&sub2, DBUS_TYPE_VARIANT, p->signature, &sub3)) - goto oom; + for (p = bp->properties; p->property; p++) { + void *data; - if ((r = p->append(&sub3, p->property, (void*) p->data)) < 0) { - - if (r == -ENOMEM) + if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_DICT_ENTRY, NULL, &sub2) || + !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &p->property) || + !dbus_message_iter_open_container(&sub2, DBUS_TYPE_VARIANT, p->signature, &sub3)) goto oom; - dbus_message_unref(reply); - return bus_send_error_reply(c, message, NULL, r); - } + data = (char*)bp->base + p->offset; + if (p->indirect) + data = *(void**)data; + r = p->append(&sub3, p->property, data); + if (r < 0) { + if (r == -ENOMEM) + goto oom; - if (!dbus_message_iter_close_container(&sub2, &sub3) || - !dbus_message_iter_close_container(&sub, &sub2)) - goto oom; + dbus_message_unref(reply); + return bus_send_error_reply(c, message, NULL, r); + } + + if (!dbus_message_iter_close_container(&sub2, &sub3) || + !dbus_message_iter_close_container(&sub, &sub2)) + goto oom; + } } if (!dbus_message_iter_close_container(&iter, &sub)) goto oom; - } else if (dbus_message_is_method_call(message, "org.freedesktop.DBus.Properties", "Set") && properties) { + } else if (dbus_message_is_method_call(message, "org.freedesktop.DBus.Properties", "Set") && bound_properties) { const char *interface, *property; DBusMessageIter iter; + const BusBoundProperties *bp; const BusProperty *p; + DBusMessageIter sub; + char *sig; if (!dbus_message_iter_init(message, &iter) || dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING) @@ -398,45 +419,52 @@ DBusHandlerResult bus_default_message_handler( dbus_message_iter_has_next(&iter)) return bus_send_error_reply(c, message, NULL, -EINVAL); - for (p = properties; p->property; p++) - if (streq(p->interface, interface) && streq(p->property, property)) - break; + for (bp = bound_properties; bp->interface; bp++) { + if (!streq(bp->interface, interface)) + continue; - if (p->set) { - DBusMessageIter sub; - char *sig; + for (p = bp->properties; p->property; p++) + if (streq(p->property, property)) + goto set_prop; + } - dbus_message_iter_recurse(&iter, &sub); + /* no match */ + if (!nulstr_contains(interfaces, interface)) + dbus_set_error_const(&error, DBUS_ERROR_UNKNOWN_INTERFACE, "Unknown interface"); + else + dbus_set_error_const(&error, DBUS_ERROR_UNKNOWN_PROPERTY, "Unknown property"); - if (!(sig = dbus_message_iter_get_signature(&sub))) - goto oom; + return bus_send_error_reply(c, message, &error, -EINVAL); - if (!streq(sig, p->signature)) { - dbus_free(sig); - return bus_send_error_reply(c, message, NULL, -EINVAL); - } +set_prop: + if (!p->set) { + dbus_set_error_const(&error, DBUS_ERROR_PROPERTY_READ_ONLY, "Property read-only"); + return bus_send_error_reply(c, message, &error, -EINVAL); + } + dbus_message_iter_recurse(&iter, &sub); + + sig = dbus_message_iter_get_signature(&sub); + if (!sig) + goto oom; + + if (!streq(sig, p->signature)) { dbus_free(sig); + return bus_send_error_reply(c, message, NULL, -EINVAL); + } - if ((r = p->set(&sub, property)) < 0) { - if (r == -ENOMEM) - goto oom; - return bus_send_error_reply(c, message, NULL, r); - } + dbus_free(sig); - if (!(reply = dbus_message_new_method_return(message))) + r = p->set(&sub, property); + if (r < 0) { + if (r == -ENOMEM) goto oom; - } else { - if (p->property) - dbus_set_error_const(&error, DBUS_ERROR_PROPERTY_READ_ONLY, "Property read-only"); - else if (!nulstr_contains(interfaces, interface)) - dbus_set_error_const(&error, DBUS_ERROR_UNKNOWN_INTERFACE, "Unknown interface"); - else - dbus_set_error_const(&error, DBUS_ERROR_UNKNOWN_PROPERTY, "Unknown property"); - - return bus_send_error_reply(c, message, &error, -EINVAL); + return bus_send_error_reply(c, message, NULL, r); } + reply = dbus_message_new_method_return(message); + if (!reply) + goto oom; } else { const char *interface = dbus_message_get_interface(message); |