1 /* -*- mode: C; c-file-style: "gnu" -*- */
2 /* services.c Service management
4 * Copyright (C) 2003 Red Hat, Inc.
5 * Copyright (C) 2003 CodeFactory AB
7 * Licensed under the Academic Free License version 1.2
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 #include <dbus/dbus-hash.h>
25 #include <dbus/dbus-list.h>
26 #include <dbus/dbus-mempool.h>
30 #include "connection.h"
32 #include "activation.h"
36 BusRegistry *registry;
40 unsigned int prohibit_replacement : 1;
49 DBusHashTable *service_hash;
50 DBusMemPool *service_pool;
54 bus_registry_new (BusContext *context)
56 BusRegistry *registry;
58 registry = dbus_new0 (BusRegistry, 1);
62 registry->refcount = 1;
63 registry->context = context;
65 registry->service_hash = _dbus_hash_table_new (DBUS_HASH_STRING,
67 if (registry->service_hash == NULL)
70 registry->service_pool = _dbus_mem_pool_new (sizeof (BusService),
72 if (registry->service_pool == NULL)
78 bus_registry_unref (registry);
83 bus_registry_ref (BusRegistry *registry)
85 _dbus_assert (registry->refcount > 0);
86 registry->refcount += 1;
90 bus_registry_unref (BusRegistry *registry)
92 _dbus_assert (registry->refcount > 0);
93 registry->refcount -= 1;
95 if (registry->refcount == 0)
97 if (registry->service_hash)
98 _dbus_hash_table_unref (registry->service_hash);
99 if (registry->service_pool)
100 _dbus_mem_pool_free (registry->service_pool);
102 dbus_free (registry);
107 bus_registry_lookup (BusRegistry *registry,
108 const DBusString *service_name)
113 _dbus_string_get_const_data (service_name, &c_name);
115 service = _dbus_hash_table_lookup_string (registry->service_hash,
122 bus_registry_ensure (BusRegistry *registry,
123 const DBusString *service_name,
124 DBusConnection *owner_if_created,
125 BusTransaction *transaction,
131 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
133 _dbus_assert (owner_if_created != NULL);
134 _dbus_assert (transaction != NULL);
136 _dbus_string_get_const_data (service_name, &c_name);
138 service = _dbus_hash_table_lookup_string (registry->service_hash,
143 service = _dbus_mem_pool_alloc (registry->service_pool);
150 service->registry = registry;
152 service->name = _dbus_strdup (c_name);
153 if (service->name == NULL)
155 _dbus_mem_pool_dealloc (registry->service_pool, service);
160 if (!bus_driver_send_service_created (service->name, transaction, error))
162 dbus_free (service->name);
163 _dbus_mem_pool_dealloc (registry->service_pool, service);
167 if (!bus_activation_service_created (bus_context_get_activation (registry->context),
168 service->name, error))
170 dbus_free (service->name);
171 _dbus_mem_pool_dealloc (registry->service_pool, service);
175 if (!bus_service_add_owner (service, owner_if_created,
178 dbus_free (service->name);
179 _dbus_mem_pool_dealloc (registry->service_pool, service);
183 if (!_dbus_hash_table_insert_string (registry->service_hash,
187 bus_connection_remove_owned_service (owner_if_created,
189 _dbus_list_clear (&service->owners);
190 dbus_free (service->name);
191 _dbus_mem_pool_dealloc (registry->service_pool, service);
200 bus_registry_foreach (BusRegistry *registry,
201 BusServiceForeachFunction function,
206 _dbus_hash_iter_init (registry->service_hash, &iter);
207 while (_dbus_hash_iter_next (&iter))
209 BusService *service = _dbus_hash_iter_get_value (&iter);
211 (* function) (service, data);
216 bus_registry_list_services (BusRegistry *registry,
224 len = _dbus_hash_table_get_n_entries (registry->service_hash);
225 retval = dbus_new (char *, len + 1);
230 _dbus_hash_iter_init (registry->service_hash, &iter);
232 while (_dbus_hash_iter_next (&iter))
234 BusService *service = _dbus_hash_iter_get_value (&iter);
236 retval[i] = _dbus_strdup (service->name);
237 if (retval[i] == NULL)
252 for (j = 0; j < i; j++)
253 dbus_free (retval[i]);
260 bus_service_add_owner (BusService *service,
261 DBusConnection *owner,
262 BusTransaction *transaction,
265 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
267 /* Send service acquired message first, OOM will result
268 * in cancelling the transaction
270 if (service->owners == NULL)
272 if (!bus_driver_send_service_acquired (owner, service->name, transaction, error))
276 if (!_dbus_list_append (&service->owners,
283 if (!bus_connection_add_owned_service (owner, service))
285 _dbus_list_remove_last (&service->owners, owner);
294 bus_service_remove_owner (BusService *service,
295 DBusConnection *owner,
296 BusTransaction *transaction,
299 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
301 /* We send out notifications before we do any work we
302 * might have to undo if the notification-sending failed
305 /* Send service lost message */
306 if (bus_service_get_primary_owner (service) == owner)
308 if (!bus_driver_send_service_lost (owner, service->name,
313 if (service->owners == NULL)
315 _dbus_assert_not_reached ("Tried to remove owner of a service that has no owners");
317 else if (_dbus_list_length_is_one (&service->owners))
319 /* We are the only owner - send service deleted */
320 if (!bus_driver_send_service_deleted (service->name,
327 link = _dbus_list_get_first (&service->owners);
328 _dbus_assert (link != NULL);
329 link = _dbus_list_get_next_link (&service->owners, link);
333 /* This will be our new owner */
334 if (!bus_driver_send_service_acquired (link->data,
342 _dbus_list_remove_last (&service->owners, owner);
343 bus_connection_remove_owned_service (owner, service);
345 if (service->owners == NULL)
347 /* Delete service (already sent message that it was deleted above) */
348 _dbus_hash_table_remove_string (service->registry->service_hash,
351 dbus_free (service->name);
352 _dbus_mem_pool_dealloc (service->registry->service_pool, service);
359 bus_service_get_primary_owner (BusService *service)
361 return _dbus_list_get_first (&service->owners);
365 bus_service_get_name (BusService *service)
367 return service->name;
371 bus_service_set_prohibit_replacement (BusService *service,
372 dbus_bool_t prohibit_replacement)
374 service->prohibit_replacement = prohibit_replacement != FALSE;
378 bus_service_get_prohibit_replacement (BusService *service)
380 return service->prohibit_replacement;
384 bus_service_has_owner (BusService *service,
385 DBusConnection *owner)
389 link = _dbus_list_get_first_link (&service->owners);
393 if (link->data == owner)
396 link = _dbus_list_get_next_link (&service->owners, link);