diff options
| -rw-r--r-- | ChangeLog | 20 | ||||
| -rw-r--r-- | bus/activation.c | 241 | ||||
| -rw-r--r-- | bus/activation.h | 18 | ||||
| -rw-r--r-- | bus/bus.c | 4 | ||||
| -rw-r--r-- | bus/desktop-file.c | 6 | ||||
| -rw-r--r-- | bus/driver.c | 4 | ||||
| -rw-r--r-- | bus/services.c | 16 | ||||
| -rw-r--r-- | bus/services.h | 2 | ||||
| -rw-r--r-- | dbus/dbus-connection.c | 2 | ||||
| -rw-r--r-- | dbus/dbus-message.c | 2 | ||||
| -rw-r--r-- | dbus/dbus-protocol.h | 6 | 
11 files changed, 295 insertions, 26 deletions
@@ -1,3 +1,23 @@ +2003-03-16  Anders Carlsson  <andersca@codefactory.se> + +	* bus/activation.c: (bus_pending_activation_entry_free), +	(bus_pending_activation_free), (bus_activation_new), +	(bus_activation_unref), (bus_activation_service_created), +	(bus_activation_activate_service): +	* bus/activation.h: +	* bus/bus.c: (bus_context_new): +	* bus/desktop-file.c: (new_section): +	* bus/driver.c: (bus_driver_send_service_deleted), +	(bus_driver_handle_activate_service): +	* bus/services.c: (bus_registry_new), (bus_registry_ensure): +	* bus/services.h: +	* dbus/dbus-connection.c: +	(dbus_connection_send_with_reply_and_block): +	* dbus/dbus-message.c: (dbus_message_append_args_valist): +	* dbus/dbus-protocol.h: +	Make activation work better. Now pending activations will be queued +	and the daemon won't try to activate services that are already registered. +	  2003-03-16  Havoc Pennington  <hp@pobox.com>  	* dbus/dbus-bus.c (ensure_bus_data): handle failure to set diff --git a/bus/activation.c b/bus/activation.c index ba130edd..c7d08baa 100644 --- a/bus/activation.c +++ b/bus/activation.c @@ -22,9 +22,11 @@   */  #include "activation.h"  #include "desktop-file.h" +#include "services.h"  #include "utils.h"  #include <dbus/dbus-internals.h>  #include <dbus/dbus-hash.h> +#include <dbus/dbus-list.h>  #include <sys/types.h>  #include <dirent.h>  #include <errno.h> @@ -37,7 +39,9 @@ struct BusActivation  {    int refcount;    DBusHashTable *entries; +  DBusHashTable *pending_activations;    char *server_address; +  BusContext *context;  };  typedef struct @@ -46,6 +50,57 @@ typedef struct    char *exec;  } BusActivationEntry; +typedef struct BusPendingActivationEntry BusPendingActivationEntry; + +struct BusPendingActivationEntry +{ +  DBusMessage *activation_message; +  DBusConnection *connection; +}; + +typedef struct +{ +  char *service_name; +  DBusList *entries; +} BusPendingActivation; + +static void +bus_pending_activation_entry_free (BusPendingActivationEntry *entry) +{ +  if (entry->activation_message) +    dbus_message_unref (entry->activation_message); +   +  if (entry->connection) +    dbus_connection_unref (entry->connection); + +  dbus_free (entry); +} + +static void +bus_pending_activation_free (BusPendingActivation *activation) +{ +  DBusList *link; +   +  if (!activation) +    return; + +  dbus_free (activation->service_name); + +  link = _dbus_list_get_first_link (&activation->entries); + +  while (link != NULL) +    { +      BusPendingActivationEntry *entry = link->data; + +      bus_pending_activation_entry_free (entry); + +      link = _dbus_list_get_next_link (&activation->entries, link); +    } +  _dbus_list_clear (&activation->entries); +   +  dbus_free (activation); +} +  static void  bus_activation_entry_free (BusActivationEntry *entry)  { @@ -264,7 +319,8 @@ load_directory (BusActivation *activation,  }  BusActivation* -bus_activation_new (const char  *address, +bus_activation_new (BusContext  *context, +		    const char  *address,                      const char **directories,                      DBusError   *error)  { @@ -279,6 +335,7 @@ bus_activation_new (const char  *address,      }    activation->refcount = 1; +  activation->context = context;    /* FIXME: We should split up the server addresses. */    activation->server_address = _dbus_strdup (address); @@ -296,6 +353,15 @@ bus_activation_new (const char  *address,        goto failed;      } +  activation->pending_activations = _dbus_hash_table_new (DBUS_HASH_STRING, NULL, +							  (DBusFreeFunction)bus_pending_activation_free); + +  if (activation->pending_activations == NULL) +    { +      BUS_SET_OOM (error); +      goto failed; +    } +      /* Load service files */    i = 0;    while (directories[i] != NULL) @@ -332,6 +398,8 @@ bus_activation_unref (BusActivation *activation)        dbus_free (activation->server_address);        if (activation->entries)          _dbus_hash_table_unref (activation->entries); +      if (activation->pending_activations) +	_dbus_hash_table_unref (activation->pending_activations);        dbus_free (activation);      }  } @@ -349,12 +417,81 @@ child_setup (void *data)  }  dbus_bool_t -bus_activation_activate_service (BusActivation *activation, -                                 const char    *service_name, -				 DBusError     *error) +bus_activation_service_created (BusActivation *activation, +				const char    *service_name, +				DBusError     *error) +{ +  BusPendingActivation *pending_activation; +  DBusMessage *message; +  DBusList *link; +   +  /* Check if it's a pending activation */ +  pending_activation = _dbus_hash_table_lookup_string (activation->pending_activations, service_name); + +  if (!pending_activation) +    return TRUE; + +  link = _dbus_list_get_first_link (&pending_activation->entries); +  while (link != NULL) +    { +      BusPendingActivationEntry *entry = link->data; +      DBusList *next = _dbus_list_get_next_link (&pending_activation->entries, link); +       +      if (dbus_connection_get_is_connected (entry->connection)) +	{ +	  message = dbus_message_new_reply (entry->activation_message); +	  if (!message) +	    { +	      BUS_SET_OOM (error); +	      goto error; +	    } + +	  if (!dbus_message_append_args (message, +					 DBUS_TYPE_UINT32, DBUS_ACTIVATION_REPLY_ACTIVATED, +					 0)) +	    { +	      dbus_message_unref (message); +	      BUS_SET_OOM (error); +	      goto error; +	    } + +	  if (!dbus_connection_send (entry->connection, message, NULL)) +	    { +	      dbus_message_unref (message); +	      BUS_SET_OOM (error); +	      goto error; +	    } +	} + +      bus_pending_activation_entry_free (entry); +       +      _dbus_list_remove_link (&pending_activation->entries, link);       +      link = next; +    } +   +  _dbus_hash_table_remove_string (activation->pending_activations, service_name); + +  return TRUE; + + error: +  _dbus_hash_table_remove_string (activation->pending_activations, service_name); +  return FALSE; +} + +dbus_bool_t +bus_activation_activate_service (BusActivation  *activation, +				 DBusConnection *connection, +				 DBusMessage    *activation_message, +                                 const char     *service_name, +				 DBusError      *error)  {    BusActivationEntry *entry; +  BusPendingActivation *pending_activation; +  BusPendingActivationEntry *pending_activation_entry; +  DBusMessage *message; +  DBusString service_str;    char *argv[2]; +  dbus_bool_t retval;    entry = _dbus_hash_table_lookup_string (activation->entries, service_name); @@ -366,6 +503,94 @@ bus_activation_activate_service (BusActivation *activation,        return FALSE;      } +  /* Check if the service is active */ +  _dbus_string_init_const (&service_str, service_name); +  if (bus_registry_lookup (bus_context_get_registry (activation->context), &service_str) != NULL) +    { +      message = dbus_message_new_reply (activation_message); + +      if (!message) +	{ +	  BUS_SET_OOM (error); +	  return FALSE; +	} + +      if (!dbus_message_append_args (message, +				     DBUS_TYPE_UINT32, DBUS_ACTIVATION_REPLY_ALREADY_ACTIVE,  +				     0)) +	{ +	  BUS_SET_OOM (error); +	  dbus_message_unref (message); +	  return FALSE; +	} + +      retval = dbus_connection_send (connection, message, NULL); +      dbus_message_unref (message); +      if (!retval) +	BUS_SET_OOM (error); + +      return retval; +    } + +  pending_activation_entry = dbus_new0 (BusPendingActivationEntry, 1); +  if (!pending_activation_entry) +    { +      BUS_SET_OOM (error); +      return FALSE; +    } + +  pending_activation_entry->activation_message = activation_message; +  dbus_message_ref (activation_message); +  pending_activation_entry->connection = connection; +  dbus_connection_ref (connection); +   +  /* Check if the service is being activated */ +  pending_activation = _dbus_hash_table_lookup_string (activation->pending_activations, service_name); +  if (pending_activation) +    { +      if (!_dbus_list_append (&pending_activation->entries, entry)) +	{ +	  BUS_SET_OOM (error); +	  bus_pending_activation_entry_free (pending_activation_entry); + +	  return FALSE; +	} +    } +  else +    { +      pending_activation = dbus_new0 (BusPendingActivation, 1); +      if (!pending_activation) +	{ +	  BUS_SET_OOM (error); +	  bus_pending_activation_entry_free (pending_activation_entry);	   +	  return FALSE; +	} +      pending_activation->service_name = _dbus_strdup (service_name); +      if (!pending_activation->service_name) +	{ +	  BUS_SET_OOM (error); +	  bus_pending_activation_free (pending_activation); +	  bus_pending_activation_entry_free (pending_activation_entry);	   +	  return FALSE; +	} + +      if (!_dbus_list_append (&pending_activation->entries, entry)) +	{ +	  BUS_SET_OOM (error); +	  bus_pending_activation_free (pending_activation); +	  bus_pending_activation_entry_free (pending_activation_entry);	   +	  return FALSE; +	} +       +      if (!_dbus_hash_table_insert_string (activation->pending_activations, +					   pending_activation->service_name, pending_activation)) +	{ +	  BUS_SET_OOM (error); +	  bus_pending_activation_free (pending_activation); +	  return FALSE; +	} +    } +      /* FIXME we need to support a full command line, not just a single     * argv[0]     */ @@ -377,7 +602,11 @@ bus_activation_activate_service (BusActivation *activation,    if (!_dbus_spawn_async (argv,  			  child_setup, activation,   			  error)) -    return FALSE; - +    { +      _dbus_hash_table_remove_string (activation->pending_activations, +				      pending_activation->service_name); +      return FALSE; +    } +      return TRUE;  } diff --git a/bus/activation.h b/bus/activation.h index 4e363c92..1fd416ea 100644 --- a/bus/activation.h +++ b/bus/activation.h @@ -27,15 +27,19 @@  #include <dbus/dbus.h>  #include "bus.h" -BusActivation* bus_activation_new              (const char     *address, -                                                const char    **paths, -                                                DBusError      *error); +BusActivation* bus_activation_new              (BusContext     *context, +						const char     *address, +						const char    **paths, +						DBusError      *error);  void           bus_activation_ref              (BusActivation  *activation);  void           bus_activation_unref            (BusActivation  *activation);  dbus_bool_t    bus_activation_activate_service (BusActivation  *activation, -                                                const char     *service_name, -                                                DBusError      *error); - - +						DBusConnection *connection,  +						DBusMessage    *activation_message, +						const char     *service_name, +						DBusError      *error); +dbus_bool_t    bus_activation_service_created  (BusActivation  *activation, +						const char     *service_name, +						DBusError      *error);  #endif /* BUS_ACTIVATION_H */ @@ -141,7 +141,7 @@ bus_context_new (const char  *address,        goto failed;      } -  context->activation = bus_activation_new (address, service_dirs, +  context->activation = bus_activation_new (context, address, service_dirs,                                              error);    if (context->activation == NULL)      { @@ -156,7 +156,7 @@ bus_context_new (const char  *address,        goto failed;      } -  context->registry = bus_registry_new (); +  context->registry = bus_registry_new (context);    if (context->registry == NULL)      {        BUS_SET_OOM (error); diff --git a/bus/desktop-file.c b/bus/desktop-file.c index 65a0d76f..f45a997e 100644 --- a/bus/desktop-file.c +++ b/bus/desktop-file.c @@ -272,8 +272,8 @@ new_section (BusDesktopFile *desktop_file,    name_copy = _dbus_strdup (name);    if (name_copy == NULL)      return NULL; -   -  n = desktop_file->n_sections + 1; + +  n = desktop_file->n_sections;    desktop_file->sections[n].section_name = name_copy;    desktop_file->sections[n].n_lines = 0; @@ -287,7 +287,7 @@ new_section (BusDesktopFile *desktop_file,        return NULL;      } -  desktop_file->n_sections = n; +  desktop_file->n_sections += 1;    return &desktop_file->sections[n];    } diff --git a/bus/driver.c b/bus/driver.c index 09ec18af..98085fc7 100644 --- a/bus/driver.c +++ b/bus/driver.c @@ -45,7 +45,7 @@ bus_driver_send_service_deleted (const char     *service_name,    dbus_bool_t retval;    _dbus_verbose ("sending service deleted: %s\n", service_name); -   +    message = dbus_message_new (DBUS_SERVICE_BROADCAST,                                DBUS_MESSAGE_SERVICE_DELETED);    if (message == NULL) @@ -625,7 +625,7 @@ bus_driver_handle_activate_service (DBusConnection *connection,    retval = FALSE; -  if (!bus_activation_activate_service (activation, name, error)) +  if (!bus_activation_activate_service (activation, connection, message, name, error))      goto out;    retval = TRUE; diff --git a/bus/services.c b/bus/services.c index 92f6cdf4..821cb4af 100644 --- a/bus/services.c +++ b/bus/services.c @@ -29,6 +29,7 @@  #include "services.h"  #include "connection.h"  #include "utils.h" +#include "activation.h"  struct BusService  { @@ -42,13 +43,15 @@ struct BusService  struct BusRegistry  {    int refcount; + +  BusContext *context;    DBusHashTable *service_hash;    DBusMemPool   *service_pool;  };  BusRegistry* -bus_registry_new (void) +bus_registry_new (BusContext *context)  {    BusRegistry *registry; @@ -57,7 +60,8 @@ bus_registry_new (void)      return NULL;    registry->refcount = 1; - +  registry->context = context; +      registry->service_hash = _dbus_hash_table_new (DBUS_HASH_STRING,                                                   NULL, NULL);    if (registry->service_hash == NULL) @@ -158,6 +162,14 @@ bus_registry_ensure (BusRegistry               *registry,        return NULL;      } +  if (!bus_activation_service_created (bus_context_get_activation (registry->context), +				       service->name, error)) +    { +      dbus_free (service->name); +      _dbus_mem_pool_dealloc (registry->service_pool, service); +      return NULL; +    } +      if (!bus_service_add_owner (service, owner_if_created,                                transaction, error))      { diff --git a/bus/services.h b/bus/services.h index 5e9ece18..aba2989a 100644 --- a/bus/services.h +++ b/bus/services.h @@ -32,7 +32,7 @@  typedef void (* BusServiceForeachFunction) (BusService       *service,                                              void             *data); -BusRegistry* bus_registry_new           (void); +BusRegistry* bus_registry_new           (BusContext                  *context);  void         bus_registry_ref           (BusRegistry                 *registry);  void         bus_registry_unref         (BusRegistry                 *registry);  BusService*  bus_registry_lookup        (BusRegistry                 *registry, diff --git a/dbus/dbus-connection.c b/dbus/dbus-connection.c index 2b4a7600..7f9423af 100644 --- a/dbus/dbus-connection.c +++ b/dbus/dbus-connection.c @@ -1488,7 +1488,7 @@ dbus_connection_send_with_reply_and_block (DBusConnection     *connection,        timeout_milliseconds = (end_tv_sec - tv_sec) * 1000 +          (end_tv_usec - tv_usec) / 1000;        _dbus_verbose ("%d milliseconds remain\n", timeout_milliseconds); -      _dbus_assert (timeout_milliseconds > 0); +      _dbus_assert (timeout_milliseconds >= 0);        if (status == DBUS_DISPATCH_NEED_MEMORY)          { diff --git a/dbus/dbus-message.c b/dbus/dbus-message.c index 6bcc2060..51a694aa 100644 --- a/dbus/dbus-message.c +++ b/dbus/dbus-message.c @@ -1167,7 +1167,7 @@ dbus_message_append_args_valist (DBusMessage *message,  	case DBUS_TYPE_STRING_ARRAY:  	  {  	    int len; -	    char **data; +	    const char **data;  	    data = va_arg (var_args, const char **);  	    len = va_arg (var_args, int); diff --git a/dbus/dbus-protocol.h b/dbus/dbus-protocol.h index e0b0c985..c7eb737f 100644 --- a/dbus/dbus-protocol.h +++ b/dbus/dbus-protocol.h @@ -77,6 +77,10 @@ extern "C" {  #define DBUS_SERVICE_REPLY_IN_QUEUE       0x2  #define DBUS_SERVICE_REPLY_SERVICE_EXISTS 0x4  #define DBUS_SERVICE_REPLY_ALREADY_OWNER  0x8 + +/* Activation replies */ +#define DBUS_ACTIVATION_REPLY_ACTIVATED      0x0 +#define DBUS_ACTIVATION_REPLY_ALREADY_ACTIVE 0x1  /* Messages */  #define DBUS_MESSAGE_ACTIVATE_SERVICE      "org.freedesktop.DBus.ActivateService"   @@ -88,7 +92,7 @@ extern "C" {  #define DBUS_MESSAGE_SERVICE_CREATED       "org.freedesktop.DBus.ServiceCreated"  #define DBUS_MESSAGE_SERVICE_DELETED       "org.freedesktop.DBus.ServiceDeleted"  #define DBUS_MESSAGE_SERVICE_LOST          "org.freedesktop.DBus.ServiceLost" -   +  #define DBUS_MESSAGE_LOCAL_DISCONNECT      "org.freedesktop.Local.Disconnect"  #ifdef __cplusplus  | 
