chiark / gitweb /
sd-bus: introduce sd_bus_slot objects encapsulating callbacks or vtables attached...
authorLennart Poettering <lennart@poettering.net>
Wed, 14 May 2014 23:15:30 +0000 (01:15 +0200)
committerLennart Poettering <lennart@poettering.net>
Wed, 14 May 2014 23:15:30 +0000 (01:15 +0200)
This makes callback behaviour more like sd-event or sd-resolve, and
creates proper object for unregistering callbacks.

Taking the refernce to the slot is optional. If not taken life time of
the slot will be bound to the underlying bus object (or in the case of
an async call until the reply has been recieved).

34 files changed:
Makefile.am
src/bus-proxyd/bus-proxyd.c
src/core/dbus.c
src/hostname/hostnamed.c
src/libsystemd/libsystemd.sym.m4
src/libsystemd/sd-bus/bus-control.h
src/libsystemd/sd-bus/bus-internal.h
src/libsystemd/sd-bus/bus-match.c
src/libsystemd/sd-bus/bus-match.h
src/libsystemd/sd-bus/bus-objects.c
src/libsystemd/sd-bus/bus-objects.h
src/libsystemd/sd-bus/bus-slot.c [new file with mode: 0644]
src/libsystemd/sd-bus/bus-slot.h [new file with mode: 0644]
src/libsystemd/sd-bus/bus-track.c
src/libsystemd/sd-bus/bus-util.c
src/libsystemd/sd-bus/bus-util.h
src/libsystemd/sd-bus/busctl.c
src/libsystemd/sd-bus/sd-bus.c
src/libsystemd/sd-bus/test-bus-chat.c
src/libsystemd/sd-bus/test-bus-kernel-bloom.c
src/libsystemd/sd-bus/test-bus-kernel.c
src/libsystemd/sd-bus/test-bus-match.c
src/libsystemd/sd-bus/test-bus-objects.c
src/locale/localed.c
src/login/logind-seat-dbus.c
src/login/logind-session-dbus.c
src/login/logind-user-dbus.c
src/login/logind.c
src/machine/machine-dbus.c
src/machine/machined.c
src/network/networkd-link.c
src/systemctl/systemctl.c
src/systemd/sd-bus.h
src/timedate/timedated.c

index 653fcfcdaea358c0832ae7653449a0fb208407a1..89b1d4e08976072482fbf308a379a004de49efa8 100644 (file)
@@ -2119,6 +2119,8 @@ libsystemd_internal_la_SOURCES = \
        src/libsystemd/sd-bus/bus-track.h \
        src/libsystemd/sd-bus/bus-util.c \
        src/libsystemd/sd-bus/bus-util.h \
+       src/libsystemd/sd-bus/bus-slot.c \
+       src/libsystemd/sd-bus/bus-slot.h \
        src/libsystemd/sd-bus/bus-protocol.h \
        src/libsystemd/sd-bus/kdbus.h \
        src/libsystemd/sd-bus/sd-memfd.c \
index c5f9f002feb58ae21b64cefb3a714494e9403654..e095d61ffbd6a1dd8ce1b8c997b8324325fe22db 100644 (file)
@@ -40,6 +40,7 @@
 #include "bus-internal.h"
 #include "bus-message.h"
 #include "bus-util.h"
+#include "bus-internal.h"
 #include "build.h"
 #include "strv.h"
 #include "def.h"
@@ -551,7 +552,7 @@ static int process_driver(sd_bus *a, sd_bus *b, sd_bus_message *m) {
                 if (r < 0)
                         return synthetic_reply_method_errno(m, r, NULL);
 
-                r = sd_bus_add_match(a, match, NULL, NULL);
+                r = sd_bus_add_match(a, NULL, match, NULL, NULL);
                 if (r < 0)
                         return synthetic_reply_method_errno(m, r, NULL);
 
@@ -564,7 +565,9 @@ static int process_driver(sd_bus *a, sd_bus *b, sd_bus_message *m) {
                 if (r < 0)
                         return synthetic_reply_method_errno(m, r, NULL);
 
-                r = sd_bus_remove_match(a, match, NULL, NULL);
+                r = bus_remove_match_by_string(a, match, NULL, NULL);
+                if (r == 0)
+                        return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_MATCH_RULE_NOT_FOUND, "Match rule not found"));
                 if (r < 0)
                         return synthetic_reply_method_errno(m, r, NULL);
 
@@ -739,9 +742,10 @@ static int process_driver(sd_bus *a, sd_bus *b, sd_bus_message *m) {
                 r = sd_bus_release_name(a, name);
                 if (r < 0) {
                         if (r == -ESRCH)
-                                synthetic_reply_method_return(m, "u", BUS_NAME_NON_EXISTENT);
+                                return synthetic_reply_method_return(m, "u", BUS_NAME_NON_EXISTENT);
                         if (r == -EADDRINUSE)
-                                synthetic_reply_method_return(m, "u", BUS_NAME_NOT_OWNER);
+                                return synthetic_reply_method_return(m, "u", BUS_NAME_NOT_OWNER);
+
                         return synthetic_reply_method_errno(m, r, NULL);
                 }
 
@@ -1177,7 +1181,7 @@ int main(int argc, char *argv[]) {
                         goto finish;
                 }
 
-                r = sd_bus_add_match(a, match, NULL, NULL);
+                r = sd_bus_add_match(a, NULL, match, NULL, NULL);
                 if (r < 0) {
                         log_error("Failed to add match for NameLost: %s", strerror(-r));
                         goto finish;
@@ -1198,7 +1202,7 @@ int main(int argc, char *argv[]) {
                         goto finish;
                 }
 
-                r = sd_bus_add_match(a, match, NULL, NULL);
+                r = sd_bus_add_match(a, NULL, match, NULL, NULL);
                 if (r < 0) {
                         log_error("Failed to add match for NameAcquired: %s", strerror(-r));
                         goto finish;
index 189d925c9ecdb037ce841f534fe07e761a383415..fb8e4963e1c004d1c3f1456bee0eef4bd1b4a5c1 100644 (file)
@@ -310,7 +310,7 @@ static int find_unit(Manager *m, sd_bus *bus, const char *path, Unit **unit, sd_
                 sd_bus_message *message;
                 pid_t pid;
 
-                message = sd_bus_get_current(bus);
+                message = sd_bus_get_current_message(bus);
                 if (!message)
                         return 0;
 
@@ -536,58 +536,58 @@ static int bus_setup_api_vtables(Manager *m, sd_bus *bus) {
         assert(bus);
 
 #ifdef HAVE_SELINUX
-        r = sd_bus_add_filter(bus, selinux_filter, m);
+        r = sd_bus_add_filter(bus, NULL, selinux_filter, m);
         if (r < 0) {
                 log_error("Failed to add SELinux access filter: %s", strerror(-r));
                 return r;
         }
 #endif
 
-        r = sd_bus_add_object_vtable(bus, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", bus_manager_vtable, m);
+        r = sd_bus_add_object_vtable(bus, NULL, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", bus_manager_vtable, m);
         if (r < 0) {
                 log_error("Failed to register Manager vtable: %s", strerror(-r));
                 return r;
         }
 
-        r = sd_bus_add_fallback_vtable(bus, "/org/freedesktop/systemd1/job", "org.freedesktop.systemd1.Job", bus_job_vtable, bus_job_find, m);
+        r = sd_bus_add_fallback_vtable(bus, NULL, "/org/freedesktop/systemd1/job", "org.freedesktop.systemd1.Job", bus_job_vtable, bus_job_find, m);
         if (r < 0) {
                 log_error("Failed to register Job vtable: %s", strerror(-r));
                 return r;
         }
 
-        r = sd_bus_add_node_enumerator(bus, "/org/freedesktop/systemd1/job", bus_job_enumerate, m);
+        r = sd_bus_add_node_enumerator(bus, NULL, "/org/freedesktop/systemd1/job", bus_job_enumerate, m);
         if (r < 0) {
                 log_error("Failed to add job enumerator: %s", strerror(-r));
                 return r;
         }
 
-        r = sd_bus_add_fallback_vtable(bus, "/org/freedesktop/systemd1/unit", "org.freedesktop.systemd1.Unit", bus_unit_vtable, bus_unit_find, m);
+        r = sd_bus_add_fallback_vtable(bus, NULL, "/org/freedesktop/systemd1/unit", "org.freedesktop.systemd1.Unit", bus_unit_vtable, bus_unit_find, m);
         if (r < 0) {
                 log_error("Failed to register Unit vtable: %s", strerror(-r));
                 return r;
         }
 
-        r = sd_bus_add_node_enumerator(bus, "/org/freedesktop/systemd1/unit", bus_unit_enumerate, m);
+        r = sd_bus_add_node_enumerator(bus, NULL, "/org/freedesktop/systemd1/unit", bus_unit_enumerate, m);
         if (r < 0) {
                 log_error("Failed to add job enumerator: %s", strerror(-r));
                 return r;
         }
 
         for (t = 0; t < _UNIT_TYPE_MAX; t++) {
-                r = sd_bus_add_fallback_vtable(bus, "/org/freedesktop/systemd1/unit", unit_vtable[t]->bus_interface, unit_vtable[t]->bus_vtable, bus_unit_interface_find, m);
+                r = sd_bus_add_fallback_vtable(bus, NULL, "/org/freedesktop/systemd1/unit", unit_vtable[t]->bus_interface, unit_vtable[t]->bus_vtable, bus_unit_interface_find, m);
                 if (r < 0)  {
                         log_error("Failed to register type specific vtable for %s: %s", unit_vtable[t]->bus_interface, strerror(-r));
                         return r;
                 }
 
                 if (unit_vtable[t]->cgroup_context_offset > 0) {
-                        r = sd_bus_add_fallback_vtable(bus, "/org/freedesktop/systemd1/unit", unit_vtable[t]->bus_interface, bus_unit_cgroup_vtable, bus_unit_cgroup_find, m);
+                        r = sd_bus_add_fallback_vtable(bus, NULL, "/org/freedesktop/systemd1/unit", unit_vtable[t]->bus_interface, bus_unit_cgroup_vtable, bus_unit_cgroup_find, m);
                         if (r < 0) {
                                 log_error("Failed to register control group unit vtable for %s: %s", unit_vtable[t]->bus_interface, strerror(-r));
                                 return r;
                         }
 
-                        r = sd_bus_add_fallback_vtable(bus, "/org/freedesktop/systemd1/unit", unit_vtable[t]->bus_interface, bus_cgroup_vtable, bus_cgroup_context_find, m);
+                        r = sd_bus_add_fallback_vtable(bus, NULL, "/org/freedesktop/systemd1/unit", unit_vtable[t]->bus_interface, bus_cgroup_vtable, bus_cgroup_context_find, m);
                         if (r < 0) {
                                 log_error("Failed to register control group vtable for %s: %s", unit_vtable[t]->bus_interface, strerror(-r));
                                 return r;
@@ -595,7 +595,7 @@ static int bus_setup_api_vtables(Manager *m, sd_bus *bus) {
                 }
 
                 if (unit_vtable[t]->exec_context_offset > 0) {
-                        r = sd_bus_add_fallback_vtable(bus, "/org/freedesktop/systemd1/unit", unit_vtable[t]->bus_interface, bus_exec_vtable, bus_exec_context_find, m);
+                        r = sd_bus_add_fallback_vtable(bus, NULL, "/org/freedesktop/systemd1/unit", unit_vtable[t]->bus_interface, bus_exec_vtable, bus_exec_context_find, m);
                         if (r < 0) {
                                 log_error("Failed to register execute vtable for %s: %s", unit_vtable[t]->bus_interface, strerror(-r));
                                 return r;
@@ -603,7 +603,7 @@ static int bus_setup_api_vtables(Manager *m, sd_bus *bus) {
                 }
 
                 if (unit_vtable[t]->kill_context_offset > 0) {
-                        r = sd_bus_add_fallback_vtable(bus, "/org/freedesktop/systemd1/unit", unit_vtable[t]->bus_interface, bus_kill_vtable, bus_kill_context_find, m);
+                        r = sd_bus_add_fallback_vtable(bus, NULL, "/org/freedesktop/systemd1/unit", unit_vtable[t]->bus_interface, bus_kill_vtable, bus_kill_context_find, m);
                         if (r < 0) {
                                 log_error("Failed to register kill vtable for %s: %s", unit_vtable[t]->bus_interface, strerror(-r));
                                 return r;
@@ -622,6 +622,7 @@ static int bus_setup_disconnected_match(Manager *m, sd_bus *bus) {
 
         r = sd_bus_add_match(
                         bus,
+                        NULL,
                         "sender='org.freedesktop.DBus.Local',"
                         "type='signal',"
                         "path='/org/freedesktop/DBus/Local',"
@@ -710,6 +711,7 @@ static int bus_on_connection(sd_event_source *s, int fd, uint32_t revents, void
 
                 r = sd_bus_add_match(
                                 bus,
+                                NULL,
                                 "type='signal',"
                                 "interface='org.freedesktop.systemd1.Agent',"
                                 "member='Released',"
@@ -780,6 +782,7 @@ static int bus_setup_api(Manager *m, sd_bus *bus) {
 
         r = sd_bus_add_match(
                         bus,
+                        NULL,
                         "type='signal',"
                         "sender='org.freedesktop.DBus',"
                         "path='/org/freedesktop/DBus',"
@@ -791,6 +794,7 @@ static int bus_setup_api(Manager *m, sd_bus *bus) {
 
         r = sd_bus_add_match(
                         bus,
+                        NULL,
                         "type='signal',"
                         "sender='org.freedesktop.DBus',"
                         "path='/org/freedesktop/DBus',"
@@ -874,6 +878,7 @@ static int bus_setup_system(Manager *m, sd_bus *bus) {
          * the system bus */
         r = sd_bus_add_match(
                         bus,
+                        NULL,
                         "type='signal',"
                         "interface='org.freedesktop.systemd1.Agent',"
                         "member='Released',"
index 2be6dcde78324ae79ec57658eebf68928fe79bb9..48cbbdb04a960421b0eeb2a9bbcd6d425a23e774 100644 (file)
@@ -591,7 +591,7 @@ static int connect_bus(Context *c, sd_event *event, sd_bus **_bus) {
                 return r;
         }
 
-        r = sd_bus_add_object_vtable(bus, "/org/freedesktop/hostname1", "org.freedesktop.hostname1", hostname_vtable, c);
+        r = sd_bus_add_object_vtable(bus, NULL, "/org/freedesktop/hostname1", "org.freedesktop.hostname1", hostname_vtable, c);
         if (r < 0) {
                 log_error("Failed to register object: %s", strerror(-r));
                 return r;
index 14d9dcf9e92512c97ba1992e25b85d9515db3c1d..7545ae4dc1a73b50fcfb4a2823bd62a8569cb8b8 100644 (file)
@@ -173,7 +173,6 @@ m4_ifdef(`ENABLE_KDBUS',
         sd_bus_send_to;
         sd_bus_call;
         sd_bus_call_async;
-        sd_bus_call_async_cancel;
         sd_bus_get_fd;
         sd_bus_get_events;
         sd_bus_get_timeout;
@@ -181,27 +180,26 @@ m4_ifdef(`ENABLE_KDBUS',
         sd_bus_process_priority;
         sd_bus_wait;
         sd_bus_flush;
-        sd_bus_get_current;
+        sd_bus_get_current_message;
+        sd_bus_get_current_slot;
         sd_bus_get_tid;
         sd_bus_attach_event;
         sd_bus_detach_event;
         sd_bus_get_event;
         sd_bus_add_filter;
-        sd_bus_remove_filter;
         sd_bus_add_match;
-        sd_bus_remove_match;
         sd_bus_add_object;
-        sd_bus_remove_object;
         sd_bus_add_fallback;
-        sd_bus_remove_fallback;
         sd_bus_add_object_vtable;
-        sd_bus_remove_object_vtable;
         sd_bus_add_fallback_vtable;
-        sd_bus_remove_fallback_vtable;
         sd_bus_add_node_enumerator;
-        sd_bus_remove_node_enumerator;
         sd_bus_add_object_manager;
-        sd_bus_remove_object_manager;
+        sd_bus_slot_ref;
+        sd_bus_slot_unref;
+        sd_bus_slot_get_bus;
+        sd_bus_slot_get_userdata;
+        sd_bus_slot_set_userdata;
+        sd_bus_slot_get_current_message;
         sd_bus_message_new_signal;
         sd_bus_message_new_method_call;
         sd_bus_message_new_method_return;
index 420e091b2e78b6d55d859040f05e48d02bdeb779..aa290edac75cc9521a7a3f97411db5b8f1ec0d49 100644 (file)
@@ -22,6 +22,7 @@
 ***/
 
 #include "sd-bus.h"
+#include "bus-match.h"
 
 int bus_add_match_internal(sd_bus *bus, const char *match, struct bus_match_component *components, unsigned n_components, uint64_t cookie);
 int bus_remove_match_internal(sd_bus *bus, const char *match, uint64_t cookie);
index 3dceb8a5da8566e4930aaa4af06e1a6301082ac5..042d3522615977e48283d599cb3b2275be2de5ba 100644 (file)
@@ -40,7 +40,6 @@
 
 struct reply_callback {
         sd_bus_message_handler_t callback;
-        void *userdata;
         usec_t timeout;
         uint64_t cookie;
         unsigned prioq_idx;
@@ -48,13 +47,23 @@ struct reply_callback {
 
 struct filter_callback {
         sd_bus_message_handler_t callback;
-        void *userdata;
 
         unsigned last_iteration;
 
         LIST_FIELDS(struct filter_callback, callbacks);
 };
 
+struct match_callback {
+        sd_bus_message_handler_t callback;
+
+        uint64_t cookie;
+        unsigned last_iteration;
+
+        char *match_string;
+
+        struct bus_match_node *match_node;
+};
+
 struct node {
         char *path;
         struct node *parent;
@@ -64,8 +73,7 @@ struct node {
         LIST_HEAD(struct node_callback, callbacks);
         LIST_HEAD(struct node_vtable, vtables);
         LIST_HEAD(struct node_enumerator, enumerators);
-
-        bool object_manager;
+        LIST_HEAD(struct node_object_manager, object_managers);
 };
 
 struct node_callback {
@@ -73,7 +81,6 @@ struct node_callback {
 
         bool is_fallback;
         sd_bus_message_handler_t callback;
-        void *userdata;
 
         unsigned last_iteration;
 
@@ -84,20 +91,24 @@ struct node_enumerator {
         struct node *node;
 
         sd_bus_node_enumerator_t callback;
-        void *userdata;
 
         unsigned last_iteration;
 
         LIST_FIELDS(struct node_enumerator, enumerators);
 };
 
+struct node_object_manager {
+        struct node *node;
+
+        LIST_FIELDS(struct node_object_manager, object_managers);
+};
+
 struct node_vtable {
         struct node *node;
 
         char *interface;
         bool is_fallback;
         const sd_bus_vtable *vtable;
-        void *userdata;
         sd_bus_object_find_t find;
 
         unsigned last_iteration;
@@ -114,6 +125,37 @@ struct vtable_member {
         const sd_bus_vtable *vtable;
 };
 
+typedef enum BusSlotType {
+        _BUS_SLOT_DISCONNECTED,
+        BUS_REPLY_CALLBACK,
+        BUS_FILTER_CALLBACK,
+        BUS_MATCH_CALLBACK,
+        BUS_NODE_CALLBACK,
+        BUS_NODE_ENUMERATOR,
+        BUS_NODE_VTABLE,
+        BUS_NODE_OBJECT_MANAGER,
+} BusSlotType;
+
+struct sd_bus_slot {
+        unsigned n_ref;
+        sd_bus *bus;
+        void *userdata;
+        BusSlotType type;
+        bool floating;
+
+        LIST_FIELDS(sd_bus_slot, slots);
+
+        union {
+                struct reply_callback reply_callback;
+                struct filter_callback filter_callback;
+                struct match_callback match_callback;
+                struct node_callback node_callback;
+                struct node_enumerator node_enumerator;
+                struct node_object_manager node_object_manager;
+                struct node_vtable node_vtable;
+        };
+};
+
 enum bus_state {
         BUS_UNSET,
         BUS_OPENING,
@@ -231,7 +273,6 @@ struct sd_bus {
         char *exec_path;
         char **exec_argv;
 
-        uint64_t hello_cookie;
         unsigned iteration_counter;
 
         void *kdbus_buffer;
@@ -260,7 +301,8 @@ struct sd_bus {
         sd_event *event;
         int event_priority;
 
-        sd_bus_message *current;
+        sd_bus_message *current_message;
+        sd_bus_slot *current_slot;
 
         sd_bus **default_bus_ptr;
         pid_t tid;
@@ -276,6 +318,8 @@ struct sd_bus {
         unsigned bloom_n_hash;
 
         sd_bus_track *track_queue;
+
+        LIST_HEAD(sd_bus_slot, slots);
 };
 
 #define BUS_DEFAULT_TIMEOUT ((usec_t) (25 * USEC_PER_SEC))
@@ -340,3 +384,5 @@ int bus_set_address_system(sd_bus *bus);
 int bus_set_address_user(sd_bus *bus);
 int bus_set_address_system_remote(sd_bus *b, const char *host);
 int bus_set_address_system_container(sd_bus *b, const char *machine);
+
+int bus_remove_match_by_string(sd_bus *bus, const char *match, sd_bus_message_handler_t callback, void *userdata);
index c54ca8d71d1bee31f00422034b62ebc152e38f1f..b868159b5c8233fd49e30650d3d74fe15f40e306 100644 (file)
@@ -116,6 +116,9 @@ static void bus_match_node_free(struct bus_match_node *node) {
 static bool bus_match_node_maybe_free(struct bus_match_node *node) {
         assert(node);
 
+        if (node->type == BUS_MATCH_ROOT)
+                return false;
+
         if (node->child)
                 return false;
 
@@ -275,10 +278,10 @@ int bus_match_run(
         case BUS_MATCH_LEAF:
 
                 if (bus) {
-                        if (node->leaf.last_iteration == bus->iteration_counter)
+                        if (node->leaf.callback->last_iteration == bus->iteration_counter)
                                 return 0;
 
-                        node->leaf.last_iteration = bus->iteration_counter;
+                        node->leaf.callback->last_iteration = bus->iteration_counter;
                 }
 
                 r = sd_bus_message_rewind(m, true);
@@ -287,9 +290,17 @@ int bus_match_run(
 
                 /* Run the callback. And then invoke siblings. */
                 if (node->leaf.callback) {
+                        sd_bus_slot *slot;
+
                         _cleanup_bus_error_free_ sd_bus_error error_buffer = SD_BUS_ERROR_NULL;
 
-                        r = node->leaf.callback(bus, m, node->leaf.userdata, &error_buffer);
+                        slot = container_of(node->leaf.callback, sd_bus_slot, match_callback);
+                        if (bus)
+                                bus->current_slot = slot;
+                        r = node->leaf.callback->callback(bus, m, slot->userdata, &error_buffer);
+                        if (bus)
+                                bus->current_slot = NULL;
+
                         r = bus_maybe_reply_error(m, r, &error_buffer);
                         if (r != 0)
                                 return r;
@@ -535,16 +546,13 @@ static int bus_match_find_compare_value(
 
 static int bus_match_add_leaf(
                 struct bus_match_node *where,
-                sd_bus_message_handler_t callback,
-                void *userdata,
-                uint64_t cookie,
-                struct bus_match_node **ret) {
+                struct match_callback *callback) {
 
         struct bus_match_node *n;
 
         assert(where);
         assert(where->type == BUS_MATCH_ROOT || where->type == BUS_MATCH_VALUE);
-        assert(ret);
+        assert(callback);
 
         n = new0(struct bus_match_node, 1);
         if (!n)
@@ -555,13 +563,12 @@ static int bus_match_add_leaf(
         n->next = where->child;
         if (n->next)
                 n->next->prev = n;
+
         n->leaf.callback = callback;
-        n->leaf.userdata = userdata;
-        n->leaf.cookie = cookie;
+        callback->match_node = n;
 
         where->child = n;
 
-        *ret = n;
         return 1;
 }
 
@@ -578,9 +585,13 @@ static int bus_match_find_leaf(
         assert(ret);
 
         for (c = where->child; c; c = c->next) {
+                sd_bus_slot *s;
+
+                s = container_of(c->leaf.callback, sd_bus_slot, match_callback);
+
                 if (c->type == BUS_MATCH_LEAF &&
-                    c->leaf.callback == callback &&
-                    c->leaf.userdata == userdata) {
+                    c->leaf.callback->callback == callback &&
+                    s->userdata == userdata) {
                         *ret = c;
                         return 1;
                 }
@@ -892,16 +903,14 @@ int bus_match_add(
                 struct bus_match_node *root,
                 struct bus_match_component *components,
                 unsigned n_components,
-                sd_bus_message_handler_t callback,
-                void *userdata,
-                uint64_t cookie,
-                struct bus_match_node **ret) {
+                struct match_callback *callback) {
 
         unsigned i;
         struct bus_match_node *n;
         int r;
 
         assert(root);
+        assert(callback);
 
         n = root;
         for (i = 0; i < n_components; i++) {
@@ -912,29 +921,56 @@ int bus_match_add(
                         return r;
         }
 
-        r = bus_match_add_leaf(n, callback, userdata, cookie, &n);
-        if (r < 0)
-                return r;
+        return bus_match_add_leaf(n, callback);
+}
 
-        if (ret)
-                *ret = n;
+int bus_match_remove(
+                struct bus_match_node *root,
+                struct match_callback *callback) {
 
-        return 0;
+        struct bus_match_node *node, *pp;
+
+        assert(root);
+        assert(callback);
+
+        node = callback->match_node;
+        if (!node)
+                return 0;
+
+        assert(node->type == BUS_MATCH_LEAF);
+
+        callback->match_node = NULL;
+
+        /* Free the leaf */
+        pp = node->parent;
+        bus_match_node_free(node);
+
+        /* Prune the tree above */
+        while (pp) {
+                node = pp;
+                pp = node->parent;
+
+                if (!bus_match_node_maybe_free(node))
+                        break;
+        }
+
+        return 1;
 }
 
-int bus_match_remove(
+int bus_match_find(
                 struct bus_match_node *root,
                 struct bus_match_component *components,
                 unsigned n_components,
                 sd_bus_message_handler_t callback,
                 void *userdata,
-                uint64_t *cookie) {
+                struct match_callback **ret) {
 
-        unsigned i;
         struct bus_match_node *n, **gc;
+        unsigned i;
         int r;
 
         assert(root);
+        assert(ret);
 
         gc = newa(struct bus_match_node*, n_components);
 
@@ -954,24 +990,8 @@ int bus_match_remove(
         if (r <= 0)
                 return r;
 
-        if (cookie)
-                *cookie = n->leaf.cookie;
-
-        /* Free the leaf */
-        bus_match_node_free(n);
-
-        /* Prune the tree above */
-        for (i = n_components; i > 0; i --) {
-                struct bus_match_node *p = gc[i-1]->parent;
-
-                if (!bus_match_node_maybe_free(gc[i-1]))
-                        break;
-
-                if (!bus_match_node_maybe_free(p))
-                        break;
-        }
-
-        return r;
+        *ret = n->leaf.callback;
+        return 1;
 }
 
 void bus_match_free(struct bus_match_node *node) {
@@ -1065,7 +1085,7 @@ void bus_match_dump(struct bus_match_node *node, unsigned level) {
         } else if (node->type == BUS_MATCH_ROOT)
                 puts(" root");
         else if (node->type == BUS_MATCH_LEAF)
-                printf(" %p/%p\n", node->leaf.callback, node->leaf.userdata);
+                printf(" %p/%p\n", node->leaf.callback->callback, container_of(node->leaf.callback, sd_bus_slot, match_callback)->userdata);
         else
                 putchar('\n');
 
index 056082b90836f31cd0f12041e54d9273f0e87570..af5f65d073c67f3974c73fad6bea11db623aecab 100644 (file)
@@ -58,10 +58,7 @@ struct bus_match_node {
                         uint8_t u8;
                 } value;
                 struct {
-                        sd_bus_message_handler_t callback;
-                        void *userdata;
-                        unsigned last_iteration;
-                        uint64_t cookie;
+                        struct match_callback *callback;
                 } leaf;
                 struct {
                         /* If this is set, then the child is NULL */
@@ -78,8 +75,10 @@ struct bus_match_component {
 
 int bus_match_run(sd_bus *bus, struct bus_match_node *root, sd_bus_message *m);
 
-int bus_match_add(struct bus_match_node *root, struct bus_match_component *components, unsigned n_components, sd_bus_message_handler_t callback, void *userdata, uint64_t cookie, struct bus_match_node **ret);
-int bus_match_remove(struct bus_match_node *root, struct bus_match_component *components, unsigned n_components, sd_bus_message_handler_t callback, void *userdata, uint64_t *cookie);
+int bus_match_add(struct bus_match_node *root, struct bus_match_component *components, unsigned n_components, struct match_callback *callback);
+int bus_match_remove(struct bus_match_node *root, struct match_callback *callback);
+
+int bus_match_find(struct bus_match_node *root, struct bus_match_component *components, unsigned n_components, sd_bus_message_handler_t callback, void *userdata, struct match_callback **ret);
 
 void bus_match_free(struct bus_match_node *node);
 
index 8b12e891647e81159cf3c7432f098bcaab6dcdf8..f160e2343d11e0436aa4d9a24cf117eea7881b19 100644 (file)
@@ -28,8 +28,9 @@
 #include "bus-type.h"
 #include "bus-signature.h"
 #include "bus-introspect.h"
-#include "bus-objects.h"
 #include "bus-util.h"
+#include "bus-slot.h"
+#include "bus-objects.h"
 
 static int node_vtable_get_userdata(
                 sd_bus *bus,
@@ -38,6 +39,7 @@ static int node_vtable_get_userdata(
                 void **userdata,
                 sd_bus_error *error) {
 
+        sd_bus_slot *s;
         void *u;
         int r;
 
@@ -45,9 +47,13 @@ static int node_vtable_get_userdata(
         assert(path);
         assert(c);
 
-        u = c->userdata;
+        s = container_of(c, sd_bus_slot, node_vtable);
+        u = s->userdata;
         if (c->find) {
+                bus->current_slot = s;
                 r = c->find(bus, path, c->interface, u, &u, error);
+                bus->current_slot = NULL;
+
                 if (r < 0)
                         return r;
                 if (sd_bus_error_is_set(error))
@@ -113,7 +119,10 @@ static int add_enumerated_to_set(
                 if (bus->nodes_modified)
                         return 0;
 
-                r = c->callback(bus, prefix, c->userdata, &children, error);
+                bus->current_slot = container_of(c, sd_bus_slot, node_enumerator);
+                r = c->callback(bus, prefix, bus->current_slot->userdata, &children, error);
+                bus->current_slot = NULL;
+
                 if (r < 0)
                         return r;
                 if (sd_bus_error_is_set(error))
@@ -257,7 +266,10 @@ static int node_callbacks_run(
                 if (r < 0)
                         return r;
 
-                r = c->callback(bus, m, c->userdata, &error_buffer);
+                bus->current_slot = container_of(c, sd_bus_slot, node_callback);
+                r = c->callback(bus, m, bus->current_slot->userdata, &error_buffer);
+                bus->current_slot = NULL;
+
                 r = bus_maybe_reply_error(m, r, &error_buffer);
                 if (r != 0)
                         return r;
@@ -382,7 +394,11 @@ static int method_callbacks_run(
         m->enforced_reply_signature = strempty(c->vtable->x.method.result);
 
         if (c->vtable->x.method.handler) {
+
+                bus->current_slot = container_of(c->parent, sd_bus_slot, node_vtable);
                 r = c->vtable->x.method.handler(bus, m, u, &error);
+                bus->current_slot = NULL;
+
                 return bus_maybe_reply_error(m, r, &error);
         }
 
@@ -396,6 +412,7 @@ static int method_callbacks_run(
 
 static int invoke_property_get(
                 sd_bus *bus,
+                sd_bus_slot *slot,
                 const sd_bus_vtable *v,
                 const char *path,
                 const char *interface,
@@ -408,6 +425,7 @@ static int invoke_property_get(
         int r;
 
         assert(bus);
+        assert(slot);
         assert(v);
         assert(path);
         assert(interface);
@@ -415,7 +433,11 @@ static int invoke_property_get(
         assert(reply);
 
         if (v->x.property.get) {
+
+                bus->current_slot = slot;
                 r = v->x.property.get(bus, path, interface, property, reply, userdata, error);
+                bus->current_slot = NULL;
+
                 if (r < 0)
                         return r;
                 if (sd_bus_error_is_set(error))
@@ -453,6 +475,7 @@ static int invoke_property_get(
 
 static int invoke_property_set(
                 sd_bus *bus,
+                sd_bus_slot *slot,
                 const sd_bus_vtable *v,
                 const char *path,
                 const char *interface,
@@ -464,6 +487,7 @@ static int invoke_property_set(
         int r;
 
         assert(bus);
+        assert(slot);
         assert(v);
         assert(path);
         assert(interface);
@@ -471,7 +495,11 @@ static int invoke_property_set(
         assert(value);
 
         if (v->x.property.set) {
+
+                bus->current_slot = slot;
                 r = v->x.property.set(bus, path, interface, property, value, userdata, error);
+                bus->current_slot = NULL;
+
                 if (r < 0)
                         return r;
                 if (sd_bus_error_is_set(error))
@@ -527,6 +555,7 @@ static int property_get_set_callbacks_run(
 
         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+        sd_bus_slot *slot;
         void *u = NULL;
         int r;
 
@@ -544,6 +573,8 @@ static int property_get_set_callbacks_run(
         if (bus->nodes_modified)
                 return 0;
 
+        slot = container_of(c->parent, sd_bus_slot, node_vtable);
+
         *found_object = true;
 
         r = sd_bus_message_new_method_return(m, &reply);
@@ -567,7 +598,7 @@ static int property_get_set_callbacks_run(
                  * PropertiesChanged signals broadcast contents
                  * anyway. */
 
-                r = invoke_property_get(bus, c->vtable, m->path, c->interface, c->member, reply, u, &error);
+                r = invoke_property_get(bus, slot, c->vtable, m->path, c->interface, c->member, reply, u, &error);
                 if (r < 0)
                         return bus_maybe_reply_error(m, r, &error);
 
@@ -598,7 +629,7 @@ static int property_get_set_callbacks_run(
                 if (r < 0)
                         return bus_maybe_reply_error(m, r, &error);
 
-                r = invoke_property_set(bus, c->vtable, m->path, c->interface, c->member, m, u, &error);
+                r = invoke_property_set(bus, slot, c->vtable, m->path, c->interface, c->member, m, u, &error);
                 if (r < 0)
                         return bus_maybe_reply_error(m, r, &error);
 
@@ -626,6 +657,7 @@ static int vtable_append_one_property(
                 void *userdata,
                 sd_bus_error *error) {
 
+        sd_bus_slot *slot;
         int r;
 
         assert(bus);
@@ -646,7 +678,9 @@ static int vtable_append_one_property(
         if (r < 0)
                 return r;
 
-        r = invoke_property_get(bus, v, path, c->interface, v->x.property.member, reply, vtable_property_convert_userdata(v, userdata), error);
+        slot = container_of(c, sd_bus_slot, node_vtable);
+
+        r = invoke_property_get(bus, slot, v, path, c->interface, v->x.property.member, reply, vtable_property_convert_userdata(v, userdata), error);
         if (r < 0)
                 return r;
         if (bus->nodes_modified)
@@ -783,7 +817,7 @@ static bool bus_node_with_object_manager(sd_bus *bus, struct node *n) {
         assert(bus);
         assert(n);
 
-        if (n->object_manager)
+        if (n->object_managers)
                 return true;
 
         if (n->parent)
@@ -827,7 +861,7 @@ static bool bus_node_exists(
                         return false;
         }
 
-        return !require_fallback && (n->enumerators || n->object_manager);
+        return !require_fallback && (n->enumerators || n->object_managers);
 }
 
 static int process_introspect(
@@ -1421,7 +1455,7 @@ static struct node *bus_node_allocate(sd_bus *bus, const char *path) {
         return n;
 }
 
-static void bus_node_gc(sd_bus *b, struct node *n) {
+void bus_node_gc(sd_bus *b, struct node *n) {
         assert(b);
 
         if (!n)
@@ -1431,7 +1465,7 @@ static void bus_node_gc(sd_bus *b, struct node *n) {
             n->callbacks ||
             n->vtables ||
             n->enumerators ||
-            n->object_manager)
+            n->object_managers)
                 return;
 
         assert(hashmap_remove(b->nodes, n->path) == n);
@@ -1446,12 +1480,13 @@ static void bus_node_gc(sd_bus *b, struct node *n) {
 
 static int bus_add_object(
                 sd_bus *bus,
+                sd_bus_slot **slot,
                 bool fallback,
                 const char *path,
                 sd_bus_message_handler_t callback,
                 void *userdata) {
 
-        struct node_callback *c;
+        sd_bus_slot *s;
         struct node *n;
         int r;
 
@@ -1464,136 +1499,49 @@ static int bus_add_object(
         if (!n)
                 return -ENOMEM;
 
-        c = new0(struct node_callback, 1);
-        if (!c) {
+        s = bus_slot_allocate(bus, !slot, BUS_NODE_CALLBACK, sizeof(struct node_callback), userdata);
+        if (!s) {
                 r = -ENOMEM;
                 goto fail;
         }
 
-        c->node = n;
-        c->callback = callback;
-        c->userdata = userdata;
-        c->is_fallback = fallback;
+        s->node_callback.callback = callback;
+        s->node_callback.is_fallback = fallback;
 
-        LIST_PREPEND(callbacks, n->callbacks, c);
+        s->node_callback.node = n;
+        LIST_PREPEND(callbacks, n->callbacks, &s->node_callback);
         bus->nodes_modified = true;
 
+        if (slot)
+                *slot = s;
+
         return 0;
 
 fail:
-        free(c);
+        sd_bus_slot_unref(s);
         bus_node_gc(bus, n);
+
         return r;
 }
 
-static int bus_remove_object(
+_public_ int sd_bus_add_object(
                 sd_bus *bus,
-                bool fallback,
+                sd_bus_slot **slot,
                 const char *path,
                 sd_bus_message_handler_t callback,
                 void *userdata) {
 
-        struct node_callback *c;
-        struct node *n;
-
-        assert_return(bus, -EINVAL);
-        assert_return(object_path_is_valid(path), -EINVAL);
-        assert_return(callback, -EINVAL);
-        assert_return(!bus_pid_changed(bus), -ECHILD);
-
-        n = hashmap_get(bus->nodes, path);
-        if (!n)
-                return 0;
-
-        LIST_FOREACH(callbacks, c, n->callbacks)
-                if (c->callback == callback && c->userdata == userdata && c->is_fallback == fallback)
-                        break;
-        if (!c)
-                return 0;
-
-        LIST_REMOVE(callbacks, n->callbacks, c);
-        free(c);
-
-        bus_node_gc(bus, n);
-        bus->nodes_modified = true;
-
-        return 1;
-}
-
-_public_ int sd_bus_add_object(sd_bus *bus,
-                               const char *path,
-                               sd_bus_message_handler_t callback,
-                               void *userdata) {
-
-        return bus_add_object(bus, false, path, callback, userdata);
-}
-
-_public_ int sd_bus_remove_object(sd_bus *bus,
-                                  const char *path,
-                                  sd_bus_message_handler_t callback,
-                                  void *userdata) {
-
-        return bus_remove_object(bus, false, path, callback, userdata);
-}
-
-_public_ int sd_bus_add_fallback(sd_bus *bus,
-                                 const char *prefix,
-                                 sd_bus_message_handler_t callback,
-                                 void *userdata) {
-
-        return bus_add_object(bus, true, prefix, callback, userdata);
-}
-
-_public_ int sd_bus_remove_fallback(sd_bus *bus,
-                                    const char *prefix,
-                                    sd_bus_message_handler_t callback,
-                                    void *userdata) {
-
-        return bus_remove_object(bus, true, prefix, callback, userdata);
+        return bus_add_object(bus, slot, false, path, callback, userdata);
 }
 
-static void free_node_vtable(sd_bus *bus, struct node_vtable *w) {
-        assert(bus);
-
-        if (!w)
-                return;
-
-        if (w->interface && w->node && w->vtable) {
-                const sd_bus_vtable *v;
-
-                for (v = w->vtable; v->type != _SD_BUS_VTABLE_END; v++) {
-                        struct vtable_member *x = NULL;
-
-                        switch (v->type) {
-
-                        case _SD_BUS_VTABLE_METHOD: {
-                                struct vtable_member key;
-
-                                key.path = w->node->path;
-                                key.interface = w->interface;
-                                key.member = v->x.method.member;
-
-                                x = hashmap_remove(bus->vtable_methods, &key);
-                                break;
-                        }
-
-                        case _SD_BUS_VTABLE_PROPERTY:
-                        case _SD_BUS_VTABLE_WRITABLE_PROPERTY: {
-                                struct vtable_member key;
-
-                                key.path = w->node->path;
-                                key.interface = w->interface;
-                                key.member = v->x.property.member;
-                                x = hashmap_remove(bus->vtable_properties, &key);
-                                break;
-                        }}
-
-                        free(x);
-                }
-        }
+_public_ int sd_bus_add_fallback(
+                sd_bus *bus,
+                sd_bus_slot **slot,
+                const char *prefix,
+                sd_bus_message_handler_t callback,
+                void *userdata) {
 
-        free(w->interface);
-        free(w);
+        return bus_add_object(bus, slot, true, prefix, callback, userdata);
 }
 
 static unsigned long vtable_member_hash_func(const void *a, const uint8_t hash_key[HASH_KEY_SIZE]) {
@@ -1637,6 +1585,7 @@ static int vtable_member_compare_func(const void *a, const void *b) {
 
 static int add_object_vtable_internal(
                 sd_bus *bus,
+                sd_bus_slot **slot,
                 const char *path,
                 const char *interface,
                 const sd_bus_vtable *vtable,
@@ -1644,7 +1593,8 @@ static int add_object_vtable_internal(
                 sd_bus_object_find_t find,
                 void *userdata) {
 
-        struct node_vtable *c = NULL, *i, *existing = NULL;
+        sd_bus_slot *s;
+        struct node_vtable *i, *existing = NULL;
         const sd_bus_vtable *v;
         struct node *n;
         int r;
@@ -1690,25 +1640,23 @@ static int add_object_vtable_internal(
                 }
         }
 
-        c = new0(struct node_vtable, 1);
-        if (!c) {
+        s = bus_slot_allocate(bus, !slot, BUS_NODE_VTABLE, sizeof(struct node_vtable), userdata);
+        if (!s) {
                 r = -ENOMEM;
                 goto fail;
         }
 
-        c->node = n;
-        c->is_fallback = fallback;
-        c->vtable = vtable;
-        c->userdata = userdata;
-        c->find = find;
+        s->node_vtable.is_fallback = fallback;
+        s->node_vtable.vtable = vtable;
+        s->node_vtable.find = find;
 
-        c->interface = strdup(interface);
-        if (!c->interface) {
+        s->node_vtable.interface = strdup(interface);
+        if (!s->node_vtable.interface) {
                 r = -ENOMEM;
                 goto fail;
         }
 
-        for (v = c->vtable+1; v->type != _SD_BUS_VTABLE_END; v++) {
+        for (v = s->node_vtable.vtable+1; v->type != _SD_BUS_VTABLE_END; v++) {
 
                 switch (v->type) {
 
@@ -1730,9 +1678,9 @@ static int add_object_vtable_internal(
                                 goto fail;
                         }
 
-                        m->parent = c;
+                        m->parent = &s->node_vtable;
                         m->path = n->path;
-                        m->interface = c->interface;
+                        m->interface = s->node_vtable.interface;
                         m->member = v->x.method.member;
                         m->vtable = v;
 
@@ -1773,9 +1721,9 @@ static int add_object_vtable_internal(
                                 goto fail;
                         }
 
-                        m->parent = c;
+                        m->parent = &s->node_vtable;
                         m->path = n->path;
-                        m->interface = c->interface;
+                        m->interface = s->node_vtable.interface;
                         m->member = v->x.property.member;
                         m->vtable = v;
 
@@ -1805,110 +1753,53 @@ static int add_object_vtable_internal(
                 }
         }
 
-        LIST_INSERT_AFTER(vtables, n->vtables, existing, c);
+        s->node_vtable.node = n;
+        LIST_INSERT_AFTER(vtables, n->vtables, existing, &s->node_vtable);
         bus->nodes_modified = true;
 
+        if (slot)
+                *slot = s;
+
         return 0;
 
 fail:
-        if (c)
-                free_node_vtable(bus, c);
-
-        bus_node_gc(bus, n);
-        return r;
-}
-
-static int remove_object_vtable_internal(
-                sd_bus *bus,
-                const char *path,
-                const char *interface,
-                const sd_bus_vtable *vtable,
-                bool fallback,
-                sd_bus_object_find_t find,
-                void *userdata) {
-
-        struct node_vtable *c;
-        struct node *n;
-
-        assert_return(bus, -EINVAL);
-        assert_return(object_path_is_valid(path), -EINVAL);
-        assert_return(interface_name_is_valid(interface), -EINVAL);
-        assert_return(!bus_pid_changed(bus), -ECHILD);
-
-        n = hashmap_get(bus->nodes, path);
-        if (!n)
-                return 0;
-
-        LIST_FOREACH(vtables, c, n->vtables)
-                if (streq(c->interface, interface) &&
-                    c->is_fallback == fallback &&
-                    c->vtable == vtable &&
-                    c->find == find &&
-                    c->userdata == userdata)
-                        break;
-
-        if (!c)
-                return 0;
-
-        LIST_REMOVE(vtables, n->vtables, c);
-
-        free_node_vtable(bus, c);
+        sd_bus_slot_unref(s);
         bus_node_gc(bus, n);
 
-        bus->nodes_modified = true;
-
-        return 1;
+        return r;
 }
 
 _public_ int sd_bus_add_object_vtable(
                 sd_bus *bus,
+                sd_bus_slot **slot,
                 const char *path,
                 const char *interface,
                 const sd_bus_vtable *vtable,
                 void *userdata) {
 
-        return add_object_vtable_internal(bus, path, interface, vtable, false, NULL, userdata);
-}
-
-_public_ int sd_bus_remove_object_vtable(
-                sd_bus *bus,
-                const char *path,
-                const char *interface,
-                const sd_bus_vtable *vtable,
-                void *userdata) {
-
-        return remove_object_vtable_internal(bus, path, interface, vtable, false, NULL, userdata);
+        return add_object_vtable_internal(bus, slot, path, interface, vtable, false, NULL, userdata);
 }
 
 _public_ int sd_bus_add_fallback_vtable(
                 sd_bus *bus,
-                const char *path,
-                const char *interface,
-                const sd_bus_vtable *vtable,
-                sd_bus_object_find_t find,
-                void *userdata) {
-
-        return add_object_vtable_internal(bus, path, interface, vtable, true, find, userdata);
-}
-
-_public_ int sd_bus_remove_fallback_vtable(
-                sd_bus *bus,
-                const char *path,
+                sd_bus_slot **slot,
+                const char *prefix,
                 const char *interface,
                 const sd_bus_vtable *vtable,
                 sd_bus_object_find_t find,
                 void *userdata) {
 
-        return remove_object_vtable_internal(bus, path, interface, vtable, true, find, userdata);
+        return add_object_vtable_internal(bus, slot, prefix, interface, vtable, true, find, userdata);
 }
 
 _public_ int sd_bus_add_node_enumerator(
                 sd_bus *bus,
+                sd_bus_slot **slot,
                 const char *path,
                 sd_bus_node_enumerator_t callback,
                 void *userdata) {
 
-        struct node_enumerator *c;
+        sd_bus_slot *s;
         struct node *n;
         int r;
 
@@ -1921,61 +1812,28 @@ _public_ int sd_bus_add_node_enumerator(
         if (!n)
                 return -ENOMEM;
 
-        c = new0(struct node_enumerator, 1);
-        if (!c) {
+        s = bus_slot_allocate(bus, !slot, BUS_NODE_ENUMERATOR, sizeof(struct node_enumerator), userdata);
+        if (!s) {
                 r = -ENOMEM;
                 goto fail;
         }
 
-        c->node = n;
-        c->callback = callback;
-        c->userdata = userdata;
-
-        LIST_PREPEND(enumerators, n->enumerators, c);
+        s->node_enumerator.callback = callback;
 
+        s->node_enumerator.node = n;
+        LIST_PREPEND(enumerators, n->enumerators, &s->node_enumerator);
         bus->nodes_modified = true;
 
+        if (slot)
+                *slot = s;
+
         return 0;
 
 fail:
-        free(c);
-        bus_node_gc(bus, n);
-        return r;
-}
-
-_public_ int sd_bus_remove_node_enumerator(
-                sd_bus *bus,
-                const char *path,
-                sd_bus_node_enumerator_t callback,
-                void *userdata) {
-
-        struct node_enumerator *c;
-        struct node *n;
-
-        assert_return(bus, -EINVAL);
-        assert_return(object_path_is_valid(path), -EINVAL);
-        assert_return(callback, -EINVAL);
-        assert_return(!bus_pid_changed(bus), -ECHILD);
-
-        n = hashmap_get(bus->nodes, path);
-        if (!n)
-                return 0;
-
-        LIST_FOREACH(enumerators, c, n->enumerators)
-                if (c->callback == callback && c->userdata == userdata)
-                        break;
-
-        if (!c)
-                return 0;
-
-        LIST_REMOVE(enumerators, n->enumerators, c);
-        free(c);
-
+        sd_bus_slot_unref(s);
         bus_node_gc(bus, n);
 
-        bus->nodes_modified = true;
-
-        return 1;
+        return r;
 }
 
 static int emit_properties_changed_on_interface(
@@ -2481,8 +2339,10 @@ _public_ int sd_bus_emit_interfaces_removed(sd_bus *bus, const char *path, const
         return sd_bus_emit_interfaces_removed_strv(bus, path, interfaces);
 }
 
-_public_ int sd_bus_add_object_manager(sd_bus *bus, const char *path) {
+_public_ int sd_bus_add_object_manager(sd_bus *bus, sd_bus_slot **slot, const char *path) {
+        sd_bus_slot *s;
         struct node *n;
+        int r;
 
         assert_return(bus, -EINVAL);
         assert_return(object_path_is_valid(path), -EINVAL);
@@ -2492,28 +2352,24 @@ _public_ int sd_bus_add_object_manager(sd_bus *bus, const char *path) {
         if (!n)
                 return -ENOMEM;
 
-        n->object_manager = true;
-        bus->nodes_modified = true;
-        return 0;
-}
-
-_public_ int sd_bus_remove_object_manager(sd_bus *bus, const char *path) {
-        struct node *n;
+        s = bus_slot_allocate(bus, !slot, BUS_NODE_OBJECT_MANAGER, sizeof(struct node_object_manager), NULL);
+        if (!s) {
+                r = -ENOMEM;
+                goto fail;
+        }
 
-        assert_return(bus, -EINVAL);
-        assert_return(object_path_is_valid(path), -EINVAL);
-        assert_return(!bus_pid_changed(bus), -ECHILD);
+        s->node_object_manager.node = n;
+        LIST_PREPEND(object_managers, n->object_managers, &s->node_object_manager);
+        bus->nodes_modified = true;
 
-        n = hashmap_get(bus->nodes, path);
-        if (!n)
-                return 0;
+        if (slot)
+                *slot = s;
 
-        if (!n->object_manager)
-                return 0;
+        return 0;
 
-        n->object_manager = false;
-        bus->nodes_modified = true;
+fail:
+        sd_bus_slot_unref(s);
         bus_node_gc(bus, n);
 
-        return 1;
+        return r;
 }
index 420edd9478be9369db6023b6ef1fe8d23328262b..4373fae89c97667d4cc8561fb6bb76e6fa8ef938 100644 (file)
@@ -24,3 +24,4 @@
 #include "bus-internal.h"
 
 int bus_process_object(sd_bus *bus, sd_bus_message *m);
+void bus_node_gc(sd_bus *b, struct node *n);
diff --git a/src/libsystemd/sd-bus/bus-slot.c b/src/libsystemd/sd-bus/bus-slot.c
new file mode 100644 (file)
index 0000000..8e38992
--- /dev/null
@@ -0,0 +1,244 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+  This file is part of systemd.
+
+  Copyright 2013 Lennart Poettering
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include "sd-bus.h"
+#include "bus-control.h"
+#include "bus-objects.h"
+#include "bus-slot.h"
+
+sd_bus_slot *bus_slot_allocate(
+                sd_bus *bus,
+                bool floating,
+                BusSlotType type,
+                size_t extra,
+                void *userdata) {
+
+        sd_bus_slot *slot;
+
+        assert(bus);
+
+        slot = malloc0(offsetof(sd_bus_slot, reply_callback) + extra);
+        if (!slot)
+                return NULL;
+
+        slot->n_ref = 1;
+        slot->type = type;
+        slot->bus = bus;
+        slot->floating = floating;
+        slot->userdata = userdata;
+
+        if (!floating)
+                sd_bus_ref(bus);
+
+        LIST_PREPEND(slots, bus->slots, slot);
+
+        return slot;
+}
+
+_public_ sd_bus_slot* sd_bus_slot_ref(sd_bus_slot *slot) {
+        assert_return(slot, NULL);
+
+        assert(slot->n_ref > 0);
+
+        slot->n_ref++;
+        return slot;
+}
+
+void bus_slot_disconnect(sd_bus_slot *slot) {
+        sd_bus *bus;
+
+        assert(slot);
+
+        switch (slot->type) {
+
+        case _BUS_SLOT_DISCONNECTED:
+                /* Already disconnected... */
+                return;
+
+        case BUS_REPLY_CALLBACK:
+
+                if (slot->reply_callback.cookie != 0)
+                        hashmap_remove(slot->bus->reply_callbacks, &slot->reply_callback.cookie);
+
+                if (slot->reply_callback.timeout != 0)
+                        prioq_remove(slot->bus->reply_callbacks_prioq, &slot->reply_callback, &slot->reply_callback.prioq_idx);
+
+                break;
+
+        case BUS_FILTER_CALLBACK:
+                slot->bus->filter_callbacks_modified = true;
+                LIST_REMOVE(callbacks, slot->bus->filter_callbacks, &slot->filter_callback);
+                break;
+
+        case BUS_MATCH_CALLBACK:
+
+                if (slot->bus->bus_client)
+                        bus_remove_match_internal(slot->bus, slot->match_callback.match_string, slot->match_callback.cookie);
+
+                slot->bus->match_callbacks_modified = true;
+                bus_match_remove(&slot->bus->match_callbacks, &slot->match_callback);
+
+                free(slot->match_callback.match_string);
+
+                break;
+
+        case BUS_NODE_CALLBACK:
+
+                if (slot->node_callback.node) {
+                        LIST_REMOVE(callbacks, slot->node_callback.node->callbacks, &slot->node_callback);
+                        slot->bus->nodes_modified = true;
+
+                        bus_node_gc(slot->bus, slot->node_callback.node);
+                }
+
+                break;
+
+        case BUS_NODE_ENUMERATOR:
+
+                if (slot->node_enumerator.node) {
+                        LIST_REMOVE(enumerators, slot->node_enumerator.node->enumerators, &slot->node_enumerator);
+                        slot->bus->nodes_modified = true;
+
+                        bus_node_gc(slot->bus, slot->node_enumerator.node);
+                }
+
+                break;
+
+        case BUS_NODE_OBJECT_MANAGER:
+
+                if (slot->node_object_manager.node) {
+                        LIST_REMOVE(object_managers, slot->node_object_manager.node->object_managers, &slot->node_object_manager);
+                        slot->bus->nodes_modified = true;
+
+                        bus_node_gc(slot->bus, slot->node_object_manager.node);
+                }
+
+                break;
+
+        case BUS_NODE_VTABLE:
+
+                if (slot->node_vtable.node && slot->node_vtable.interface && slot->node_vtable.vtable) {
+                        const sd_bus_vtable *v;
+
+                        for (v = slot->node_vtable.vtable; v->type != _SD_BUS_VTABLE_END; v++) {
+                                struct vtable_member *x = NULL;
+
+                                switch (v->type) {
+
+                                case _SD_BUS_VTABLE_METHOD: {
+                                        struct vtable_member key;
+
+                                        key.path = slot->node_vtable.node->path;
+                                        key.interface = slot->node_vtable.interface;
+                                        key.member = v->x.method.member;
+
+                                        x = hashmap_remove(slot->bus->vtable_methods, &key);
+                                        break;
+                                }
+
+                                case _SD_BUS_VTABLE_PROPERTY:
+                                case _SD_BUS_VTABLE_WRITABLE_PROPERTY: {
+                                        struct vtable_member key;
+
+                                        key.path = slot->node_vtable.node->path;
+                                        key.interface = slot->node_vtable.interface;
+                                        key.member = v->x.method.member;
+
+
+                                        x = hashmap_remove(slot->bus->vtable_properties, &key);
+                                        break;
+                                }}
+
+                                free(x);
+                        }
+                }
+
+                free(slot->node_vtable.interface);
+
+                if (slot->node_vtable.node) {
+                        LIST_REMOVE(vtables, slot->node_vtable.node->vtables, &slot->node_vtable);
+                        slot->bus->nodes_modified = true;
+
+                        bus_node_gc(slot->bus, slot->node_vtable.node);
+                }
+
+                break;
+        }
+        bus = slot->bus;
+
+        slot->type = _BUS_SLOT_DISCONNECTED;
+        slot->bus = NULL;
+        LIST_REMOVE(slots, bus->slots, slot);
+
+        if (!slot->floating)
+                sd_bus_unref(bus);
+}
+
+_public_ sd_bus_slot* sd_bus_slot_unref(sd_bus_slot *slot) {
+
+        if (!slot)
+                return NULL;
+
+        assert(slot->n_ref > 0);
+
+        if (slot->n_ref > 1) {
+                slot->n_ref --;
+                return NULL;
+        }
+
+        bus_slot_disconnect(slot);
+        free(slot);
+
+        return NULL;
+}
+
+_public_ sd_bus* sd_bus_slot_get_bus(sd_bus_slot *slot) {
+        assert_return(slot, NULL);
+
+        return slot->bus;
+}
+
+_public_ void *sd_bus_slot_get_userdata(sd_bus_slot *slot) {
+        assert_return(slot, NULL);
+
+        return slot->userdata;
+}
+
+_public_ void *sd_bus_slot_set_userdata(sd_bus_slot *slot, void *userdata) {
+        void *ret;
+
+        assert_return(slot, NULL);
+
+        ret = slot->userdata;
+        slot->userdata = userdata;
+
+        return ret;
+}
+
+_public_ sd_bus_message *sd_bus_slot_get_current_message(sd_bus_slot *slot) {
+        assert_return(slot, NULL);
+        assert_return(slot->type != _BUS_SLOT_DISCONNECTED, NULL);
+
+        if (slot->bus->current_slot != slot)
+                return NULL;
+
+        return slot->bus->current_message;
+}
diff --git a/src/libsystemd/sd-bus/bus-slot.h b/src/libsystemd/sd-bus/bus-slot.h
new file mode 100644 (file)
index 0000000..23a15e4
--- /dev/null
@@ -0,0 +1,29 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+#pragma once
+
+/***
+  This file is part of systemd.
+
+  Copyright 2014 Lennart Poettering
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include "sd-bus.h"
+#include "bus-internal.h"
+
+sd_bus_slot *bus_slot_allocate(sd_bus *bus, bool floating, BusSlotType type, size_t extra, void *userdata);
+
+void bus_slot_disconnect(sd_bus_slot *slot);
index 0f6a2eafbdf7730d3f0022e37aeb798563a661bf..ffa2cf3d75afe21fc0bf1eb3920eaf3a632bc0e1 100644 (file)
@@ -21,6 +21,7 @@
 
 #include "sd-bus.h"
 #include "set.h"
+#include "bus-util.h"
 #include "bus-internal.h"
 #include "bus-track.h"
 
@@ -29,7 +30,7 @@ struct sd_bus_track {
         sd_bus *bus;
         sd_bus_track_handler_t handler;
         void *userdata;
-        Set *names;
+        Hashmap *names;
         LIST_FIELDS(sd_bus_track, queue);
         Iterator iterator;
         bool in_queue;
@@ -128,11 +129,11 @@ _public_ sd_bus_track* sd_bus_track_unref(sd_bus_track *track) {
                 return NULL;
         }
 
-        while ((n = set_first(track->names)))
+        while ((n = hashmap_first_key(track->names)))
                 sd_bus_track_remove_name(track, n);
 
         bus_track_remove_from_queue(track);
-        set_free(track->names);
+        hashmap_free(track->names);
         sd_bus_unref(track->bus);
         free(track);
 
@@ -157,6 +158,7 @@ static int on_name_owner_changed(sd_bus *bus, sd_bus_message *message, void *use
 }
 
 _public_ int sd_bus_track_add_name(sd_bus_track *track, const char *name) {
+        _cleanup_bus_slot_unref_ sd_bus_slot *slot = NULL;
         _cleanup_free_ char *n = NULL;
         const char *match;
         int r;
@@ -164,7 +166,7 @@ _public_ int sd_bus_track_add_name(sd_bus_track *track, const char *name) {
         assert_return(track, -EINVAL);
         assert_return(service_name_is_valid(name), -EINVAL);
 
-        r = set_ensure_allocated(&track->names, string_hash_func, string_compare_func);
+        r = hashmap_ensure_allocated(&track->names, string_hash_func, string_compare_func);
         if (r < 0)
                 return r;
 
@@ -172,30 +174,28 @@ _public_ int sd_bus_track_add_name(sd_bus_track *track, const char *name) {
         if (!n)
                 return -ENOMEM;
 
-        r = set_put(track->names, n);
+        /* First, subscribe to this name */
+        match = MATCH_FOR_NAME(n);
+        r = sd_bus_add_match(track->bus, &slot, match, on_name_owner_changed, track);
+        if (r < 0)
+                return r;
+
+        r = hashmap_put(track->names, n, slot);
         if (r == -EEXIST)
                 return 0;
         if (r < 0)
                 return r;
 
-        /* First, subscribe to this name */
-        match = MATCH_FOR_NAME(name);
-        r = sd_bus_add_match(track->bus, match, on_name_owner_changed, track);
-        if (r < 0) {
-                set_remove(track->names, n);
-                return r;
-        }
-
         /* Second, check if it is currently existing, or maybe
          * doesn't, or maybe disappeared already. */
-        r = sd_bus_get_owner(track->bus, name, 0, NULL);
+        r = sd_bus_get_owner(track->bus, n, 0, NULL);
         if (r < 0) {
-                set_remove(track->names, n);
-                sd_bus_remove_match(track->bus, match, on_name_owner_changed, track);
+                hashmap_remove(track->names, n);
                 return r;
         }
 
         n = NULL;
+        slot = NULL;
 
         bus_track_remove_from_queue(track);
         track->modified = true;
@@ -204,22 +204,19 @@ _public_ int sd_bus_track_add_name(sd_bus_track *track, const char *name) {
 }
 
 _public_ int sd_bus_track_remove_name(sd_bus_track *track, const char *name) {
-        const char *match;
-        _cleanup_free_ char *n = NULL;;
+        _cleanup_bus_slot_unref_ sd_bus_slot *slot = NULL;
+        _cleanup_free_ char *n = NULL;
 
         assert_return(name, -EINVAL);
 
         if (!track)
                 return 0;
 
-        n = set_remove(track->names, (char*) name);
-        if (!n)
+        slot = hashmap_remove2(track->names, (char*) name, (void**) &n);
+        if (!slot)
                 return 0;
 
-        match = MATCH_FOR_NAME(n);
-        sd_bus_remove_match(track->bus, match, on_name_owner_changed, track);
-
-        if (set_isempty(track->names))
+        if (hashmap_isempty(track->names))
                 bus_track_add_to_queue(track);
 
         track->modified = true;
@@ -231,34 +228,40 @@ _public_ unsigned sd_bus_track_count(sd_bus_track *track) {
         if (!track)
                 return 0;
 
-        return set_size(track->names);
+        return hashmap_size(track->names);
 }
 
 _public_ const char* sd_bus_track_contains(sd_bus_track *track, const char *name) {
         assert_return(track, NULL);
         assert_return(name, NULL);
 
-        return set_get(track->names, (void*) name);
+        return hashmap_get(track->names, (void*) name) ? name : NULL;
 }
 
 _public_ const char* sd_bus_track_first(sd_bus_track *track) {
+        const char *n = NULL;
+
         if (!track)
                 return NULL;
 
         track->modified = false;
         track->iterator = NULL;
 
-        return set_iterate(track->names, &track->iterator);
+        hashmap_iterate(track->names, &track->iterator, (const void**) &n);
+        return n;
 }
 
 _public_ const char* sd_bus_track_next(sd_bus_track *track) {
+        const char *n = NULL;
+
         if (!track)
                 return NULL;
 
         if (track->modified)
                 return NULL;
 
-        return set_iterate(track->names, &track->iterator);
+        hashmap_iterate(track->names, &track->iterator, (const void**) &n);
+        return n;
 }
 
 _public_ int sd_bus_track_add_sender(sd_bus_track *track, sd_bus_message *m) {
index 84b3fc5af5d44912c629ed123b55a3cc01b87b12..b5b3c857b8afc3075f38fe363d49b285f0365b54 100644 (file)
@@ -77,7 +77,7 @@ int bus_async_unregister_and_exit(sd_event *e, sd_bus *bus, const char *name) {
         if (r < 0)
                 return -ENOMEM;
 
-        r = sd_bus_add_match(bus, match, name_owner_change_callback, e);
+        r = sd_bus_add_match(bus, NULL, match, name_owner_change_callback, e);
         if (r < 0)
                 return r;
 
@@ -251,17 +251,16 @@ typedef struct AsyncPolkitQuery {
         sd_bus_message *request, *reply;
         sd_bus_message_handler_t callback;
         void *userdata;
-        uint64_t serial;
+        sd_bus_slot *slot;
         Hashmap *registry;
 } AsyncPolkitQuery;
 
-static void async_polkit_query_free(sd_bus *b, AsyncPolkitQuery *q) {
+static void async_polkit_query_free(AsyncPolkitQuery *q) {
 
         if (!q)
                 return;
 
-        if (q->serial > 0 && b)
-                sd_bus_call_async_cancel(b, q->serial);
+        sd_bus_slot_unref(q->slot);
 
         if (q->registry && q->request)
                 hashmap_remove(q->registry, q->request);
@@ -281,8 +280,8 @@ static int async_polkit_callback(sd_bus *bus, sd_bus_message *reply, void *userd
         assert(reply);
         assert(q);
 
+        q->slot = sd_bus_slot_unref(q->slot);
         q->reply = sd_bus_message_ref(reply);
-        q->serial = 0;
 
         r = sd_bus_message_rewind(q->request, true);
         if (r < 0) {
@@ -294,7 +293,8 @@ static int async_polkit_callback(sd_bus *bus, sd_bus_message *reply, void *userd
         r = bus_maybe_reply_error(q->request, r, &error_buffer);
 
 finish:
-        async_polkit_query_free(bus, q);
+        async_polkit_query_free(q);
+
         return r;
 }
 
@@ -413,15 +413,15 @@ int bus_verify_polkit_async(
 
         r = hashmap_put(*registry, m, q);
         if (r < 0) {
-                async_polkit_query_free(bus, q);
+                async_polkit_query_free(q);
                 return r;
         }
 
         q->registry = *registry;
 
-        r = sd_bus_call_async(bus, pk, async_polkit_callback, q, 0, &q->serial);
+        r = sd_bus_call_async(bus, &q->slot, pk, async_polkit_callback, q, 0);
         if (r < 0) {
-                async_polkit_query_free(bus, q);
+                async_polkit_query_free(q);
                 return r;
         }
 
@@ -436,7 +436,7 @@ void bus_verify_polkit_async_registry_free(sd_bus *bus, Hashmap *registry) {
         AsyncPolkitQuery *q;
 
         while ((q = hashmap_steal_first(registry)))
-                async_polkit_query_free(bus, q);
+                async_polkit_query_free(q);
 
         hashmap_free(registry);
 #endif
index 8103555fe8f9c2749af724d5e8680ea7d0eb12d3..1514fad81f737d2a339858aefd5eb672174933f4 100644 (file)
@@ -139,12 +139,16 @@ typedef struct UnitInfo {
 int bus_parse_unit_info(sd_bus_message *message, UnitInfo *u);
 
 DEFINE_TRIVIAL_CLEANUP_FUNC(sd_bus*, sd_bus_unref);
+DEFINE_TRIVIAL_CLEANUP_FUNC(sd_bus_slot*, sd_bus_slot_unref);
 DEFINE_TRIVIAL_CLEANUP_FUNC(sd_bus_message*, sd_bus_message_unref);
 DEFINE_TRIVIAL_CLEANUP_FUNC(sd_bus_creds*, sd_bus_creds_unref);
+DEFINE_TRIVIAL_CLEANUP_FUNC(sd_bus_track*, sd_bus_track_unref);
 
 #define _cleanup_bus_unref_ _cleanup_(sd_bus_unrefp)
+#define _cleanup_bus_slot_unref_ _cleanup_(sd_bus_slot_unrefp)
 #define _cleanup_bus_message_unref_ _cleanup_(sd_bus_message_unrefp)
 #define _cleanup_bus_creds_unref_ _cleanup_(sd_bus_creds_unrefp)
+#define _cleanup_bus_track_unref_ _cleanup_(sd_bus_slot_unrefp)
 #define _cleanup_bus_error_free_ _cleanup_(sd_bus_error_free)
 
 #define BUS_DEFINE_PROPERTY_GET_ENUM(function, name, type)              \
index 4e396f20c1e9c3cb697b68ba55d2fbfa0b3f600d..454504701141df862114d3908218025b6e7ed136 100644 (file)
@@ -240,7 +240,7 @@ static int monitor(sd_bus *bus, char *argv[]) {
                 if (!m)
                         return log_oom();
 
-                r = sd_bus_add_match(bus, m, NULL, NULL);
+                r = sd_bus_add_match(bus, NULL, m, NULL, NULL);
                 if (r < 0) {
                         log_error("Failed to add match: %s", strerror(-r));
                         return r;
@@ -250,7 +250,7 @@ static int monitor(sd_bus *bus, char *argv[]) {
         }
 
         STRV_FOREACH(i, arg_matches) {
-                r = sd_bus_add_match(bus, *i, NULL, NULL);
+                r = sd_bus_add_match(bus, NULL, *i, NULL, NULL);
                 if (r < 0) {
                         log_error("Failed to add match: %s", strerror(-r));
                         return r;
@@ -260,7 +260,7 @@ static int monitor(sd_bus *bus, char *argv[]) {
         }
 
         if (!added_something) {
-                r = sd_bus_add_match(bus, "", NULL, NULL);
+                r = sd_bus_add_match(bus, NULL, "", NULL, NULL);
                 if (r < 0) {
                         log_error("Failed to add match: %s", strerror(-r));
                         return r;
index dc54e211a490b3918a400bc7c8eebfa5a0da780f..ea80e9d19b5e1ad5d8c5807e0224b2c39d56da7e 100644 (file)
@@ -52,6 +52,7 @@
 #include "bus-container.h"
 #include "bus-protocol.h"
 #include "bus-track.h"
+#include "bus-slot.h"
 
 static int bus_poll(sd_bus *bus, bool need_more, uint64_t timeout_usec);
 static int attach_io_events(sd_bus *b);
@@ -71,43 +72,6 @@ static void bus_close_fds(sd_bus *b) {
         b->input_fd = b->output_fd = -1;
 }
 
-static void bus_node_destroy(sd_bus *b, struct node *n) {
-        struct node_callback *c;
-        struct node_vtable *v;
-        struct node_enumerator *e;
-
-        assert(b);
-
-        if (!n)
-                return;
-
-        while (n->child)
-                bus_node_destroy(b, n->child);
-
-        while ((c = n->callbacks)) {
-                LIST_REMOVE(callbacks, n->callbacks, c);
-                free(c);
-        }
-
-        while ((v = n->vtables)) {
-                LIST_REMOVE(vtables, n->vtables, v);
-                free(v->interface);
-                free(v);
-        }
-
-        while ((e = n->enumerators)) {
-                LIST_REMOVE(enumerators, n->enumerators, e);
-                free(e);
-        }
-
-        if (n->parent)
-                LIST_REMOVE(siblings, n->parent->child, n);
-
-        assert_se(hashmap_remove(b->nodes, n->path) == n);
-        free(n->path);
-        free(n);
-}
-
 static void bus_reset_queues(sd_bus *b) {
         assert(b);
 
@@ -133,15 +97,28 @@ static void bus_reset_queues(sd_bus *b) {
 }
 
 static void bus_free(sd_bus *b) {
-        struct filter_callback *f;
-        struct node *n;
+        sd_bus_slot *s;
 
         assert(b);
-
         assert(!b->track_queue);
 
+        b->state = BUS_CLOSED;
+
         sd_bus_detach_event(b);
 
+        while ((s = b->slots)) {
+                /* At this point only floating slots can still be
+                 * around, because the non-floating ones keep a
+                 * reference to the bus, and we thus couldn't be
+                 * destructing right now... We forcibly disconnect the
+                 * slots here, so that they still can be referenced by
+                 * apps, but are dead. */
+
+                assert(s->floating);
+                bus_slot_disconnect(s);
+                sd_bus_slot_unref(s);
+        }
+
         if (b->default_bus_ptr)
                 *b->default_bus_ptr = NULL;
 
@@ -171,19 +148,12 @@ static void bus_free(sd_bus *b) {
         hashmap_free_free(b->reply_callbacks);
         prioq_free(b->reply_callbacks_prioq);
 
-        while ((f = b->filter_callbacks)) {
-                LIST_REMOVE(callbacks, b->filter_callbacks, f);
-                free(f);
-        }
-
         bus_match_free(&b->match_callbacks);
 
         hashmap_free_free(b->vtable_methods);
         hashmap_free_free(b->vtable_properties);
 
-        while ((n = hashmap_first(b->nodes)))
-                bus_node_destroy(b, n);
-
+        assert(hashmap_isempty(b->nodes));
         hashmap_free(b->nodes);
 
         bus_kernel_flush_memfd(b);
@@ -426,7 +396,7 @@ static int bus_send_hello(sd_bus *bus) {
         if (r < 0)
                 return r;
 
-        return sd_bus_call_async(bus, m, hello_callback, NULL, 0, &bus->hello_cookie);
+        return sd_bus_call_async(bus, NULL, m, hello_callback, NULL, 0);
 }
 
 int bus_start_running(sd_bus *bus) {
@@ -1793,14 +1763,14 @@ static int timeout_compare(const void *a, const void *b) {
 
 _public_ int sd_bus_call_async(
                 sd_bus *bus,
+                sd_bus_slot **slot,
                 sd_bus_message *_m,
                 sd_bus_message_handler_t callback,
                 void *userdata,
-                uint64_t usec,
-                uint64_t *cookie) {
+                uint64_t usec) {
 
         _cleanup_bus_message_unref_ sd_bus_message *m = sd_bus_message_ref(_m);
-        struct reply_callback *c;
+        _cleanup_bus_slot_unref_ sd_bus_slot *s = NULL;
         int r;
 
         assert_return(bus, -EINVAL);
@@ -1830,55 +1800,37 @@ _public_ int sd_bus_call_async(
         if (r < 0)
                 return r;
 
-        c = new0(struct reply_callback, 1);
-        if (!c)
+        s = bus_slot_allocate(bus, !slot, BUS_REPLY_CALLBACK, sizeof(struct reply_callback), userdata);
+        if (!s)
                 return -ENOMEM;
 
-        c->callback = callback;
-        c->userdata = userdata;
-        c->cookie = BUS_MESSAGE_COOKIE(m);
-        c->timeout = calc_elapse(m->timeout);
+        s->reply_callback.callback = callback;
 
-        r = hashmap_put(bus->reply_callbacks, &c->cookie, c);
+        s->reply_callback.cookie = BUS_MESSAGE_COOKIE(m);
+        r = hashmap_put(bus->reply_callbacks, &s->reply_callback.cookie, &s->reply_callback);
         if (r < 0) {
-                free(c);
+                s->reply_callback.cookie = 0;
                 return r;
         }
 
-        if (c->timeout != 0) {
-                r = prioq_put(bus->reply_callbacks_prioq, c, &c->prioq_idx);
+        s->reply_callback.timeout = calc_elapse(m->timeout);
+        if (s->reply_callback.timeout != 0) {
+                r = prioq_put(bus->reply_callbacks_prioq, &s->reply_callback, &s->reply_callback.prioq_idx);
                 if (r < 0) {
-                        c->timeout = 0;
-                        sd_bus_call_async_cancel(bus, c->cookie);
+                        s->reply_callback.timeout = 0;
                         return r;
                 }
         }
 
-        r = sd_bus_send(bus, m, cookie);
-        if (r < 0) {
-                sd_bus_call_async_cancel(bus, c->cookie);
+        r = sd_bus_send(bus, m, &s->reply_callback.cookie);
+        if (r < 0)
                 return r;
-        }
-
-        return r;
-}
-
-_public_ int sd_bus_call_async_cancel(sd_bus *bus, uint64_t cookie) {
-        struct reply_callback *c;
 
-        assert_return(bus, -EINVAL);
-        assert_return(cookie != 0, -EINVAL);
-        assert_return(!bus_pid_changed(bus), -ECHILD);
-
-        c = hashmap_remove(bus->reply_callbacks, &cookie);
-        if (!c)
-                return 0;
-
-        if (c->timeout != 0)
-                prioq_remove(bus->reply_callbacks_prioq, c, &c->prioq_idx);
+        if (slot)
+                *slot = s;
+        s = NULL;
 
-        free(c);
-        return 1;
+        return r;
 }
 
 int bus_ensure_running(sd_bus *bus) {
@@ -2125,6 +2077,11 @@ _public_ int sd_bus_get_timeout(sd_bus *bus, uint64_t *timeout_usec) {
                 return 0;
         }
 
+        if (c->timeout == 0) {
+                *timeout_usec = (uint64_t) -1;
+                return 0;
+        }
+
         *timeout_usec = c->timeout;
         return 1;
 }
@@ -2161,16 +2118,21 @@ static int process_timeout(sd_bus *bus) {
                 return r;
 
         assert_se(prioq_pop(bus->reply_callbacks_prioq) == c);
+        c->timeout = 0;
+
         hashmap_remove(bus->reply_callbacks, &c->cookie);
+        c->cookie = 0;
+
+        bus->current_message = m;
+        bus->current_slot = container_of(c, sd_bus_slot, reply_callback);
 
-        bus->current = m;
         bus->iteration_counter ++;
 
-        r = c->callback(bus, m, c->userdata, &error_buffer);
+        r = c->callback(bus, m, bus->current_slot->userdata, &error_buffer);
         r = bus_maybe_reply_error(m, r, &error_buffer);
-        free(c);
 
-        bus->current = NULL;
+        bus->current_message = NULL;
+        bus->current_slot = NULL;
 
         return r;
 }
@@ -2191,7 +2153,7 @@ static int process_hello(sd_bus *bus, sd_bus_message *m) {
             m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
                 return -EIO;
 
-        if (m->reply_cookie != bus->hello_cookie)
+        if (m->reply_cookie != 1)
                 return -EIO;
 
         return 0;
@@ -2200,7 +2162,8 @@ static int process_hello(sd_bus *bus, sd_bus_message *m) {
 static int process_reply(sd_bus *bus, sd_bus_message *m) {
         _cleanup_bus_message_unref_ sd_bus_message *synthetic_reply = NULL;
         _cleanup_bus_error_free_ sd_bus_error error_buffer = SD_BUS_ERROR_NULL;
-        _cleanup_free_ struct reply_callback *c = NULL;
+        sd_bus_slot *slot;
+        struct reply_callback *c;
         int r;
 
         assert(bus);
@@ -2220,8 +2183,13 @@ static int process_reply(sd_bus *bus, sd_bus_message *m) {
         if (!c)
                 return 0;
 
-        if (c->timeout != 0)
+        c->cookie = 0;
+        slot = container_of(c, sd_bus_slot, reply_callback);
+
+        if (c->timeout != 0) {
                 prioq_remove(bus->reply_callbacks_prioq, c, &c->prioq_idx);
+                c->timeout = 0;
+        }
 
         if (m->n_fds > 0 && !(bus->hello_flags & KDBUS_HELLO_ACCEPT_FD)) {
 
@@ -2234,22 +2202,31 @@ static int process_reply(sd_bus *bus, sd_bus_message *m) {
                                 &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INCONSISTENT_MESSAGE, "Reply message contained file descriptor"),
                                 &synthetic_reply);
                 if (r < 0)
-                        return r;
+                        goto finish;
 
                 r = bus_seal_synthetic_message(bus, synthetic_reply);
                 if (r < 0)
-                        return r;
+                        goto finish;
 
                 m = synthetic_reply;
         } else {
                 r = sd_bus_message_rewind(m, true);
                 if (r < 0)
-                        return r;
+                        goto finish;
         }
 
-        r = c->callback(bus, m, c->userdata, &error_buffer);
+        bus->current_slot = slot;
+        r = c->callback(bus, m, bus->current_slot->userdata, &error_buffer);
+        bus->current_slot = NULL;
+
         r = bus_maybe_reply_error(m, r, &error_buffer);
 
+finish:
+        if (slot->floating) {
+                bus_slot_disconnect(slot);
+                sd_bus_slot_unref(slot);
+        }
+
         return r;
 }
 
@@ -2279,7 +2256,10 @@ static int process_filter(sd_bus *bus, sd_bus_message *m) {
                         if (r < 0)
                                 return r;
 
-                        r = l->callback(bus, m, l->userdata, &error_buffer);
+                        bus->current_slot = container_of(l, sd_bus_slot, filter_callback);
+                        r = l->callback(bus, m, bus->current_slot->userdata, &error_buffer);
+                        bus->current_slot = NULL;
+
                         r = bus_maybe_reply_error(m, r, &error_buffer);
                         if (r != 0)
                                 return r;
@@ -2395,7 +2375,7 @@ static int process_message(sd_bus *bus, sd_bus_message *m) {
         assert(bus);
         assert(m);
 
-        bus->current = m;
+        bus->current_message = m;
         bus->iteration_counter++;
 
         log_debug("Got message type=%s sender=%s destination=%s object=%s interface=%s member=%s cookie=%" PRIu64 " reply_cookie=%" PRIu64 " error=%s",
@@ -2436,7 +2416,7 @@ static int process_message(sd_bus *bus, sd_bus_message *m) {
         r = bus_process_object(bus, m);
 
 finish:
-        bus->current = NULL;
+        bus->current_message = NULL;
         return r;
 }
 
@@ -2539,17 +2519,23 @@ static int process_closing(sd_bus *bus, sd_bus_message **ret) {
                 if (r < 0)
                         return r;
 
-                if (c->timeout != 0)
+                if (c->timeout != 0) {
                         prioq_remove(bus->reply_callbacks_prioq, c, &c->prioq_idx);
+                        c->timeout = 0;
+                }
 
                 hashmap_remove(bus->reply_callbacks, &c->cookie);
+                c->cookie = 0;
+
+                bus->current_message = m;
+                bus->current_slot = container_of(c, sd_bus_slot, reply_callback);
 
-                bus->current = m;
                 bus->iteration_counter++;
 
-                r = c->callback(bus, m, c->userdata, &error_buffer);
+                r = c->callback(bus, m, bus->current_slot->userdata, &error_buffer);
                 r = bus_maybe_reply_error(m, r, &error_buffer);
-                free(c);
+
+                bus->current_slot = NULL;
 
                 goto finish;
         }
@@ -2572,7 +2558,7 @@ static int process_closing(sd_bus *bus, sd_bus_message **ret) {
 
         sd_bus_close(bus);
 
-        bus->current = m;
+        bus->current_message = m;
         bus->iteration_counter++;
 
         r = process_filter(bus, m);
@@ -2591,7 +2577,8 @@ static int process_closing(sd_bus *bus, sd_bus_message **ret) {
         r = 1;
 
 finish:
-        bus->current = NULL;
+        bus->current_message = NULL;
+
         return r;
 }
 
@@ -2608,7 +2595,8 @@ static int bus_process_internal(sd_bus *bus, bool hint_priority, int64_t priorit
         assert_return(!bus_pid_changed(bus), -ECHILD);
 
         /* We don't allow recursively invoking sd_bus_process(). */
-        assert_return(!bus->current, -EBUSY);
+        assert_return(!bus->current_message, -EBUSY);
+        assert(!bus->current_slot);
 
         switch (bus->state) {
 
@@ -2785,57 +2773,43 @@ _public_ int sd_bus_flush(sd_bus *bus) {
         }
 }
 
-_public_ int sd_bus_add_filter(sd_bus *bus,
-                               sd_bus_message_handler_t callback,
-                               void *userdata) {
+_public_ int sd_bus_add_filter(
+                sd_bus *bus,
+                sd_bus_slot **slot,
+                sd_bus_message_handler_t callback,
+                void *userdata) {
 
-        struct filter_callback *f;
+        sd_bus_slot *s;
 
         assert_return(bus, -EINVAL);
         assert_return(callback, -EINVAL);
         assert_return(!bus_pid_changed(bus), -ECHILD);
 
-        f = new0(struct filter_callback, 1);
-        if (!f)
+        s = bus_slot_allocate(bus, !slot, BUS_FILTER_CALLBACK, sizeof(struct filter_callback), userdata);
+        if (!s)
                 return -ENOMEM;
-        f->callback = callback;
-        f->userdata = userdata;
 
-        bus->filter_callbacks_modified = true;
-        LIST_PREPEND(callbacks, bus->filter_callbacks, f);
-        return 0;
-}
+        s->filter_callback.callback = callback;
 
-_public_ int sd_bus_remove_filter(sd_bus *bus,
-                                  sd_bus_message_handler_t callback,
-                                  void *userdata) {
-
-        struct filter_callback *f;
-
-        assert_return(bus, -EINVAL);
-        assert_return(callback, -EINVAL);
-        assert_return(!bus_pid_changed(bus), -ECHILD);
+        bus->filter_callbacks_modified = true;
+        LIST_PREPEND(callbacks, bus->filter_callbacks, &s->filter_callback);
 
-        LIST_FOREACH(callbacks, f, bus->filter_callbacks) {
-                if (f->callback == callback && f->userdata == userdata) {
-                        bus->filter_callbacks_modified = true;
-                        LIST_REMOVE(callbacks, bus->filter_callbacks, f);
-                        free(f);
-                        return 1;
-                }
-        }
+        if (slot)
+                *slot = s;
 
         return 0;
 }
 
-_public_ int sd_bus_add_match(sd_bus *bus,
-                              const char *match,
-                              sd_bus_message_handler_t callback,
-                              void *userdata) {
+_public_ int sd_bus_add_match(
+                sd_bus *bus,
+                sd_bus_slot **slot,
+                const char *match,
+                sd_bus_message_handler_t callback,
+                void *userdata) {
 
         struct bus_match_component *components = NULL;
         unsigned n_components = 0;
-        uint64_t cookie = 0;
+        sd_bus_slot *s;
         int r = 0;
 
         assert_return(bus, -EINVAL);
@@ -2846,35 +2820,60 @@ _public_ int sd_bus_add_match(sd_bus *bus,
         if (r < 0)
                 goto finish;
 
+        s = bus_slot_allocate(bus, !slot, BUS_MATCH_CALLBACK, sizeof(struct match_callback), userdata);
+        if (!s) {
+                r = -ENOMEM;
+                goto finish;
+        }
+
+        s->match_callback.callback = callback;
+        s->match_callback.cookie = ++bus->match_cookie;
+
         if (bus->bus_client) {
-                cookie = ++bus->match_cookie;
 
-                r = bus_add_match_internal(bus, match, components, n_components, cookie);
+                if (!bus->is_kernel) {
+                        /* When this is not a kernel transport, we
+                         * store the original match string, so that we
+                         * can use it to remove the match again */
+
+                        s->match_callback.match_string = strdup(match);
+                        if (!s->match_callback.match_string) {
+                                r = -ENOMEM;
+                                goto finish;
+                        }
+                }
+
+                r = bus_add_match_internal(bus, s->match_callback.match_string, components, n_components, s->match_callback.cookie);
                 if (r < 0)
                         goto finish;
         }
 
         bus->match_callbacks_modified = true;
-        r = bus_match_add(&bus->match_callbacks, components, n_components, callback, userdata, cookie, NULL);
-        if (r < 0) {
-                if (bus->bus_client)
-                        bus_remove_match_internal(bus, match, cookie);
-        }
+        r = bus_match_add(&bus->match_callbacks, components, n_components, &s->match_callback);
+        if (r < 0)
+                goto finish;
+
+        if (slot)
+                *slot = s;
+        s = NULL;
 
 finish:
         bus_match_parse_free(components, n_components);
+        sd_bus_slot_unref(s);
+
         return r;
 }
 
-_public_ int sd_bus_remove_match(sd_bus *bus,
-                                 const char *match,
-                                 sd_bus_message_handler_t callback,
-                                 void *userdata) {
+int bus_remove_match_by_string(
+                sd_bus *bus,
+                const char *match,
+                sd_bus_message_handler_t callback,
+                void *userdata) {
 
         struct bus_match_component *components = NULL;
         unsigned n_components = 0;
-        int r = 0, q = 0;
-        uint64_t cookie = 0;
+        struct match_callback *c;
+        int r = 0;
 
         assert_return(bus, -EINVAL);
         assert_return(match, -EINVAL);
@@ -2882,17 +2881,18 @@ _public_ int sd_bus_remove_match(sd_bus *bus,
 
         r = bus_match_parse(match, &components, &n_components);
         if (r < 0)
-                return r;
+                goto finish;
 
-        bus->match_callbacks_modified = true;
-        r = bus_match_remove(&bus->match_callbacks, components, n_components, callback, userdata, &cookie);
+        r = bus_match_find(&bus->match_callbacks, components, n_components, NULL, NULL, &c);
+        if (r <= 0)
+                goto finish;
 
-        if (bus->bus_client)
-                q = bus_remove_match_internal(bus, match, cookie);
+        sd_bus_slot_unref(container_of(c, sd_bus_slot, match_callback));
 
+finish:
         bus_match_parse_free(components, n_components);
 
-        return r < 0 ? r : q;
+        return r;
 }
 
 bool bus_pid_changed(sd_bus *bus) {
@@ -3116,10 +3116,16 @@ _public_ sd_event* sd_bus_get_event(sd_bus *bus) {
         return bus->event;
 }
 
-_public_ sd_bus_message* sd_bus_get_current(sd_bus *bus) {
+_public_ sd_bus_message* sd_bus_get_current_message(sd_bus *bus) {
+        assert_return(bus, NULL);
+
+        return bus->current_message;
+}
+
+_public_ sd_bus_slot* sd_bus_get_current_slot(sd_bus *bus) {
         assert_return(bus, NULL);
 
-        return bus->current;
+        return bus->current_slot;
 }
 
 static int bus_default(int (*bus_open)(sd_bus **), sd_bus **default_bus, sd_bus **ret) {
index c0abc7a69795864a8ba34b16980928a4970efa60..c9eb69843d5c4be1b519dd94f6144cc7f2bca2dc 100644 (file)
@@ -100,19 +100,19 @@ static int server_init(sd_bus **_bus) {
                 goto fail;
         }
 
-        r = sd_bus_add_fallback(bus, "/foo/bar", object_callback, NULL);
+        r = sd_bus_add_fallback(bus, NULL, "/foo/bar", object_callback, NULL);
         if (r < 0) {
                 log_error("Failed to add object: %s", strerror(-r));
                 goto fail;
         }
 
-        r = sd_bus_add_match(bus, "type='signal',interface='foo.bar',member='Notify'", match_callback, NULL);
+        r = sd_bus_add_match(bus, NULL, "type='signal',interface='foo.bar',member='Notify'", match_callback, NULL);
         if (r < 0) {
                 log_error("Failed to add match: %s", strerror(-r));
                 goto fail;
         }
 
-        r = sd_bus_add_match(bus, "type='signal',interface='org.freedesktop.DBus',member='NameOwnerChanged'", match_callback, NULL);
+        r = sd_bus_add_match(bus, NULL, "type='signal',interface='org.freedesktop.DBus',member='NameOwnerChanged'", match_callback, NULL);
         if (r < 0) {
                 log_error("Failed to add match: %s", strerror(-r));
                 goto fail;
@@ -490,7 +490,7 @@ static void* client2(void*p) {
                 goto finish;
         }
 
-        r = sd_bus_call_async(bus, m, quit_callback, &quit, 200 * USEC_PER_MSEC, NULL);
+        r = sd_bus_call_async(bus, NULL, m, quit_callback, &quit, 200 * USEC_PER_MSEC);
         if (r < 0) {
                 log_info("Failed to issue method call: %s", bus_error_message(&error, -r));
                 goto finish;
index 0ecad18f45f2e32b0892158d033f693b53c585b5..5ee6eea0e8ad56c1499db1ecd5fd42f80b238481 100644 (file)
@@ -72,7 +72,7 @@ static void test_one(
         assert_se(r >= 0);
 
         log_debug("match");
-        r = sd_bus_add_match(b, match, NULL, NULL);
+        r = sd_bus_add_match(b, NULL, match, NULL, NULL);
         assert_se(r >= 0);
 
         log_debug("signal");
index 34d000f1c654d31e4c022ea63a1818a79c7cfba5..7bb8b0a5407036f5dae157bc7b7bbd2a875ba515 100644 (file)
@@ -101,7 +101,7 @@ int main(int argc, char *argv[]) {
         assert_se(sd_bus_error_has_name(&error, SD_BUS_ERROR_SERVICE_UNKNOWN));
         assert_se(r == -EHOSTUNREACH);
 
-        r = sd_bus_add_match(b, "interface='waldo.com',member='Piep'", NULL, NULL);
+        r = sd_bus_add_match(b, NULL, "interface='waldo.com',member='Piep'", NULL, NULL);
         assert_se(r >= 0);
 
         r = sd_bus_emit_signal(a, "/foo/bar/waldo", "waldo.com", "Piep", "sss", "I am a string", "/this/is/a/path", "and.this.a.domain.name");
index c561be2a65539cc61c6c1634c1942476429fc784..a62de502f94cc4afcbd169fa07a94b1f19829c0a 100644 (file)
@@ -28,6 +28,7 @@
 #include "bus-match.h"
 #include "bus-message.h"
 #include "bus-util.h"
+#include "bus-slot.h"
 
 static bool mask[32];
 
@@ -56,31 +57,23 @@ static bool mask_contains(unsigned a[], unsigned n) {
         return true;
 }
 
-static int match_add(struct bus_match_node *root, const char *match, int value) {
+static int match_add(sd_bus_slot *slots, struct bus_match_node *root, const char *match, int value) {
         struct bus_match_component *components = NULL;
         unsigned n_components = 0;
+        sd_bus_slot *s;
         int r;
 
-        r = bus_match_parse(match, &components, &n_components);
-        if (r < 0)
-                return r;
-
-        r = bus_match_add(root, components, n_components, filter, INT_TO_PTR(value), 0, NULL);
-        bus_match_parse_free(components, n_components);
-
-        return r;
-}
-
-static int match_remove(struct bus_match_node *root, const char *match, int value) {
-        struct bus_match_component *components = NULL;
-        unsigned n_components = 0;
-        int r;
+        s = slots + value;
+        zero(*s);
 
         r = bus_match_parse(match, &components, &n_components);
         if (r < 0)
                 return r;
 
-        r = bus_match_remove(root, components, n_components, filter, INT_TO_PTR(value), 0);
+        s->userdata = INT_TO_PTR(value);
+        s->match_callback.callback = filter;
+
+        r = bus_match_add(root, components, n_components, &s->match_callback);
         bus_match_parse_free(components, n_components);
 
         return r;
@@ -90,24 +83,25 @@ int main(int argc, char *argv[]) {
         struct bus_match_node root;
         _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
         enum bus_match_node_type i;
+        sd_bus_slot slots[15];
 
         zero(root);
         root.type = BUS_MATCH_ROOT;
 
-        assert_se(match_add(&root, "arg2='wal\\'do',sender='foo',type='signal',interface='bar.x',", 1) >= 0);
-        assert_se(match_add(&root, "arg2='wal\\'do2',sender='foo',type='signal',interface='bar.x',", 2) >= 0);
-        assert_se(match_add(&root, "arg3='test',sender='foo',type='signal',interface='bar.x',", 3) >= 0);
-        assert_se(match_add(&root, "arg3='test',sender='foo',type='method_call',interface='bar.x',", 4) >= 0);
-        assert_se(match_add(&root, "", 5) >= 0);
-        assert_se(match_add(&root, "interface='quux.x'", 6) >= 0);
-        assert_se(match_add(&root, "interface='bar.x'", 7) >= 0);
-        assert_se(match_add(&root, "member='waldo',path='/foo/bar'", 8) >= 0);
-        assert_se(match_add(&root, "path='/foo/bar'", 9) >= 0);
-        assert_se(match_add(&root, "path_namespace='/foo'", 10) >= 0);
-        assert_se(match_add(&root, "path_namespace='/foo/quux'", 11) >= 0);
-        assert_se(match_add(&root, "arg1='two'", 12) >= 0);
-        assert_se(match_add(&root, "member='waldo',arg2path='/prefix/'", 13) >= 0);
-        assert_se(match_add(&root, "member=waldo,path='/foo/bar',arg3namespace='prefix'", 14) >= 0);
+        assert_se(match_add(slots, &root, "arg2='wal\\'do',sender='foo',type='signal',interface='bar.x',", 1) >= 0);
+        assert_se(match_add(slots, &root, "arg2='wal\\'do2',sender='foo',type='signal',interface='bar.x',", 2) >= 0);
+        assert_se(match_add(slots, &root, "arg3='test',sender='foo',type='signal',interface='bar.x',", 3) >= 0);
+        assert_se(match_add(slots, &root, "arg3='test',sender='foo',type='method_call',interface='bar.x',", 4) >= 0);
+        assert_se(match_add(slots, &root, "", 5) >= 0);
+        assert_se(match_add(slots, &root, "interface='quux.x'", 6) >= 0);
+        assert_se(match_add(slots, &root, "interface='bar.x'", 7) >= 0);
+        assert_se(match_add(slots, &root, "member='waldo',path='/foo/bar'", 8) >= 0);
+        assert_se(match_add(slots, &root, "path='/foo/bar'", 9) >= 0);
+        assert_se(match_add(slots, &root, "path_namespace='/foo'", 10) >= 0);
+        assert_se(match_add(slots, &root, "path_namespace='/foo/quux'", 11) >= 0);
+        assert_se(match_add(slots, &root, "arg1='two'", 12) >= 0);
+        assert_se(match_add(slots, &root, "member='waldo',arg2path='/prefix/'", 13) >= 0);
+        assert_se(match_add(slots, &root, "member=waldo,path='/foo/bar',arg3namespace='prefix'", 14) >= 0);
 
         bus_match_dump(&root, 0);
 
@@ -119,9 +113,8 @@ int main(int argc, char *argv[]) {
         assert_se(bus_match_run(NULL, &root, m) == 0);
         assert_se(mask_contains((unsigned[]) { 9, 8, 7, 5, 10, 12, 13, 14 }, 8));
 
-        assert_se(match_remove(&root, "member='waldo',path='/foo/bar'", 8) > 0);
-        assert_se(match_remove(&root, "arg2path='/prefix/',member='waldo'", 13) > 0);
-        assert_se(match_remove(&root, "interface='bar.xx'", 7) == 0);
+        assert_se(bus_match_remove(&root, &slots[8].match_callback) >= 0);
+        assert_se(bus_match_remove(&root, &slots[13].match_callback) >= 0);
 
         bus_match_dump(&root, 0);
 
index e2423c7f67d5b8b3b79c5cd0824048a16d169a6f..e7a445f3cbbc495ae931f9d2b4908e02f4698017 100644 (file)
@@ -200,7 +200,7 @@ static const sd_bus_vtable vtable2[] = {
         SD_BUS_VTABLE_END
 };
 
-static int enumerator_callback(sd_bus *b, const char *path, void *userdata, char ***nodes, sd_bus_error *error) {
+static int enumerator_callback(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) {
 
         if (object_path_startswith("/value", path))
                 assert_se(*nodes = strv_new("/value/a", "/value/b", "/value/c", NULL));
@@ -222,11 +222,11 @@ static void *server(void *p) {
         assert_se(sd_bus_set_fd(bus, c->fds[0], c->fds[0]) >= 0);
         assert_se(sd_bus_set_server(bus, 1, id) >= 0);
 
-        assert_se(sd_bus_add_object_vtable(bus, "/foo", "org.freedesktop.systemd.test", vtable, c) >= 0);
-        assert_se(sd_bus_add_object_vtable(bus, "/foo", "org.freedesktop.systemd.test2", vtable, c) >= 0);
-        assert_se(sd_bus_add_fallback_vtable(bus, "/value", "org.freedesktop.systemd.ValueTest", vtable2, NULL, UINT_TO_PTR(20)) >= 0);
-        assert_se(sd_bus_add_node_enumerator(bus, "/value", enumerator_callback, NULL) >= 0);
-        assert_se(sd_bus_add_object_manager(bus, "/value") >= 0);
+        assert_se(sd_bus_add_object_vtable(bus, NULL, "/foo", "org.freedesktop.systemd.test", vtable, c) >= 0);
+        assert_se(sd_bus_add_object_vtable(bus, NULL, "/foo", "org.freedesktop.systemd.test2", vtable, c) >= 0);
+        assert_se(sd_bus_add_fallback_vtable(bus, NULL, "/value", "org.freedesktop.systemd.ValueTest", vtable2, NULL, UINT_TO_PTR(20)) >= 0);
+        assert_se(sd_bus_add_node_enumerator(bus, NULL, "/value", enumerator_callback, NULL) >= 0);
+        assert_se(sd_bus_add_object_manager(bus, NULL, "/value") >= 0);
 
         assert_se(sd_bus_start(bus) >= 0);
 
index de6e3b2f84d5461102c430ead02d9979d40b2739..e3061c8d5ea46ea6187c790f519f4ce6d2bd619b 100644 (file)
@@ -1088,7 +1088,7 @@ static int connect_bus(Context *c, sd_event *event, sd_bus **_bus) {
                 return r;
         }
 
-        r = sd_bus_add_object_vtable(bus, "/org/freedesktop/locale1", "org.freedesktop.locale1", locale_vtable, c);
+        r = sd_bus_add_object_vtable(bus, NULL, "/org/freedesktop/locale1", "org.freedesktop.locale1", locale_vtable, c);
         if (r < 0) {
                 log_error("Failed to register object: %s", strerror(-r));
                 return r;
index 82323d6b8770e796f796e8ec4c384f388dac2c6e..1a2f09c615d97ec016e154d49f3c25d1ab45633c 100644 (file)
@@ -329,7 +329,7 @@ int seat_object_find(sd_bus *bus, const char *path, const char *interface, void
                 Session *session;
                 pid_t pid;
 
-                message = sd_bus_get_current(bus);
+                message = sd_bus_get_current_message(bus);
                 if (!message)
                         return 0;
 
index ffdc5582dca356f84f7ba1664af1b2f42d5201a2..7d81500426dc0e7bbc5fed8c153a2f08b6bab719 100644 (file)
@@ -493,7 +493,7 @@ int session_object_find(sd_bus *bus, const char *path, const char *interface, vo
                 sd_bus_message *message;
                 pid_t pid;
 
-                message = sd_bus_get_current(bus);
+                message = sd_bus_get_current_message(bus);
                 if (!message)
                         return 0;
 
index b5d27e74dea8b588e8d7643aba00098f51bd2e93..4f1a079ecd5cfaf1ad06599efcc3b3c32541efd5 100644 (file)
@@ -250,7 +250,7 @@ int user_object_find(sd_bus *bus, const char *path, const char *interface, void
                 sd_bus_message *message;
                 pid_t pid;
 
-                message = sd_bus_get_current(bus);
+                message = sd_bus_get_current_message(bus);
                 if (!message)
                         return 0;
 
index 86ce7df5d63ec28d1f3390850371d53afd7a754c..686506cc6511543275cb48802d080e757dfeb3cc 100644 (file)
@@ -586,49 +586,50 @@ static int manager_connect_bus(Manager *m) {
                 return r;
         }
 
-        r = sd_bus_add_object_vtable(m->bus, "/org/freedesktop/login1", "org.freedesktop.login1.Manager", manager_vtable, m);
+        r = sd_bus_add_object_vtable(m->bus, NULL, "/org/freedesktop/login1", "org.freedesktop.login1.Manager", manager_vtable, m);
         if (r < 0) {
                 log_error("Failed to add manager object vtable: %s", strerror(-r));
                 return r;
         }
 
-        r = sd_bus_add_fallback_vtable(m->bus, "/org/freedesktop/login1/seat", "org.freedesktop.login1.Seat", seat_vtable, seat_object_find, m);
+        r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/login1/seat", "org.freedesktop.login1.Seat", seat_vtable, seat_object_find, m);
         if (r < 0) {
                 log_error("Failed to add seat object vtable: %s", strerror(-r));
                 return r;
         }
 
-        r = sd_bus_add_node_enumerator(m->bus, "/org/freedesktop/login1/seat", seat_node_enumerator, m);
+        r = sd_bus_add_node_enumerator(m->bus, NULL, "/org/freedesktop/login1/seat", seat_node_enumerator, m);
         if (r < 0) {
                 log_error("Failed to add seat enumerator: %s", strerror(-r));
                 return r;
         }
 
-        r = sd_bus_add_fallback_vtable(m->bus, "/org/freedesktop/login1/session", "org.freedesktop.login1.Session", session_vtable, session_object_find, m);
+        r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/login1/session", "org.freedesktop.login1.Session", session_vtable, session_object_find, m);
         if (r < 0) {
                 log_error("Failed to add session object vtable: %s", strerror(-r));
                 return r;
         }
 
-        r = sd_bus_add_node_enumerator(m->bus, "/org/freedesktop/login1/session", session_node_enumerator, m);
+        r = sd_bus_add_node_enumerator(m->bus, NULL, "/org/freedesktop/login1/session", session_node_enumerator, m);
         if (r < 0) {
                 log_error("Failed to add session enumerator: %s", strerror(-r));
                 return r;
         }
 
-        r = sd_bus_add_fallback_vtable(m->bus, "/org/freedesktop/login1/user", "org.freedesktop.login1.User", user_vtable, user_object_find, m);
+        r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/login1/user", "org.freedesktop.login1.User", user_vtable, user_object_find, m);
         if (r < 0) {
                 log_error("Failed to add user object vtable: %s", strerror(-r));
                 return r;
         }
 
-        r = sd_bus_add_node_enumerator(m->bus, "/org/freedesktop/login1/user", user_node_enumerator, m);
+        r = sd_bus_add_node_enumerator(m->bus, NULL, "/org/freedesktop/login1/user", user_node_enumerator, m);
         if (r < 0) {
                 log_error("Failed to add user enumerator: %s", strerror(-r));
                 return r;
         }
 
         r = sd_bus_add_match(m->bus,
+                             NULL,
                              "type='signal',"
                              "sender='org.freedesktop.DBus',"
                              "interface='org.freedesktop.DBus',"
@@ -641,6 +642,7 @@ static int manager_connect_bus(Manager *m) {
         }
 
         r = sd_bus_add_match(m->bus,
+                             NULL,
                              "type='signal',"
                              "sender='org.freedesktop.systemd1',"
                              "interface='org.freedesktop.systemd1.Manager',"
@@ -653,6 +655,7 @@ static int manager_connect_bus(Manager *m) {
         }
 
         r = sd_bus_add_match(m->bus,
+                             NULL,
                              "type='signal',"
                              "sender='org.freedesktop.systemd1',"
                              "interface='org.freedesktop.systemd1.Manager',"
@@ -665,6 +668,7 @@ static int manager_connect_bus(Manager *m) {
         }
 
         r = sd_bus_add_match(m->bus,
+                             NULL,
                              "type='signal',"
                              "sender='org.freedesktop.systemd1',"
                              "interface='org.freedesktop.DBus.Properties',"
@@ -676,6 +680,7 @@ static int manager_connect_bus(Manager *m) {
         }
 
         r = sd_bus_add_match(m->bus,
+                             NULL,
                              "type='signal',"
                              "sender='org.freedesktop.systemd1',"
                              "interface='org.freedesktop.systemd1.Manager',"
index 920c9956aeeb953948c12be2cc7f5a350369620f..83ef82d2e02818c7da804b51e10b7c67eaf58fd7 100644 (file)
@@ -160,7 +160,7 @@ int machine_object_find(sd_bus *bus, const char *path, const char *interface, vo
                 sd_bus_message *message;
                 pid_t pid;
 
-                message = sd_bus_get_current(bus);
+                message = sd_bus_get_current_message(bus);
                 if (!message)
                         return 0;
 
index 20e6f7cd63e92c2ae192eefa2d4e5407b3478a0c..45768d2e97581b9a60b089bf0f7cf461f2b79952 100644 (file)
@@ -141,25 +141,26 @@ static int manager_connect_bus(Manager *m) {
                 return r;
         }
 
-        r = sd_bus_add_object_vtable(m->bus, "/org/freedesktop/machine1", "org.freedesktop.machine1.Manager", manager_vtable, m);
+        r = sd_bus_add_object_vtable(m->bus, NULL, "/org/freedesktop/machine1", "org.freedesktop.machine1.Manager", manager_vtable, m);
         if (r < 0) {
                 log_error("Failed to add manager object vtable: %s", strerror(-r));
                 return r;
         }
 
-        r = sd_bus_add_fallback_vtable(m->bus, "/org/freedesktop/machine1/machine", "org.freedesktop.machine1.Machine", machine_vtable, machine_object_find, m);
+        r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/machine1/machine", "org.freedesktop.machine1.Machine", machine_vtable, machine_object_find, m);
         if (r < 0) {
                 log_error("Failed to add machine object vtable: %s", strerror(-r));
                 return r;
         }
 
-        r = sd_bus_add_node_enumerator(m->bus, "/org/freedesktop/machine1/machine", machine_node_enumerator, m);
+        r = sd_bus_add_node_enumerator(m->bus, NULL, "/org/freedesktop/machine1/machine", machine_node_enumerator, m);
         if (r < 0) {
                 log_error("Failed to add machine enumerator: %s", strerror(-r));
                 return r;
         }
 
         r = sd_bus_add_match(m->bus,
+                             NULL,
                              "type='signal',"
                              "sender='org.freedesktop.systemd1',"
                              "interface='org.freedesktop.systemd1.Manager',"
@@ -173,6 +174,7 @@ static int manager_connect_bus(Manager *m) {
         }
 
         r = sd_bus_add_match(m->bus,
+                             NULL,
                              "type='signal',"
                              "sender='org.freedesktop.systemd1',"
                              "interface='org.freedesktop.systemd1.Manager',"
@@ -186,6 +188,7 @@ static int manager_connect_bus(Manager *m) {
         }
 
         r = sd_bus_add_match(m->bus,
+                             NULL,
                              "type='signal',"
                              "sender='org.freedesktop.systemd1',"
                              "interface='org.freedesktop.DBus.Properties',"
@@ -198,6 +201,7 @@ static int manager_connect_bus(Manager *m) {
         }
 
         r = sd_bus_add_match(m->bus,
+                             NULL,
                              "type='signal',"
                              "sender='org.freedesktop.systemd1',"
                              "interface='org.freedesktop.systemd1.Manager',"
index 77c505fc784f3f6d3276f9103e994b4de6012b5d..37a572dc0fd28006c7204a9329e8a284d5bd6276 100644 (file)
@@ -684,7 +684,7 @@ static int link_set_hostname(Link *link, const char *hostname) {
         if (r < 0)
                 return r;
 
-        r = sd_bus_call_async(link->manager->bus, m, set_hostname_handler, link, 0, NULL);
+        r = sd_bus_call_async(link->manager->bus, NULL, m, set_hostname_handler, link, 0);
         if (r < 0)
                 log_error_link(link, "Could not set transient hostname: %s", strerror(-r));
 
index e1e4640ae8f47ef6d3419360eb73ba5f157dae92..91d8032945fbe5899287a859f528f9d890a347ba 100644 (file)
@@ -2305,6 +2305,7 @@ static int enable_wait_for_jobs(sd_bus *bus) {
 
         r = sd_bus_add_match(
                         bus,
+                        NULL,
                         "type='signal',"
                         "sender='org.freedesktop.systemd1',"
                         "interface='org.freedesktop.systemd1.Manager',"
@@ -2364,13 +2365,14 @@ static int check_wait_response(WaitData *d) {
 }
 
 static int wait_for_jobs(sd_bus *bus, Set *s) {
+        _cleanup_bus_slot_unref_ sd_bus_slot *slot = NULL;
         WaitData d = { .set = s };
         int r = 0, q;
 
         assert(bus);
         assert(s);
 
-        q = sd_bus_add_filter(bus, wait_filter, &d);
+        q = sd_bus_add_filter(bus, &slot, wait_filter, &d);
         if (q < 0)
                 return log_oom();
 
@@ -2398,10 +2400,6 @@ static int wait_for_jobs(sd_bus *bus, Set *s) {
                 d.result = NULL;
         }
 
-        q = sd_bus_remove_filter(bus, wait_filter, &d);
-        if (q < 0 && r == 0)
-                r = q;
-
         return r;
 }
 
index c6787ca80946a04eac61be0ac8f3525adb92e342..79566d2109920989691420a4488c4faf172d0bbc 100644 (file)
@@ -37,6 +37,7 @@ _SD_BEGIN_DECLARATIONS;
 
 typedef struct sd_bus sd_bus;
 typedef struct sd_bus_message sd_bus_message;
+typedef struct sd_bus_slot sd_bus_slot;
 typedef struct sd_bus_creds sd_bus_creds;
 typedef struct sd_bus_track sd_bus_track;
 
@@ -138,8 +139,7 @@ int sd_bus_get_tid(sd_bus *bus, pid_t *tid);
 int sd_bus_send(sd_bus *bus, sd_bus_message *m, uint64_t *cookie);
 int sd_bus_send_to(sd_bus *bus, sd_bus_message *m, const char *destination, uint64_t *cookie);
 int sd_bus_call(sd_bus *bus, sd_bus_message *m, uint64_t usec, sd_bus_error *ret_error, sd_bus_message **reply);
-int sd_bus_call_async(sd_bus *bus, sd_bus_message *m, sd_bus_message_handler_t callback, void *userdata, uint64_t usec, uint64_t *cookie);
-int sd_bus_call_async_cancel(sd_bus *bus, uint64_t cookie);
+int sd_bus_call_async(sd_bus *bus, sd_bus_slot **slot, sd_bus_message *m, sd_bus_message_handler_t callback, void *userdata, uint64_t usec);
 
 int sd_bus_get_fd(sd_bus *bus);
 int sd_bus_get_events(sd_bus *bus);
@@ -148,35 +148,33 @@ int sd_bus_process(sd_bus *bus, sd_bus_message **r);
 int sd_bus_process_priority(sd_bus *bus, int64_t max_priority, sd_bus_message **r);
 int sd_bus_wait(sd_bus *bus, uint64_t timeout_usec);
 int sd_bus_flush(sd_bus *bus);
-sd_bus_message* sd_bus_get_current(sd_bus *bus);
+sd_bus_message* sd_bus_get_current_message(sd_bus *bus);
+sd_bus_slot* sd_bus_get_current_slot(sd_bus *bus);
 
 int sd_bus_attach_event(sd_bus *bus, sd_event *e, int priority);
 int sd_bus_detach_event(sd_bus *bus);
 sd_event *sd_bus_get_event(sd_bus *bus);
 
-int sd_bus_add_filter(sd_bus *bus, sd_bus_message_handler_t callback, void *userdata);
-int sd_bus_remove_filter(sd_bus *bus, sd_bus_message_handler_t callback, void *userdata);
+int sd_bus_add_filter(sd_bus *bus, sd_bus_slot **slot, sd_bus_message_handler_t callback, void *userdata);
+int sd_bus_add_match(sd_bus *bus, sd_bus_slot **slot, const char *match, sd_bus_message_handler_t callback, void *userdata);
+int sd_bus_add_object(sd_bus *bus, sd_bus_slot **slot, const char *path, sd_bus_message_handler_t callback, void *userdata);
+int sd_bus_add_fallback(sd_bus *bus, sd_bus_slot **slot, const char *prefix, sd_bus_message_handler_t callback, void *userdata);
+int sd_bus_add_object_vtable(sd_bus *bus, sd_bus_slot **slot, const char *path, const char *interface, const sd_bus_vtable *vtable, void *userdata);
+int sd_bus_add_fallback_vtable(sd_bus *bus, sd_bus_slot **slot, const char *prefix, const char *interface, const sd_bus_vtable *vtable, sd_bus_object_find_t find, void *userdata);
+int sd_bus_add_node_enumerator(sd_bus *bus, sd_bus_slot **slot, const char *path, sd_bus_node_enumerator_t callback, void *userdata);
+int sd_bus_add_object_manager(sd_bus *bus, sd_bus_slot **slot, const char *path);
 
-int sd_bus_add_match(sd_bus *bus, const char *match, sd_bus_message_handler_t callback, void *userdata);
-int sd_bus_remove_match(sd_bus *bus, const char *match, sd_bus_message_handler_t callback, void *userdata);
+/* Slot object */
 
-int sd_bus_add_object(sd_bus *bus, const char *path, sd_bus_message_handler_t callback, void *userdata);
-int sd_bus_remove_object(sd_bus *bus, const char *path, sd_bus_message_handler_t callback, void *userdata);
+sd_bus_slot* sd_bus_slot_ref(sd_bus_slot *slot);
+sd_bus_slot* sd_bus_slot_unref(sd_bus_slot *slot);
 
-int sd_bus_add_fallback(sd_bus *bus, const char *prefix, sd_bus_message_handler_t callback, void *userdata);
-int sd_bus_remove_fallback(sd_bus *bus, const char *prefix, sd_bus_message_handler_t callback, void *userdata);
+sd_bus* sd_bus_slot_get_bus(sd_bus_slot *slot);
 
-int sd_bus_add_object_vtable(sd_bus *bus, const char *path, const char *interface, const sd_bus_vtable *vtable, void *userdata);
-int sd_bus_remove_object_vtable(sd_bus *bus, const char *path, const char *interface, const sd_bus_vtable *vtable, void *userdata);
+void *sd_bus_slot_get_userdata(sd_bus_slot *slot);
+void *sd_bus_slot_set_userdata(sd_bus_slot *slot, void *userdata);
 
-int sd_bus_add_fallback_vtable(sd_bus *bus, const char *path, const char *interface, const sd_bus_vtable *vtable, sd_bus_object_find_t find, void *userdata);
-int sd_bus_remove_fallback_vtable(sd_bus *bus, const char *path, const char *interface, const sd_bus_vtable *vtable, sd_bus_object_find_t find, void *userdata);
-
-int sd_bus_add_node_enumerator(sd_bus *bus, const char *path, sd_bus_node_enumerator_t callback, void *userdata);
-int sd_bus_remove_node_enumerator(sd_bus *bus, const char *path, sd_bus_node_enumerator_t callback, void *userdata);
-
-int sd_bus_add_object_manager(sd_bus *bus, const char *path);
-int sd_bus_remove_object_manager(sd_bus *bus, const char *path);
+sd_bus_message* sd_bus_slot_get_current_message(sd_bus_slot *slot);
 
 /* Message object */
 
index 3895e321c2895b18571d6df1d63efd58346a87eb..1b09380094f06243f6d02a365a134bcfc4f23afb 100644 (file)
@@ -784,7 +784,7 @@ static int connect_bus(Context *c, sd_event *event, sd_bus **_bus) {
                 return r;
         }
 
-        r = sd_bus_add_object_vtable(bus, "/org/freedesktop/timedate1", "org.freedesktop.timedate1", timedate_vtable, c);
+        r = sd_bus_add_object_vtable(bus, NULL, "/org/freedesktop/timedate1", "org.freedesktop.timedate1", timedate_vtable, c);
         if (r < 0) {
                 log_error("Failed to register object: %s", strerror(-r));
                 return r;