dbus/bus activation.c, 1.40, 1.41 bus.h, 1.26, 1.27 dispatch.c, 1.73,
1.74 driver.c, 1.75, 1.76 services.c, 1.32, 1.33 services.h,
1.14, 1.15 signals.c, 1.13, 1.14
John Palmieri
johnp at freedesktop.org
Tue Nov 22 12:37:02 PST 2005
Update of /cvs/dbus/dbus/bus
In directory gabe:/tmp/cvs-serv18986/bus
Modified Files:
activation.c bus.h dispatch.c driver.c services.c services.h
signals.c
Log Message:
* configure.in: Add test/name-test/Makefile to the generated
Makefile list
* dbus/dbus-shared.h (#define DBUS_NAME_FLAG_ALLOW_REPLACEMENT):
New flag which replaces DBUS_NAME_FLAG_PROHIBIT_REPLACEMENT
(#define DBUS_NAME_FLAG_DO_NOT_QUEUE): New flag for specifying
not to queue an ower if it can't be the primary owner
* bus/bus.h: Add new internal BusOwner struct
* bus/driver.c (bus_driver_handle_hello): Send flags (0 for default)
to bus_registry_ensure and don't set the prohibit_replacement flag
since they are now set per BusOwner and not per name.
(bus_driver_handle_list_queued_owners): bus method (ListQueuedOwners)
that returns the list of connections in a name's connection queue
* bus/services.c (struct BusService): remove prohibit_replacement field
(struct BusOwner): new struct for keeping track of queued connections
and their associated flags for the queue
(struct BusRegistry): add a BusOwner memory pool
(bus_registry_new): initialize the BusOwner memory pool
(bus_registry_unref): free the BusOwner memory pool
(_bus_service_find_owner_link): new internal method for
searching the queue for a specific connection
(bus_owner_set_flags): new method for adding setting the flags on a
bus owner
(bus_owner_new): new method that creates a BusOwner object from the
pool and sets its flags
(bus_owner_ref, bus_owner_unref): ref counting for BusOwner objects
(bus_registry_ensure): Add the flags parameter
(bus_registry_acquire_service): Switch from using raw connections to
using the BusOwner struct
Add new state machine for dealing with the new set of flags
(bus_registry_set_service_context_table, struct OwnershipCancelData,
cancel_ownership, free_ownership_cancel_data,
add_cancel_ownership_to_transaction, struct OwnershipRestoreData,
restore_ownership, free_ownership_restore_data,
add_restore_ownership_to_transaction): Switch to using BusOwner
instead of raw connections
(bus_service_add_owner): Add flags parameter
Switch to using BusOwner instead of raw connections
Add state machine for dealing with the new set of flags
(bus_service_swap_owner): Swaps the first and second owners in the
queue. Used to make sure proper signals are sent when a service looses
or gains primary ownership. We never insert an owner at the top of the
queue. Instead we insert it in the second position and then swap.
(bus_service_remove_owner): Remove the owner from the queue sending
out the NameLost and NameOwnerChanged signals if the we were the
primary owner
(bus_service_get_primary_owners_connection): New method that extracts
the connection from the primary owner
(bus_service_get_primary_owner): Returns the BusOwner instead of the
connection
(bus_service_get_allow_replacement): Changed from the old
bus_service_get_prohibit_replacement method. Checks the flags of the
primary owner and returns if it can be replaced or not
(bus_service_set_prohibit_replacement): removed
(bus_service_has_owner): returns TRUE if and owner with
the specified connection exists in the queue
* dbus/dbus-bus.c (dbus_bus_connection_get_unique_name): New helper
method that only compiles if tests are enabled. Allows us to get the
unique name of a connection so we can check it against the queue when
doing regression tests
* bus/activation.c (bus_activation_send_pending_auto_activate),
bus/dispatch.c (bus_dispatch),
bus/driver.c (bus_driver_handle_get_service_owner,
bus_driver_handle_get_connection_unix_user,
bus_driver_handle_get_connection_unix_process_id,
bus_driver_handle_get_connection_selinux_security_context),
bus/signals.c (connection_is_primary_owner):
use bus_service_get_primary_owners_connection instead of
bus_service_get_primary_owner
* dbus/dbus-sysdeps.c (_dbus_connect_unix_socket,
_dbus_listen_unix_socket): Calculate the length of the socket
path and use that instead of using a fixed length which was
causing socket names to contain many trailing Nul bytes.
* dbus/dbus-glib-lowlevel.h, glib/dbus-gobject.c
(dbus_g_method_get_sender): New method for extracting the sender
from a DBusGMethodInvocation
(dbus_g_method_return_get_reply): changed name to
dbus_g_method_get_reply
(dbus_g_method_return_send_reply): changed name to
dbus_g_method_send reply
* doc/dbus-specification.xml: New docs that describe how the new
queueing system works and talks about the changes to the how
we specify socket names
* glib/examples/example-service.c,
glib/examples/example-signal-emitter.c,
glib/examples/statemachine/statemachine-server.c:
Changed the RequestName flags to the new system
* test/name-test/ (test-names.c, run-test.sh, Makefile.am): New
regression test suite for testing various states of the new
queueing system
Index: activation.c
===================================================================
RCS file: /cvs/dbus/dbus/bus/activation.c,v
retrieving revision 1.40
retrieving revision 1.41
diff -u -d -r1.40 -r1.41
--- activation.c 6 Sep 2005 22:38:54 -0000 1.40
+++ activation.c 22 Nov 2005 20:37:00 -0000 1.41
@@ -980,7 +980,7 @@
{
DBusConnection *addressed_recipient;
- addressed_recipient = bus_service_get_primary_owner (service);
+ addressed_recipient = bus_service_get_primary_owners_connection (service);
/* Check the security policy, which has the side-effect of adding an
* expected pending reply.
Index: bus.h
===================================================================
RCS file: /cvs/dbus/dbus/bus/bus.h,v
retrieving revision 1.26
retrieving revision 1.27
diff -u -d -r1.26 -r1.27
--- bus.h 12 Sep 2004 10:23:42 -0000 1.26
+++ bus.h 22 Nov 2005 20:37:00 -0000 1.27
@@ -40,6 +40,7 @@
typedef struct BusRegistry BusRegistry;
typedef struct BusSELinuxID BusSELinuxID;
typedef struct BusService BusService;
+typedef struct BusOwner BusOwner;
typedef struct BusTransaction BusTransaction;
typedef struct BusMatchmaker BusMatchmaker;
typedef struct BusMatchRule BusMatchRule;
Index: dispatch.c
===================================================================
RCS file: /cvs/dbus/dbus/bus/dispatch.c,v
retrieving revision 1.73
retrieving revision 1.74
diff -u -d -r1.73 -r1.74
--- dispatch.c 3 Oct 2005 19:55:56 -0000 1.73
+++ dispatch.c 22 Nov 2005 20:37:00 -0000 1.74
@@ -287,7 +287,7 @@
}
else
{
- addressed_recipient = bus_service_get_primary_owner (service);
+ addressed_recipient = bus_service_get_primary_owners_connection (service);
_dbus_assert (addressed_recipient != NULL);
if (!bus_context_check_security_policy (context, transaction,
Index: driver.c
===================================================================
RCS file: /cvs/dbus/dbus/bus/driver.c,v
retrieving revision 1.75
retrieving revision 1.76
diff -u -d -r1.75 -r1.76
--- driver.c 15 Nov 2005 17:19:19 -0000 1.75
+++ driver.c 22 Nov 2005 20:37:00 -0000 1.76
@@ -308,12 +308,10 @@
/* Create the service */
service = bus_registry_ensure (registry,
- &unique_name, connection, transaction, error);
+ &unique_name, connection, 0, transaction, error);
if (service == NULL)
goto out_0;
- bus_service_set_prohibit_replacement (service, TRUE);
-
_dbus_assert (bus_connection_is_active (connection));
retval = TRUE;
@@ -883,7 +881,7 @@
}
else
{
- base_name = bus_connection_get_name (bus_service_get_primary_owner (service));
+ base_name = bus_connection_get_name (bus_service_get_primary_owners_connection (service));
if (base_name == NULL)
{
/* FIXME - how is this error possible? */
@@ -924,6 +922,113 @@
}
static dbus_bool_t
+bus_driver_handle_list_queued_owners (DBusConnection *connection,
+ BusTransaction *transaction,
+ DBusMessage *message,
+ DBusError *error)
+{
+ const char *text;
+ DBusList *base_names;
+ DBusList *link;
+ DBusString str;
+ BusRegistry *registry;
+ BusService *service;
+ DBusMessage *reply;
+ DBusMessageIter iter, array_iter;
+ char *dbus_service_name = DBUS_SERVICE_DBUS;
+
+ _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+ registry = bus_connection_get_registry (connection);
+
+ base_names = NULL;
+ text = NULL;
+ reply = NULL;
+
+ if (! dbus_message_get_args (message, error,
+ DBUS_TYPE_STRING, &text,
+ DBUS_TYPE_INVALID))
+ goto failed;
+
+ _dbus_string_init_const (&str, text);
+ service = bus_registry_lookup (registry, &str);
+ if (service == NULL &&
+ _dbus_string_equal_c_str (&str, DBUS_SERVICE_DBUS))
+ {
+ /* ORG_FREEDESKTOP_DBUS owns itself */
+ if (! _dbus_list_append (&base_names, dbus_service_name))
+ goto oom;
+ }
+ else if (service == NULL)
+ {
+ dbus_set_error (error,
+ DBUS_ERROR_NAME_HAS_NO_OWNER,
+ "Could not get owners of name '%s': no such name", text);
+ goto failed;
+ }
+ else
+ {
+ if (!bus_service_list_queued_owners (service,
+ &base_names,
+ error))
+ goto failed;
+ }
+
+ _dbus_assert (base_names != NULL);
+
+ reply = dbus_message_new_method_return (message);
+ if (reply == NULL)
+ goto oom;
+
+ dbus_message_iter_init_append (reply, &iter);
+ if (!dbus_message_iter_open_container (&iter,
+ DBUS_TYPE_ARRAY,
+ DBUS_TYPE_STRING_AS_STRING,
+ &array_iter))
+ goto oom;
+
+ link = _dbus_list_get_first_link (&base_names);
+ while (link != NULL)
+ {
+ char *uname;
+
+ _dbus_assert (link->data != NULL);
+ uname = (char *)link->data;
+
+ if (!dbus_message_iter_append_basic (&array_iter,
+ DBUS_TYPE_STRING,
+ &uname))
+ goto oom;
+
+ link = _dbus_list_get_next_link (&base_names, link);
+ }
+
+ if (! dbus_message_iter_close_container (&iter, &array_iter))
+ goto oom;
+
+
+ if (! bus_transaction_send_from_driver (transaction, connection, reply))
+ goto oom;
+
+ dbus_message_unref (reply);
+
+ return TRUE;
+
+ oom:
+ BUS_SET_OOM (error);
+
+ failed:
+ _DBUS_ASSERT_ERROR_IS_SET (error);
+ if (reply)
+ dbus_message_unref (reply);
+
+ if (base_names)
+ _dbus_list_clear (&base_names);
+
+ return FALSE;
+}
+
+static dbus_bool_t
bus_driver_handle_get_connection_unix_user (DBusConnection *connection,
BusTransaction *transaction,
DBusMessage *message,
@@ -962,7 +1067,7 @@
goto failed;
}
- conn = bus_service_get_primary_owner (serv);
+ conn = bus_service_get_primary_owners_connection (serv);
reply = dbus_message_new_method_return (message);
if (reply == NULL)
@@ -1038,7 +1143,7 @@
goto failed;
}
- conn = bus_service_get_primary_owner (serv);
+ conn = bus_service_get_primary_owners_connection (serv);
reply = dbus_message_new_method_return (message);
if (reply == NULL)
@@ -1113,7 +1218,7 @@
goto failed;
}
- conn = bus_service_get_primary_owner (serv);
+ conn = bus_service_get_primary_owners_connection (serv);
reply = dbus_message_new_method_return (message);
if (reply == NULL)
@@ -1235,6 +1340,10 @@
DBUS_TYPE_STRING_AS_STRING,
DBUS_TYPE_STRING_AS_STRING,
bus_driver_handle_get_service_owner },
+ { "ListQueuedOwners",
+ DBUS_TYPE_STRING_AS_STRING,
+ DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_STRING_AS_STRING,
+ bus_driver_handle_list_queued_owners },
{ "GetConnectionUnixUser",
DBUS_TYPE_STRING_AS_STRING,
DBUS_TYPE_UINT32_AS_STRING,
Index: services.c
===================================================================
RCS file: /cvs/dbus/dbus/bus/services.c,v
retrieving revision 1.32
retrieving revision 1.33
diff -u -d -r1.32 -r1.33
--- services.c 15 Nov 2005 17:19:19 -0000 1.32
+++ services.c 22 Nov 2005 20:37:00 -0000 1.33
@@ -42,8 +42,17 @@
BusRegistry *registry;
char *name;
DBusList *owners;
-
- unsigned int prohibit_replacement : 1;
+};
+
+struct BusOwner
+{
+ int refcount;
+
+ BusService *service;
+ DBusConnection *conn;
+
+ unsigned int allow_replacement : 1;
+ unsigned int do_not_queue : 1;
};
struct BusRegistry
@@ -54,6 +63,7 @@
DBusHashTable *service_hash;
DBusMemPool *service_pool;
+ DBusMemPool *owner_pool;
DBusHashTable *service_sid_table;
};
@@ -77,9 +87,16 @@
registry->service_pool = _dbus_mem_pool_new (sizeof (BusService),
TRUE);
+
if (registry->service_pool == NULL)
goto failed;
+ registry->owner_pool = _dbus_mem_pool_new (sizeof (BusOwner),
+ TRUE);
+
+ if (registry->owner_pool == NULL)
+ goto failed;
+
registry->service_sid_table = NULL;
return registry;
@@ -110,6 +127,8 @@
_dbus_hash_table_unref (registry->service_hash);
if (registry->service_pool)
_dbus_mem_pool_free (registry->service_pool);
+ if (registry->owner_pool)
+ _dbus_mem_pool_free (registry->owner_pool);
if (registry->service_sid_table)
_dbus_hash_table_unref (registry->service_sid_table);
@@ -129,10 +148,98 @@
return service;
}
+static DBusList *
+_bus_service_find_owner_link (BusService *service,
+ DBusConnection *connection)
+{
+ DBusList *link;
+
+ link = _dbus_list_get_first_link (&service->owners);
+
+ while (link != NULL)
+ {
+ BusOwner *bus_owner;
+
+ bus_owner = (BusOwner *) link->data;
+ if (bus_owner->conn == connection)
+ break;
+
+ link = _dbus_list_get_next_link (&service->owners, link);
+ }
+
+ return link;
+}
+
+static void
+bus_owner_set_flags (BusOwner *owner,
+ dbus_uint32_t flags)
+{
+ owner->allow_replacement =
+ (flags & DBUS_NAME_FLAG_ALLOW_REPLACEMENT) != FALSE;
+
+ owner->do_not_queue =
+ (flags & DBUS_NAME_FLAG_DO_NOT_QUEUE) != FALSE;
+}
+
+static BusOwner *
+bus_owner_new (BusService *service,
+ DBusConnection *conn,
+ dbus_uint32_t flags)
+{
+ BusOwner *result;
+
+ result = _dbus_mem_pool_alloc (service->registry->owner_pool);
+ if (result != NULL)
+ {
+ result->refcount = 1;
+ /* don't ref the connection because we don't want
+ to block the connection from going away.
+ transactions take care of reffing the connection
+ but we need to use refcounting on the owner
+ so that the owner does not get freed before
+ we can deref the connection in the transaction
+ */
+ result->conn = conn;
+ result->service = service;
+
+ if (!bus_connection_add_owned_service (conn, service))
+ {
+ _dbus_mem_pool_dealloc (service->registry->owner_pool, result);
+ return NULL;
+ }
+
+ bus_owner_set_flags (result, flags);
+ }
+ return result;
+}
+
+static BusOwner *
+bus_owner_ref (BusOwner *owner)
+{
+ _dbus_assert (owner->refcount > 0);
+ owner->refcount += 1;
+
+ return owner;
+}
+
+static void
+bus_owner_unref (BusOwner *owner)
+{
+ _dbus_assert (owner->refcount > 0);
+ owner->refcount -= 1;
+
+ if (owner->refcount == 0)
+ {
+ bus_connection_remove_owned_service (owner->conn, owner->service);
+ _dbus_mem_pool_dealloc (owner->service->registry->owner_pool, owner);
+ }
+}
+
BusService*
bus_registry_ensure (BusRegistry *registry,
const DBusString *service_name,
- DBusConnection *owner_if_created,
+ DBusConnection *owner_connection_if_created,
+ dbus_uint32_t flags,
BusTransaction *transaction,
DBusError *error)
{
@@ -140,7 +247,7 @@
_DBUS_ASSERT_ERROR_IS_CLEAR (error);
- _dbus_assert (owner_if_created != NULL);
+ _dbus_assert (owner_connection_if_created != NULL);
_dbus_assert (transaction != NULL);
service = _dbus_hash_table_lookup_string (registry->service_hash,
@@ -172,7 +279,7 @@
if (!bus_driver_send_service_owner_changed (service->name,
NULL,
- bus_connection_get_name (owner_if_created),
+ bus_connection_get_name (owner_connection_if_created),
transaction, error))
{
bus_service_unref (service);
@@ -186,8 +293,8 @@
return NULL;
}
- if (!bus_service_add_owner (service, owner_if_created,
- transaction, error))
+ if (!bus_service_add_owner (service, owner_connection_if_created, flags,
+ transaction, error))
{
bus_service_unref (service);
return NULL;
@@ -275,13 +382,14 @@
DBusError *error)
{
dbus_bool_t retval;
- DBusConnection *old_owner;
- DBusConnection *current_owner;
+ DBusConnection *old_owner_conn;
+ DBusConnection *current_owner_conn;
BusClientPolicy *policy;
BusService *service;
BusActivation *activation;
BusSELinuxID *sid;
-
+ BusOwner *primary_owner;
+
retval = FALSE;
if (!_dbus_validate_bus_name (service_name, 0,
@@ -366,37 +474,70 @@
service = bus_registry_lookup (registry, service_name);
if (service != NULL)
- old_owner = bus_service_get_primary_owner (service);
+ {
+ primary_owner = bus_service_get_primary_owner (service);
+ if (primary_owner != NULL)
+ old_owner_conn = primary_owner->conn;
+ else
+ old_owner_conn = NULL;
+ }
else
- old_owner = NULL;
+ old_owner_conn = NULL;
if (service == NULL)
{
service = bus_registry_ensure (registry,
- service_name, connection, transaction, error);
+ service_name, connection, flags,
+ transaction, error);
if (service == NULL)
goto out;
}
- current_owner = bus_service_get_primary_owner (service);
-
- if (old_owner == NULL)
+ primary_owner = bus_service_get_primary_owner (service);
+ if (primary_owner == NULL)
+ goto out;
+
+ current_owner_conn = primary_owner->conn;
+
+ if (old_owner_conn == NULL)
{
- _dbus_assert (current_owner == connection);
+ _dbus_assert (current_owner_conn == connection);
- bus_service_set_prohibit_replacement (service,
- (flags & DBUS_NAME_FLAG_PROHIBIT_REPLACEMENT));
-
*result = DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER;
}
- else if (old_owner == connection)
- *result = DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER;
- else if (!((flags & DBUS_NAME_FLAG_REPLACE_EXISTING)))
- *result = DBUS_REQUEST_NAME_REPLY_EXISTS;
- else if (bus_service_get_prohibit_replacement (service))
+ else if (old_owner_conn == connection)
+ {
+ bus_owner_set_flags (primary_owner, flags);
+ *result = DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER;
+ }
+ else if (((flags & DBUS_NAME_FLAG_DO_NOT_QUEUE) &&
+ !(bus_service_get_allow_replacement (service))) ||
+ ((flags & DBUS_NAME_FLAG_DO_NOT_QUEUE) &&
+ !(flags & DBUS_NAME_FLAG_REPLACE_EXISTING)))
+ {
+ DBusList *link;
+ BusOwner *temp_owner;
+ /* Since we can't be queued if we are already in the queue
+ remove us */
+
+ link = _bus_service_find_owner_link (service, connection);
+ if (link != NULL)
+ {
+ _dbus_list_unlink (&service->owners, link);
+ temp_owner = (BusOwner *)link->data;
+ bus_owner_unref (temp_owner);
+ _dbus_list_free_link (link);
+ }
+
+ *result = DBUS_REQUEST_NAME_REPLY_EXISTS;
+ }
+ else if (!(flags & DBUS_NAME_FLAG_DO_NOT_QUEUE) &&
+ (!(flags & DBUS_NAME_FLAG_REPLACE_EXISTING) ||
+ !(bus_service_get_allow_replacement (service))))
{
/* Queue the connection */
- if (!bus_service_add_owner (service, connection,
+ if (!bus_service_add_owner (service, connection,
+ flags,
transaction, error))
goto out;
@@ -412,14 +553,25 @@
*/
if (!bus_service_add_owner (service, connection,
+ flags,
transaction, error))
goto out;
- if (!bus_service_remove_owner (service, old_owner,
- transaction, error))
- goto out;
-
- _dbus_assert (connection == bus_service_get_primary_owner (service));
+ if (primary_owner->do_not_queue)
+ {
+ if (!bus_service_remove_owner (service, old_owner_conn,
+ transaction, error))
+ goto out;
+ }
+ else
+ {
+ if (!bus_service_swap_owner (service, old_owner_conn,
+ transaction, error))
+ goto out;
+ }
+
+
+ _dbus_assert (connection == bus_service_get_primary_owner (service)->conn);
*result = DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER;
}
@@ -528,10 +680,10 @@
static void
bus_service_unlink_owner (BusService *service,
- DBusConnection *owner)
+ BusOwner *owner)
{
_dbus_list_remove_last (&service->owners, owner);
- bus_connection_remove_owned_service (owner, service);
+ bus_owner_unref (owner);
}
static void
@@ -570,7 +722,7 @@
*/
typedef struct
{
- DBusConnection *connection; /**< the connection */
+ BusOwner *owner; /**< the owner */
BusService *service; /**< service to cancel ownership of */
} OwnershipCancelData;
@@ -583,7 +735,7 @@
* changes, since we're reverting something that was
* cancelled (effectively never really happened)
*/
- bus_service_unlink_owner (d->service, d->connection);
+ bus_service_unlink_owner (d->service, d->owner);
if (d->service->owners == NULL)
bus_service_unlink (d->service);
@@ -594,7 +746,8 @@
{
OwnershipCancelData *d = data;
- dbus_connection_unref (d->connection);
+ dbus_connection_unref (d->owner->conn);
+ bus_owner_unref (d->owner);
bus_service_unref (d->service);
dbus_free (d);
@@ -603,7 +756,7 @@
static dbus_bool_t
add_cancel_ownership_to_transaction (BusTransaction *transaction,
BusService *service,
- DBusConnection *connection)
+ BusOwner *owner)
{
OwnershipCancelData *d;
@@ -612,7 +765,7 @@
return FALSE;
d->service = service;
- d->connection = connection;
+ d->owner = owner;
if (!bus_transaction_add_cancel_hook (transaction, cancel_ownership, d,
free_ownership_cancel_data))
@@ -622,18 +775,23 @@
}
bus_service_ref (d->service);
- dbus_connection_ref (d->connection);
-
+ bus_owner_ref (owner);
+ dbus_connection_ref (d->owner->conn);
+
return TRUE;
}
/* this function is self-cancelling if you cancel the transaction */
dbus_bool_t
bus_service_add_owner (BusService *service,
- DBusConnection *owner,
+ DBusConnection *connection,
+ dbus_uint32_t flags,
BusTransaction *transaction,
DBusError *error)
{
+ BusOwner *bus_owner;
+ DBusList *bus_owner_link;
+
_DBUS_ASSERT_ERROR_IS_CLEAR (error);
/* Send service acquired message first, OOM will result
@@ -641,42 +799,83 @@
*/
if (service->owners == NULL)
{
- if (!bus_driver_send_service_acquired (owner, service->name, transaction, error))
+ if (!bus_driver_send_service_acquired (connection, service->name, transaction, error))
return FALSE;
}
- if (!_dbus_list_append (&service->owners,
- owner))
+ bus_owner_link = _bus_service_find_owner_link (service, connection);
+
+ if (bus_owner_link == NULL)
{
- BUS_SET_OOM (error);
- return FALSE;
- }
+ bus_owner = bus_owner_new (service, connection, flags);
+ if (bus_owner == NULL)
+ {
+ BUS_SET_OOM (error);
+ return FALSE;
+ }
- if (!bus_connection_add_owned_service (owner, service))
+ bus_owner_set_flags (bus_owner, flags);
+ if (!(flags & DBUS_NAME_FLAG_REPLACE_EXISTING) || service->owners == NULL)
+ {
+ if (!_dbus_list_append (&service->owners,
+ bus_owner))
+ {
+ bus_owner_unref (bus_owner);
+ BUS_SET_OOM (error);
+ return FALSE;
+ }
+ }
+ else
+ {
+ if (!_dbus_list_insert_after (&service->owners,
+ _dbus_list_get_first_link (&service->owners),
+ bus_owner))
+ {
+ bus_owner_unref (bus_owner);
+ BUS_SET_OOM (error);
+ return FALSE;
+ }
+ }
+ }
+ else
{
- _dbus_list_remove_last (&service->owners, owner);
- BUS_SET_OOM (error);
- return FALSE;
+ /* Update the link since we are already in the queue
+ * No need for operations that can produce OOM
+ */
+
+ bus_owner = (BusOwner *) bus_owner_link->data;
+ if (flags & DBUS_NAME_FLAG_REPLACE_EXISTING)
+ {
+ DBusList *link;
+ _dbus_list_unlink (&service->owners, bus_owner_link);
+ link = _dbus_list_get_first_link (&service->owners);
+ _dbus_assert (link != NULL);
+
+ _dbus_list_insert_after_link (&service->owners, link, bus_owner_link);
+ }
+
+ bus_owner_set_flags (bus_owner, flags);
+ return TRUE;
}
if (!add_cancel_ownership_to_transaction (transaction,
service,
- owner))
+ bus_owner))
{
- bus_service_unlink_owner (service, owner);
+ bus_service_unlink_owner (service, bus_owner);
BUS_SET_OOM (error);
return FALSE;
}
-
+
return TRUE;
}
typedef struct
{
- DBusConnection *connection;
+ BusOwner *owner;
BusService *service;
- DBusConnection *before_connection; /* restore to position before this connection in owners list */
- DBusList *connection_link;
+ BusOwner *before_owner; /* restore to position before this connection in owners list */
+ DBusList *owner_link;
DBusList *service_link;
DBusPreallocatedHash *hash_entry;
} OwnershipRestoreData;
@@ -688,7 +887,7 @@
DBusList *link;
_dbus_assert (d->service_link != NULL);
- _dbus_assert (d->connection_link != NULL);
+ _dbus_assert (d->owner_link != NULL);
if (d->service->owners == NULL)
{
@@ -707,13 +906,13 @@
link = _dbus_list_get_first_link (&d->service->owners);
while (link != NULL)
{
- if (link->data == d->before_connection)
+ if (link->data == d->before_owner)
break;
link = _dbus_list_get_next_link (&d->service->owners, link);
}
- _dbus_list_insert_before_link (&d->service->owners, link, d->connection_link);
+ _dbus_list_insert_before_link (&d->service->owners, link, d->owner_link);
/* Note that removing then restoring this changes the order in which
* ServiceDeleted messages are sent on destruction of the
@@ -721,11 +920,11 @@
* that the base service is destroyed last, and we never even
* tentatively remove the base service.
*/
- bus_connection_add_owned_service_link (d->connection, d->service_link);
+ bus_connection_add_owned_service_link (d->owner->conn, d->service_link);
d->hash_entry = NULL;
d->service_link = NULL;
- d->connection_link = NULL;
+ d->owner_link = NULL;
}
static void
@@ -735,13 +934,14 @@
if (d->service_link)
_dbus_list_free_link (d->service_link);
- if (d->connection_link)
- _dbus_list_free_link (d->connection_link);
+ if (d->owner_link)
+ _dbus_list_free_link (d->owner_link);
if (d->hash_entry)
_dbus_hash_table_free_preallocated_entry (d->service->registry->service_hash,
d->hash_entry);
- dbus_connection_unref (d->connection);
+ dbus_connection_unref (d->owner->conn);
+ bus_owner_unref (d->owner);
bus_service_unref (d->service);
dbus_free (d);
@@ -750,7 +950,7 @@
static dbus_bool_t
add_restore_ownership_to_transaction (BusTransaction *transaction,
BusService *service,
- DBusConnection *connection)
+ BusOwner *owner)
{
OwnershipRestoreData *d;
DBusList *link;
@@ -760,24 +960,25 @@
return FALSE;
d->service = service;
- d->connection = connection;
+ d->owner = owner;
d->service_link = _dbus_list_alloc_link (service);
- d->connection_link = _dbus_list_alloc_link (connection);
+ d->owner_link = _dbus_list_alloc_link (owner);
d->hash_entry = _dbus_hash_table_preallocate_entry (service->registry->service_hash);
bus_service_ref (d->service);
- dbus_connection_ref (d->connection);
+ bus_owner_ref (d->owner);
+ dbus_connection_ref (d->owner->conn);
- d->before_connection = NULL;
+ d->before_owner = NULL;
link = _dbus_list_get_first_link (&service->owners);
while (link != NULL)
{
- if (link->data == connection)
+ if (link->data == owner)
{
link = _dbus_list_get_next_link (&service->owners, link);
if (link)
- d->before_connection = link->data;
+ d->before_owner = link->data;
break;
}
@@ -786,7 +987,7 @@
}
if (d->service_link == NULL ||
- d->connection_link == NULL ||
+ d->owner_link == NULL ||
d->hash_entry == NULL ||
!bus_transaction_add_cancel_hook (transaction, restore_ownership, d,
free_ownership_restore_data))
@@ -798,13 +999,92 @@
return TRUE;
}
+dbus_bool_t
+bus_service_swap_owner (BusService *service,
+ DBusConnection *connection,
+ BusTransaction *transaction,
+ DBusError *error)
+{
+ DBusList *swap_link;
+ BusOwner *primary_owner;
+
+ _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+ /* We send out notifications before we do any work we
+ * might have to undo if the notification-sending failed
+ */
+
+ /* Send service lost message */
+ primary_owner = bus_service_get_primary_owner (service);
+ if (primary_owner == NULL || primary_owner->conn != connection)
+ _dbus_assert_not_reached ("Tried to swap a non primary owner");
+
+
+ if (!bus_driver_send_service_lost (connection, service->name,
+ transaction, error))
+ return FALSE;
+
+ if (service->owners == NULL)
+ {
+ _dbus_assert_not_reached ("Tried to swap owner of a service that has no owners");
+ }
+ else if (_dbus_list_length_is_one (&service->owners))
+ {
+ _dbus_assert_not_reached ("Tried to swap owner of a service that has no other owners in the queue");
+ }
+ else
+ {
+ DBusList *link;
+ BusOwner *new_owner;
+ DBusConnection *new_owner_conn;
+ link = _dbus_list_get_first_link (&service->owners);
+ _dbus_assert (link != NULL);
+ link = _dbus_list_get_next_link (&service->owners, link);
+ _dbus_assert (link != NULL);
+
+ new_owner = (BusOwner *)link->data;
+ new_owner_conn = new_owner->conn;
+
+ if (!bus_driver_send_service_owner_changed (service->name,
+ bus_connection_get_name (connection),
+ bus_connection_get_name (new_owner_conn),
+ transaction, error))
+ return FALSE;
+
+ /* This will be our new owner */
+ if (!bus_driver_send_service_acquired (new_owner_conn,
+ service->name,
+ transaction,
+ error))
+ return FALSE;
+ }
+
+ if (!add_restore_ownership_to_transaction (transaction, service, primary_owner))
+ {
+ BUS_SET_OOM (error);
+ return FALSE;
+ }
+
+ /* unlink the primary and make it the second link */
+ swap_link = _dbus_list_get_first_link (&service->owners);
+ _dbus_list_unlink (&service->owners, swap_link);
+
+ _dbus_list_insert_after_link (&service->owners,
+ _dbus_list_get_first_link (&service->owners),
+ swap_link);
+
+ return TRUE;
+}
+
/* this function is self-cancelling if you cancel the transaction */
dbus_bool_t
bus_service_remove_owner (BusService *service,
- DBusConnection *owner,
+ DBusConnection *connection,
BusTransaction *transaction,
DBusError *error)
{
+ BusOwner *primary_owner;
+
_DBUS_ASSERT_ERROR_IS_CLEAR (error);
/* We send out notifications before we do any work we
@@ -812,12 +1092,27 @@
*/
/* Send service lost message */
- if (bus_service_get_primary_owner (service) == owner)
+ primary_owner = bus_service_get_primary_owner (service);
+ if (primary_owner != NULL && primary_owner->conn == connection)
{
- if (!bus_driver_send_service_lost (owner, service->name,
+ if (!bus_driver_send_service_lost (connection, service->name,
transaction, error))
return FALSE;
}
+ else
+ {
+ /* if we are not the primary owner then just remove us from the queue */
+ DBusList *link;
+ BusOwner *temp_owner;
+
+ link = _bus_service_find_owner_link (service, connection);
+ _dbus_list_unlink (&service->owners, link);
+ temp_owner = (BusOwner *)link->data;
+ bus_owner_unref (temp_owner);
+ _dbus_list_free_link (link);
+
+ return TRUE;
+ }
if (service->owners == NULL)
{
@@ -826,7 +1121,7 @@
else if (_dbus_list_length_is_one (&service->owners))
{
if (!bus_driver_send_service_owner_changed (service->name,
- bus_connection_get_name (owner),
+ bus_connection_get_name (connection),
NULL,
transaction, error))
return FALSE;
@@ -834,35 +1129,37 @@
else
{
DBusList *link;
- DBusConnection *new_owner;
+ BusOwner *new_owner;
+ DBusConnection *new_owner_conn;
link = _dbus_list_get_first_link (&service->owners);
_dbus_assert (link != NULL);
link = _dbus_list_get_next_link (&service->owners, link);
_dbus_assert (link != NULL);
- new_owner = link->data;
+ new_owner = (BusOwner *)link->data;
+ new_owner_conn = new_owner->conn;
if (!bus_driver_send_service_owner_changed (service->name,
- bus_connection_get_name (owner),
- bus_connection_get_name (new_owner),
+ bus_connection_get_name (connection),
+ bus_connection_get_name (new_owner_conn),
transaction, error))
return FALSE;
/* This will be our new owner */
- if (!bus_driver_send_service_acquired (new_owner,
+ if (!bus_driver_send_service_acquired (new_owner_conn,
service->name,
transaction,
error))
return FALSE;
}
- if (!add_restore_ownership_to_transaction (transaction, service, owner))
+ if (!add_restore_ownership_to_transaction (transaction, service, primary_owner))
{
BUS_SET_OOM (error);
return FALSE;
}
-
- bus_service_unlink_owner (service, owner);
+
+ bus_service_unlink_owner (service, primary_owner);
if (service->owners == NULL)
bus_service_unlink (service);
@@ -896,7 +1193,20 @@
}
}
-DBusConnection*
+DBusConnection *
+bus_service_get_primary_owners_connection (BusService *service)
+{
+ BusOwner *owner;
+
+ owner = bus_service_get_primary_owner (service);
+
+ if (owner != NULL)
+ return owner->conn;
+ else
+ return NULL;
+}
+
+BusOwner*
bus_service_get_primary_owner (BusService *service)
{
return _dbus_list_get_first (&service->owners);
@@ -908,34 +1218,64 @@
return service->name;
}
-void
-bus_service_set_prohibit_replacement (BusService *service,
- dbus_bool_t prohibit_replacement)
+dbus_bool_t
+bus_service_get_allow_replacement (BusService *service)
{
- service->prohibit_replacement = prohibit_replacement != FALSE;
+ BusOwner *owner;
+ DBusList *link;
+
+ _dbus_assert (service->owners != NULL);
+
+ link = _dbus_list_get_first_link (&service->owners);
+ owner = (BusOwner *) link->data;
+
+ return owner->allow_replacement;
}
dbus_bool_t
-bus_service_get_prohibit_replacement (BusService *service)
+bus_service_has_owner (BusService *service,
+ DBusConnection *connection)
{
- return service->prohibit_replacement;
+ DBusList *link;
+
+ link = _bus_service_find_owner_link (service, connection);
+
+ if (link == NULL)
+ return FALSE;
+ else
+ return TRUE;
}
-dbus_bool_t
-bus_service_has_owner (BusService *service,
- DBusConnection *owner)
+dbus_bool_t
+bus_service_list_queued_owners (BusService *service,
+ DBusList **return_list,
+ DBusError *error)
{
DBusList *link;
+ _dbus_assert (*return_list == NULL);
+
link = _dbus_list_get_first_link (&service->owners);
+ _dbus_assert (link != NULL);
while (link != NULL)
{
- if (link->data == owner)
- return TRUE;
-
+ BusOwner *owner;
+ const char *uname;
+
+ owner = (BusOwner *) link->data;
+ uname = bus_connection_get_name (owner->conn);
+
+ if (!_dbus_list_append (return_list, uname))
+ goto oom;
+
link = _dbus_list_get_next_link (&service->owners, link);
}
-
+
+ return TRUE;
+
+ oom:
+ _dbus_list_clear (return_list);
+ BUS_SET_OOM (error);
return FALSE;
}
Index: services.h
===================================================================
RCS file: /cvs/dbus/dbus/bus/services.h,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -d -r1.14 -r1.15
--- services.h 15 Nov 2005 17:19:19 -0000 1.14
+++ services.h 22 Nov 2005 20:37:00 -0000 1.15
@@ -40,7 +40,8 @@
const DBusString *service_name);
BusService* bus_registry_ensure (BusRegistry *registry,
const DBusString *service_name,
- DBusConnection *owner_if_created,
+ DBusConnection *owner_connection_if_created,
+ dbus_uint32_t flags,
BusTransaction *transaction,
DBusError *error);
void bus_registry_foreach (BusRegistry *registry,
@@ -65,23 +66,29 @@
dbus_bool_t bus_registry_set_service_context_table (BusRegistry *registry,
DBusHashTable *table);
-BusService* bus_service_ref (BusService *service);
-void bus_service_unref (BusService *service);
-dbus_bool_t bus_service_add_owner (BusService *service,
- DBusConnection *owner,
- BusTransaction *transaction,
- DBusError *error);
-dbus_bool_t bus_service_remove_owner (BusService *service,
- DBusConnection *owner,
- BusTransaction *transaction,
- DBusError *error);
-dbus_bool_t bus_service_has_owner (BusService *service,
- DBusConnection *owner);
-DBusConnection* bus_service_get_primary_owner (BusService *service);
-void bus_service_set_prohibit_replacement (BusService *service,
- dbus_bool_t prohibit_replacement);
-dbus_bool_t bus_service_get_prohibit_replacement (BusService *service);
-const char* bus_service_get_name (BusService *service);
-
+BusService* bus_service_ref (BusService *service);
+void bus_service_unref (BusService *service);
+dbus_bool_t bus_service_add_owner (BusService *service,
+ DBusConnection *connection,
+ dbus_uint32_t flags,
+ BusTransaction *transaction,
+ DBusError *error);
+dbus_bool_t bus_service_swap_owner (BusService *service,
+ DBusConnection *connection,
+ BusTransaction *transaction,
+ DBusError *error);
+dbus_bool_t bus_service_remove_owner (BusService *service,
+ DBusConnection *connection,
+ BusTransaction *transaction,
+ DBusError *error);
+dbus_bool_t bus_service_has_owner (BusService *service,
+ DBusConnection *connection);
+BusOwner* bus_service_get_primary_owner (BusService *service);
+dbus_bool_t bus_service_get_allow_replacement (BusService *service);
+const char* bus_service_get_name (BusService *service);
+dbus_bool_t bus_service_list_queued_owners (BusService *service,
+ DBusList **return_list,
+ DBusError *error);
+DBusConnection* bus_service_get_primary_owners_connection (BusService *service);
#endif /* BUS_SERVICES_H */
Index: signals.c
===================================================================
RCS file: /cvs/dbus/dbus/bus/signals.c,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -d -r1.13 -r1.14
--- signals.c 29 Jul 2005 17:43:30 -0000 1.13
+++ signals.c 22 Nov 2005 20:37:00 -0000 1.14
@@ -1274,7 +1274,7 @@
if (service == NULL)
return FALSE; /* Service doesn't exist so connection can't own it. */
- return bus_service_get_primary_owner (service) == connection;
+ return bus_service_get_primary_owners_connection (service) == connection;
}
static dbus_bool_t
More information about the dbus-commit
mailing list