diff options
author | Luke Shumaker <lukeshu@lukeshu.com> | 2017-05-10 15:54:51 -0400 |
---|---|---|
committer | Luke Shumaker <lukeshu@lukeshu.com> | 2017-05-10 15:54:51 -0400 |
commit | 51bf8f984974c8d60e6576b623b4ea7e0e20a470 (patch) | |
tree | 3ff14638977c50bffd735a6628842a675fc1710b /src/libsystemd/sd-bus/bus-track.c | |
parent | 88cdc57b277ec240d4c5ddfbbfaddfed2b2408c1 (diff) |
./tools/notsd-move
Diffstat (limited to 'src/libsystemd/sd-bus/bus-track.c')
-rw-r--r-- | src/libsystemd/sd-bus/bus-track.c | 525 |
1 files changed, 0 insertions, 525 deletions
diff --git a/src/libsystemd/sd-bus/bus-track.c b/src/libsystemd/sd-bus/bus-track.c deleted file mode 100644 index 4acaf24793..0000000000 --- a/src/libsystemd/sd-bus/bus-track.c +++ /dev/null @@ -1,525 +0,0 @@ -/*** - 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 "alloc-util.h" -#include "bus-internal.h" -#include "bus-track.h" -#include "bus-util.h" - -struct track_item { - unsigned n_ref; - char *name; - sd_bus_slot *slot; -}; - -struct sd_bus_track { - unsigned n_ref; - unsigned n_adding; /* are we in the process of adding a new name? */ - sd_bus *bus; - sd_bus_track_handler_t handler; - void *userdata; - Hashmap *names; - LIST_FIELDS(sd_bus_track, queue); - Iterator iterator; - bool in_list:1; /* In bus->tracks? */ - bool in_queue:1; /* In bus->track_queue? */ - bool modified:1; - bool recursive:1; - - LIST_FIELDS(sd_bus_track, tracks); -}; - -#define MATCH_PREFIX \ - "type='signal'," \ - "sender='org.freedesktop.DBus'," \ - "path='/org/freedesktop/DBus'," \ - "interface='org.freedesktop.DBus'," \ - "member='NameOwnerChanged'," \ - "arg0='" - -#define MATCH_SUFFIX \ - "'" - -#define MATCH_FOR_NAME(name) \ - ({ \ - char *_x; \ - size_t _l = strlen(name); \ - _x = alloca(strlen(MATCH_PREFIX)+_l+strlen(MATCH_SUFFIX)+1); \ - strcpy(stpcpy(stpcpy(_x, MATCH_PREFIX), name), MATCH_SUFFIX); \ - _x; \ - }) - -static struct track_item* track_item_free(struct track_item *i) { - - if (!i) - return NULL; - - sd_bus_slot_unref(i->slot); - free(i->name); - return mfree(i); -} - -DEFINE_TRIVIAL_CLEANUP_FUNC(struct track_item*, track_item_free); - -static void bus_track_add_to_queue(sd_bus_track *track) { - assert(track); - - /* Adds the bus track object to the queue of objects we should dispatch next, subject to a number of - * conditions. */ - - /* Already in the queue? */ - if (track->in_queue) - return; - - /* if we are currently in the process of adding a new name, then let's not enqueue this just yet, let's wait - * until the addition is complete. */ - if (track->n_adding > 0) - return; - - /* still referenced? */ - if (hashmap_size(track->names) > 0) - return; - - /* Nothing to call? */ - if (!track->handler) - return; - - /* Already closed? */ - if (!track->in_list) - return; - - LIST_PREPEND(queue, track->bus->track_queue, track); - track->in_queue = true; -} - -static void bus_track_remove_from_queue(sd_bus_track *track) { - assert(track); - - if (!track->in_queue) - return; - - LIST_REMOVE(queue, track->bus->track_queue, track); - track->in_queue = false; -} - -static int bus_track_remove_name_fully(sd_bus_track *track, const char *name) { - struct track_item *i; - - assert(track); - assert(name); - - i = hashmap_remove(track->names, name); - if (!i) - return 0; - - track_item_free(i); - - bus_track_add_to_queue(track); - - track->modified = true; - return 1; -} - -_public_ int sd_bus_track_new( - sd_bus *bus, - sd_bus_track **track, - sd_bus_track_handler_t handler, - void *userdata) { - - sd_bus_track *t; - - assert_return(bus, -EINVAL); - assert_return(track, -EINVAL); - - if (!bus->bus_client) - return -EINVAL; - - t = new0(sd_bus_track, 1); - if (!t) - return -ENOMEM; - - t->n_ref = 1; - t->handler = handler; - t->userdata = userdata; - t->bus = sd_bus_ref(bus); - - LIST_PREPEND(tracks, bus->tracks, t); - t->in_list = true; - - bus_track_add_to_queue(t); - - *track = t; - return 0; -} - -_public_ sd_bus_track* sd_bus_track_ref(sd_bus_track *track) { - - if (!track) - return NULL; - - assert(track->n_ref > 0); - - track->n_ref++; - - return track; -} - -_public_ sd_bus_track* sd_bus_track_unref(sd_bus_track *track) { - struct track_item *i; - - if (!track) - return NULL; - - assert(track->n_ref > 0); - - if (track->n_ref > 1) { - track->n_ref--; - return NULL; - } - - while ((i = hashmap_steal_first(track->names))) - track_item_free(i); - - if (track->in_list) - LIST_REMOVE(tracks, track->bus->tracks, track); - - bus_track_remove_from_queue(track); - hashmap_free(track->names); - sd_bus_unref(track->bus); - return mfree(track); -} - -static int on_name_owner_changed(sd_bus_message *message, void *userdata, sd_bus_error *error) { - sd_bus_track *track = userdata; - const char *name, *old, *new; - int r; - - assert(message); - assert(track); - - r = sd_bus_message_read(message, "sss", &name, &old, &new); - if (r < 0) - return 0; - - bus_track_remove_name_fully(track, name); - return 0; -} - -_public_ int sd_bus_track_add_name(sd_bus_track *track, const char *name) { - _cleanup_(track_item_freep) struct track_item *n = NULL; - struct track_item *i; - const char *match; - int r; - - assert_return(track, -EINVAL); - assert_return(service_name_is_valid(name), -EINVAL); - - i = hashmap_get(track->names, name); - if (i) { - if (track->recursive) { - unsigned k = track->n_ref + 1; - - if (k < track->n_ref) /* Check for overflow */ - return -EOVERFLOW; - - track->n_ref = k; - } - - bus_track_remove_from_queue(track); - return 0; - } - - r = hashmap_ensure_allocated(&track->names, &string_hash_ops); - if (r < 0) - return r; - - n = new0(struct track_item, 1); - if (!n) - return -ENOMEM; - n->name = strdup(name); - if (!n->name) - return -ENOMEM; - - /* First, subscribe to this name */ - match = MATCH_FOR_NAME(name); - - bus_track_remove_from_queue(track); /* don't dispatch this while we work in it */ - - track->n_adding++; /* make sure we aren't dispatched while we synchronously add this match */ - r = sd_bus_add_match(track->bus, &n->slot, match, on_name_owner_changed, track); - track->n_adding--; - if (r < 0) { - bus_track_add_to_queue(track); - return r; - } - - r = hashmap_put(track->names, n->name, n); - if (r < 0) { - bus_track_add_to_queue(track); - return r; - } - - /* Second, check if it is currently existing, or maybe doesn't, or maybe disappeared already. */ - track->n_adding++; /* again, make sure this isn't dispatch while we are working in it */ - r = sd_bus_get_name_creds(track->bus, name, 0, NULL); - track->n_adding--; - if (r < 0) { - hashmap_remove(track->names, name); - bus_track_add_to_queue(track); - return r; - } - - n->n_ref = 1; - n = NULL; - - bus_track_remove_from_queue(track); - track->modified = true; - - return 1; -} - -_public_ int sd_bus_track_remove_name(sd_bus_track *track, const char *name) { - struct track_item *i; - - assert_return(name, -EINVAL); - - if (!track) /* Treat a NULL track object as an empty track object */ - return 0; - - if (!track->recursive) - return bus_track_remove_name_fully(track, name); - - i = hashmap_get(track->names, name); - if (!i) - return -EUNATCH; - if (i->n_ref <= 0) - return -EUNATCH; - - i->n_ref--; - - if (i->n_ref <= 0) - return bus_track_remove_name_fully(track, name); - - return 1; -} - -_public_ unsigned sd_bus_track_count(sd_bus_track *track) { - - if (!track) /* Let's consider a NULL object equivalent to an empty object */ - return 0; - - /* This signature really should have returned an int, so that we can propagate errors. But well, ... Also, note - * that this returns the number of names being watched, and multiple references to the same name are not - * counted. */ - - return hashmap_size(track->names); -} - -_public_ const char* sd_bus_track_contains(sd_bus_track *track, const char *name) { - assert_return(name, NULL); - - if (!track) /* Let's consider a NULL object equivalent to an empty object */ - return NULL; - - 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 = ITERATOR_FIRST; - - hashmap_iterate(track->names, &track->iterator, NULL, (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; - - hashmap_iterate(track->names, &track->iterator, NULL, (const void**) &n); - return n; -} - -_public_ int sd_bus_track_add_sender(sd_bus_track *track, sd_bus_message *m) { - const char *sender; - - assert_return(track, -EINVAL); - assert_return(m, -EINVAL); - - if (sd_bus_message_get_bus(m) != track->bus) - return -EINVAL; - - sender = sd_bus_message_get_sender(m); - if (!sender) - return -EINVAL; - - return sd_bus_track_add_name(track, sender); -} - -_public_ int sd_bus_track_remove_sender(sd_bus_track *track, sd_bus_message *m) { - const char *sender; - - assert_return(m, -EINVAL); - - if (!track) /* Treat a NULL track object as an empty track object */ - return 0; - - if (sd_bus_message_get_bus(m) != track->bus) - return -EINVAL; - - sender = sd_bus_message_get_sender(m); - if (!sender) - return -EINVAL; - - return sd_bus_track_remove_name(track, sender); -} - -_public_ sd_bus* sd_bus_track_get_bus(sd_bus_track *track) { - assert_return(track, NULL); - - return track->bus; -} - -void bus_track_dispatch(sd_bus_track *track) { - int r; - - assert(track); - assert(track->handler); - - bus_track_remove_from_queue(track); - - sd_bus_track_ref(track); - - r = track->handler(track, track->userdata); - if (r < 0) - log_debug_errno(r, "Failed to process track handler: %m"); - else if (r == 0) - bus_track_add_to_queue(track); - - sd_bus_track_unref(track); -} - -void bus_track_close(sd_bus_track *track) { - struct track_item *i; - - assert(track); - - /* Called whenever our bus connected is closed. If so, and our track object is non-empty, dispatch it - * immediately, as we are closing now, but first flush out all names. */ - - if (!track->in_list) - return; /* We already closed this one, don't close it again. */ - - /* Remember that this one is closed now */ - LIST_REMOVE(tracks, track->bus->tracks, track); - track->in_list = false; - - /* If there's no name in this one anyway, we don't have to dispatch */ - if (hashmap_isempty(track->names)) - return; - - /* Let's flush out all names */ - while ((i = hashmap_steal_first(track->names))) - track_item_free(i); - - /* Invoke handler */ - if (track->handler) - bus_track_dispatch(track); -} - -_public_ void *sd_bus_track_get_userdata(sd_bus_track *track) { - assert_return(track, NULL); - - return track->userdata; -} - -_public_ void *sd_bus_track_set_userdata(sd_bus_track *track, void *userdata) { - void *ret; - - assert_return(track, NULL); - - ret = track->userdata; - track->userdata = userdata; - - return ret; -} - -_public_ int sd_bus_track_set_recursive(sd_bus_track *track, int b) { - assert_return(track, -EINVAL); - - if (track->recursive == !!b) - return 0; - - if (!hashmap_isempty(track->names)) - return -EBUSY; - - track->recursive = b; - return 0; -} - -_public_ int sd_bus_track_get_recursive(sd_bus_track *track) { - assert_return(track, -EINVAL); - - return track->recursive; -} - -_public_ int sd_bus_track_count_sender(sd_bus_track *track, sd_bus_message *m) { - const char *sender; - - assert_return(m, -EINVAL); - - if (!track) /* Let's consider a NULL object equivalent to an empty object */ - return 0; - - if (sd_bus_message_get_bus(m) != track->bus) - return -EINVAL; - - sender = sd_bus_message_get_sender(m); - if (!sender) - return -EINVAL; - - return sd_bus_track_count_name(track, sender); -} - -_public_ int sd_bus_track_count_name(sd_bus_track *track, const char *name) { - struct track_item *i; - - assert_return(service_name_is_valid(name), -EINVAL); - - if (!track) /* Let's consider a NULL object equivalent to an empty object */ - return 0; - - i = hashmap_get(track->names, name); - if (!i) - return 0; - - return i->n_ref; -} |