Commit 3f4086f0 authored by Anders Carlsson's avatar Anders Carlsson

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.
parent d1f65c6c
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
......
......@@ -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;
}
......@@ -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);
......
......@@ -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];
}
......
......@@ -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;
......
......@@ -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))
{
......
......@@ -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,
......
......@@ -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)
{
......
......@@ -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);
......
......@@ -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
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment