summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAnders Carlsson <andersca@codefactory.se>2003-03-16 22:25:18 +0000
committerAnders Carlsson <andersca@codefactory.se>2003-03-16 22:25:18 +0000
commit3f4086f0fdd1cc7fc03585ec9f750897fb3c1d55 (patch)
treea180077e4b5a97e83b0afc08619b2fb5db790f22
parentd1f65c6c4f9dd9750f9ad3eda5b590a4ffca6498 (diff)
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.
-rw-r--r--ChangeLog20
-rw-r--r--bus/activation.c241
-rw-r--r--bus/activation.h18
-rw-r--r--bus/bus.c4
-rw-r--r--bus/desktop-file.c6
-rw-r--r--bus/driver.c4
-rw-r--r--bus/services.c16
-rw-r--r--bus/services.h2
-rw-r--r--dbus/dbus-connection.c2
-rw-r--r--dbus/dbus-message.c2
-rw-r--r--dbus/dbus-protocol.h6
11 files changed, 295 insertions, 26 deletions
diff --git a/ChangeLog b/ChangeLog
index 76310fc5..7740ee18 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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 */
diff --git a/bus/bus.c b/bus/bus.c
index 4319e5fe..589dda1b 100644
--- a/bus/bus.c
+++ b/bus/bus.c
@@ -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