diff options
author | Havoc Pennington <hp@redhat.com> | 2003-03-13 00:56:43 +0000 |
---|---|---|
committer | Havoc Pennington <hp@redhat.com> | 2003-03-13 00:56:43 +0000 |
commit | 29560adcc79a259a0be3511c056ee7453aa26c04 (patch) | |
tree | 57e72dd26b5876da48379e5ff910c63e66cb7001 /bus/services.c | |
parent | 799a3ff443f5357ae7857ebe989a7f92f7bd84df (diff) |
2003-03-12 Havoc Pennington <hp@redhat.com>
Mega-patch that gets the message bus daemon initially handling
out-of-memory. Work still needed. Also lots of random
moving stuff to DBusError instead of ResultCode.
* dbus/dbus-list.c (_dbus_list_length_is_one): new function
* dbus/dbus-connection.c
(dbus_connection_send_with_reply_and_block): use DBusError
* dbus/dbus-bus.c: adapt to API changes, make it use DBusError not
DBusResultCode
* dbus/dbus-connection.c (dbus_connection_send): drop the result
code here, as the only failure possible is OOM.
* bus/connection.c (bus_connection_disconnect):
rename bus_connection_disconnected as it's a notification only
* bus/driver.c (bus_driver_handle_acquire_service): don't free
"name" on get_args failure, should be done by get_args;
don't disconnect client for bad args, just return an error.
(bus_driver_handle_service_exists): ditto
* bus/services.c (bus_services_list): NULL-terminate returned array
* bus/driver.c (bus_driver_send_service_lost)
(bus_driver_send_service_acquired): send messages from driver to a
specific client to the client's unique name, not to the broadcast
service.
* dbus/dbus-message.c (decode_header_data): reject messages that
contain no name field
(_dbus_message_get_client_serial): rename to
dbus_message_get_serial and make public
(_dbus_message_set_serial): rename from set_client_serial
(_dbus_message_set_reply_serial): make public
(_dbus_message_get_reply_serial): make public
* bus/connection.c (bus_connection_foreach): allow stopping
iteration by returning FALSE from foreach function.
* dbus/dbus-connection.c (dbus_connection_send_preallocated)
(dbus_connection_free_preallocated_send)
(dbus_connection_preallocate_send): new API for sending a message
without possibility of malloc failure.
(dbus_connection_send_message): rename to just
dbus_connection_send (and same for whole function family)
* dbus/dbus-errors.c (dbus_error_free): make this reinit the error
* dbus/dbus-sysdeps.c (_dbus_exit): new function
* bus/activation.c: handle/return errors
* dbus/dbus-errors.h: add more DBUS_ERROR #define
* dbus/dbus-sysdeps.c (_dbus_directory_open) (_dbus_file_get_contents)
(_dbus_directory_get_next_file): use DBusError instead of DBusResultCode
(_dbus_result_from_errno): move to this file
Diffstat (limited to 'bus/services.c')
-rw-r--r-- | bus/services.c | 165 |
1 files changed, 126 insertions, 39 deletions
diff --git a/bus/services.c b/bus/services.c index 497978d0..22302af4 100644 --- a/bus/services.c +++ b/bus/services.c @@ -21,31 +21,29 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ -#include "driver.h" -#include "services.h" -#include "connection.h" #include <dbus/dbus-hash.h> #include <dbus/dbus-list.h> #include <dbus/dbus-mempool.h> +#include "driver.h" +#include "services.h" +#include "connection.h" +#include "utils.h" + struct BusService { char *name; DBusList *owners; - - unsigned int prohibit_replacement:1; + + unsigned int prohibit_replacement : 1; }; static DBusHashTable *service_hash = NULL; static DBusMemPool *service_pool = NULL; -BusService* -bus_service_lookup (const DBusString *service_name, - dbus_bool_t create_if_not_found) +static dbus_bool_t +init_hash (void) { - const char *c_name; - BusService *service; - if (service_hash == NULL) { service_hash = _dbus_hash_table_new (DBUS_HASH_STRING, @@ -65,93 +63,182 @@ bus_service_lookup (const DBusString *service_name, _dbus_mem_pool_free (service_pool); service_pool = NULL; } - return NULL; + return FALSE; } } + return TRUE; +} + +BusService* +bus_service_lookup (const DBusString *service_name) +{ + const char *c_name; + BusService *service; + + if (!init_hash ()) + return NULL; _dbus_string_get_const_data (service_name, &c_name); service = _dbus_hash_table_lookup_string (service_hash, c_name); - if (service != NULL) - return service; - if (!create_if_not_found) + return service; +} + +BusService* +bus_service_ensure (const DBusString *service_name, + DBusConnection *owner_if_created, + BusTransaction *transaction, + DBusError *error) +{ + const char *c_name; + BusService *service; + + _dbus_assert (owner_if_created != NULL); + _dbus_assert (transaction != NULL); + + if (!init_hash ()) return NULL; + _dbus_string_get_const_data (service_name, &c_name); + + service = _dbus_hash_table_lookup_string (service_hash, + c_name); + if (service != NULL) + return service; + service = _dbus_mem_pool_alloc (service_pool); if (service == NULL) - return NULL; + { + BUS_SET_OOM (error); + return NULL; + } service->name = _dbus_strdup (c_name); if (service->name == NULL) { _dbus_mem_pool_dealloc (service_pool, service); + BUS_SET_OOM (error); return NULL; } + if (!bus_driver_send_service_created (service->name, transaction, error)) + { + dbus_free (service->name); + _dbus_mem_pool_dealloc (service_pool, service); + return NULL; + } + + if (!bus_service_add_owner (service, owner_if_created, + transaction, error)) + { + dbus_free (service->name); + _dbus_mem_pool_dealloc (service_pool, service); + return NULL; + } + if (!_dbus_hash_table_insert_string (service_hash, service->name, service)) { + _dbus_list_clear (&service->owners); dbus_free (service->name); _dbus_mem_pool_dealloc (service_pool, service); + BUS_SET_OOM (error); return NULL; } - - bus_driver_send_service_created (service->name); return service; } dbus_bool_t bus_service_add_owner (BusService *service, - DBusConnection *owner) + DBusConnection *owner, + BusTransaction *transaction, + DBusError *error) { + /* Send service acquired message first, OOM will result + * in cancelling the transaction + */ + if (service->owners == NULL) + { + if (!bus_driver_send_service_acquired (owner, service->name, transaction, error)) + return FALSE; + } + if (!_dbus_list_append (&service->owners, owner)) - return FALSE; + { + BUS_SET_OOM (error); + return FALSE; + } if (!bus_connection_add_owned_service (owner, service)) { _dbus_list_remove_last (&service->owners, owner); + BUS_SET_OOM (error); return FALSE; } - - /* Send service acquired message */ - if (bus_service_get_primary_owner (service) == owner) - bus_driver_send_service_acquired (owner, service->name); return TRUE; } -void +dbus_bool_t bus_service_remove_owner (BusService *service, - DBusConnection *owner) + DBusConnection *owner, + BusTransaction *transaction, + DBusError *error) { + /* We send out notifications before we do any work we + * might have to undo if the notification-sending failed + */ + /* Send service lost message */ if (bus_service_get_primary_owner (service) == owner) - bus_driver_send_service_lost (owner, service->name); + { + if (!bus_driver_send_service_lost (owner, service->name, + transaction, error)) + return FALSE; + } + + if (_dbus_list_length_is_one (&service->owners)) + { + /* We are the only owner - send service deleted */ + if (!bus_driver_send_service_deleted (service->name, + transaction, error)) + return FALSE; + } + else + { + DBusList *link; + link = _dbus_list_get_first (&service->owners); + link = _dbus_list_get_next_link (&service->owners, link); + + if (link != NULL) + { + /* This will be our new owner */ + if (!bus_driver_send_service_acquired (link->data, + service->name, + transaction, + error)) + return FALSE; + } + } _dbus_list_remove_last (&service->owners, owner); bus_connection_remove_owned_service (owner, service); if (service->owners == NULL) { - /* Delete service */ - bus_driver_send_service_deleted (service->name); - + /* Delete service (already sent message that it was deleted above) */ _dbus_hash_table_remove_string (service_hash, service->name); dbus_free (service->name); _dbus_mem_pool_dealloc (service_pool, service); } - else - { - /* Send service acquired to the new owner */ - bus_driver_send_service_acquired (bus_service_get_primary_owner (service), - service->name); - } + + return TRUE; } DBusConnection* @@ -192,7 +279,7 @@ bus_services_list (int *array_len) DBusHashIter iter; len = _dbus_hash_table_get_n_entries (service_hash); - retval = dbus_new (char *, len); + retval = dbus_new (char *, len + 1); if (retval == NULL) return NULL; @@ -210,6 +297,8 @@ bus_services_list (int *array_len) i++; } + retval[i] = NULL; + if (array_len) *array_len = len; @@ -227,8 +316,6 @@ void bus_service_set_prohibit_replacement (BusService *service, dbus_bool_t prohibit_replacement) { - _dbus_assert (service->owners == NULL); - service->prohibit_replacement = prohibit_replacement != FALSE; } |