summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Hult <rhult@src.gnome.org>2003-12-04 11:43:50 +0000
committerRichard Hult <rhult@src.gnome.org>2003-12-04 11:43:50 +0000
commitb3bf70b95c191945d5f07aa19878a4a849608c5a (patch)
tree642f72065236edad65fabac601ba4ce16a198fbe
parent0dbe4caf7504b5d072f24da8ddbbad75ec463c06 (diff)
downloadgconf-b3bf70b95c191945d5f07aa19878a4a849608c5a.tar.gz
Only notify clients that have asked for notification on the changed key
and handle both when the service and clients disappear.
-rw-r--r--gconf/gconf-database-dbus.c277
-rw-r--r--gconf/gconf-dbus-utils.h10
-rw-r--r--gconf/gconf-dbus.c1189
-rw-r--r--gconf/gconfd-dbus.c9
4 files changed, 797 insertions, 688 deletions
diff --git a/gconf/gconf-database-dbus.c b/gconf/gconf-database-dbus.c
index e4d63f98..372bd243 100644
--- a/gconf/gconf-database-dbus.c
+++ b/gconf/gconf-database-dbus.c
@@ -1,3 +1,4 @@
+/* -*- mode: C; c-file-style: "gnu" -*- */
/* GConf
* Copyright (C) 2003 Imendio HB
*
@@ -17,6 +18,8 @@
* Boston, MA 02111-1307, USA.
*/
+#include <config.h>
+#include <string.h>
#include "gconfd.h"
#include "gconf-dbus-utils.h"
#include "gconfd-dbus.h"
@@ -29,20 +32,36 @@ static GConfDatabaseDBus *default_db = NULL;
static gint object_nr = 0;
struct _GConfDatabaseDBus {
- GConfDatabase *db;
- DBusConnection *conn;
+ GConfDatabase *db;
+ DBusConnection *conn;
+
+ char *address;
+ char *object_path;
+
+ /* Information about clients that want notification. */
+ GHashTable *notifications;
+};
+
+typedef struct {
+ char *namespace_section;
+ GList *clients;
+} NotificationData;
- char *address;
- char *object_path;
- /* Information about listeners */
-};
static void database_unregistered_func (DBusConnection *connection,
GConfDatabaseDBus *db);
static DBusHandlerResult
database_message_func (DBusConnection *connection,
DBusMessage *message,
GConfDatabaseDBus *db);
+static DBusHandlerResult
+database_filter_func (DBusConnection *connection,
+ DBusMessage *message,
+ GConfDatabaseDBus *db);
+static DBusHandlerResult
+database_handle_service_deleted (DBusConnection *connection,
+ DBusMessage *message,
+ GConfDatabaseDBus *db);
static void database_handle_lookup (DBusConnection *conn,
DBusMessage *message,
GConfDatabaseDBus *db);
@@ -73,6 +92,17 @@ database_handle_get_all_dirs (DBusConnection *conn,
static void database_handle_set_schema (DBusConnection *conn,
DBusMessage *message,
GConfDatabaseDBus *db);
+static void database_handle_add_notify (DBusConnection *conn,
+ DBusMessage *message,
+ GConfDatabaseDBus *db);
+static gboolean
+database_remove_notification_data (GConfDatabaseDBus *db,
+ NotificationData *notification,
+ const char *client);
+static void
+database_handle_remove_notify (DBusConnection *conn,
+ DBusMessage *message,
+ GConfDatabaseDBus *db);
static void ensure_initialized (void);
static void database_removed (GConfDatabaseDBus *db);
@@ -143,13 +173,79 @@ database_message_func (DBusConnection *connection,
GCONF_DBUS_DATABASE_INTERFACE,
GCONF_DBUS_DATABASE_SET_SCHEMA)) {
database_handle_set_schema (connection, message, db);
+ }
+ else if (dbus_message_is_method_call (message,
+ GCONF_DBUS_DATABASE_INTERFACE,
+ GCONF_DBUS_DATABASE_ADD_NOTIFY)) {
+ database_handle_add_notify (connection, message, db);
+ }
+ else if (dbus_message_is_method_call (message,
+ GCONF_DBUS_DATABASE_INTERFACE,
+ GCONF_DBUS_DATABASE_REMOVE_NOTIFY)) {
+ database_handle_remove_notify (connection, message, db);
} else {
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}
return DBUS_HANDLER_RESULT_HANDLED;
}
-
+
+static void
+get_all_notifications_func (gpointer key,
+ gpointer value,
+ gpointer user_data)
+{
+ GList **list = user_data;
+
+ *list = g_list_prepend (*list, value);
+}
+
+static DBusHandlerResult
+database_filter_func (DBusConnection *connection,
+ DBusMessage *message,
+ GConfDatabaseDBus *db)
+{
+ if (dbus_message_is_signal (message,
+ DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
+ "ServiceDeleted"))
+ return database_handle_service_deleted (connection, message, db);
+
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+static DBusHandlerResult
+database_handle_service_deleted (DBusConnection *connection,
+ DBusMessage *message,
+ GConfDatabaseDBus *db)
+{
+ DBusMessageIter iter;
+ char *service;
+ GList *notifications = NULL, *l;
+ NotificationData *notification;
+
+ /* FIXME: This might be a bit too slow to do like this. We could add a hash
+ * table that maps client base service names to notification data, instead of
+ * going through the entire list of notifications and clients.
+ */
+ dbus_message_iter_init (message, &iter);
+ service = dbus_message_iter_get_string (&iter);
+
+ g_hash_table_foreach (db->notifications, get_all_notifications_func,
+ &notifications);
+
+ for (l = notifications; l; l = l->next)
+ {
+ notification = l->data;
+
+ database_remove_notification_data (db, notification, service);
+ }
+
+ g_list_free (notifications);
+ dbus_free (service);
+
+ return DBUS_HANDLER_RESULT_HANDLED;
+}
+
static void
database_handle_lookup (DBusConnection *conn,
DBusMessage *message,
@@ -471,6 +567,104 @@ database_handle_set_schema (DBusConnection *conn,
}
static void
+database_handle_add_notify (DBusConnection *conn,
+ DBusMessage *message,
+ GConfDatabaseDBus *db)
+{
+ gchar *namespace_section;
+ DBusMessage *reply;
+ const char *sender;
+ NotificationData *notification;
+
+ if (!gconfd_dbus_get_message_args (conn, message,
+ DBUS_TYPE_STRING, &namespace_section,
+ 0))
+ return;
+
+ sender = dbus_message_get_sender (message);
+
+ notification = g_hash_table_lookup (db->notifications, namespace_section);
+
+ if (notification == NULL)
+ {
+ notification = g_new0 (NotificationData, 1);
+ notification->namespace_section = g_strdup (namespace_section);
+
+ g_hash_table_insert (db->notifications,
+ notification->namespace_section, notification);
+ }
+
+ notification->clients = g_list_prepend (notification->clients,
+ g_strdup (sender));
+
+ dbus_free (namespace_section);
+
+ reply = dbus_message_new_method_return (message);
+ dbus_connection_send (conn, reply, NULL);
+ dbus_message_unref (reply);
+}
+
+static gboolean
+database_remove_notification_data (GConfDatabaseDBus *db,
+ NotificationData *notification,
+ const char *client)
+{
+ GList *element;
+
+ element = g_list_find_custom (notification->clients, client,
+ (GCompareFunc)strcmp);
+ if (element == NULL)
+ return FALSE;
+
+ notification->clients = g_list_remove_link (notification->clients, element);
+ if (notification->clients == NULL)
+ {
+ g_hash_table_remove (db->notifications,
+ notification->namespace_section);
+
+ g_free (notification->namespace_section);
+ g_free (notification);
+ }
+
+ g_free (element->data);
+ g_list_free_1 (element);
+
+ return TRUE;
+}
+
+static void
+database_handle_remove_notify (DBusConnection *conn,
+ DBusMessage *message,
+ GConfDatabaseDBus *db)
+{
+ gchar *namespace_section;
+ DBusMessage *reply;
+ const char *sender;
+ NotificationData *notification;
+
+ if (!gconfd_dbus_get_message_args (conn, message,
+ DBUS_TYPE_STRING, &namespace_section,
+ 0))
+ return;
+
+ sender = dbus_message_get_sender (message);
+
+ notification = g_hash_table_lookup (db->notifications, namespace_section);
+ dbus_free (namespace_section);
+
+ /* Notification can be NULL if the client and server get out of sync. */
+ if (notification == NULL || !database_remove_notification_data (db, notification, sender))
+ {
+ gconf_log (GCL_DEBUG, _("Notification on %s doesn't exist"),
+ namespace_section);
+ }
+
+ reply = dbus_message_new_method_return (message);
+ dbus_connection_send (conn, reply, NULL);
+ dbus_message_unref (reply);
+}
+
+static void
database_removed (GConfDatabaseDBus *dbus_db)
{
/* FIXME: Free stuff */
@@ -540,6 +734,12 @@ gconf_database_dbus_get (DBusConnection *conn, const gchar *address,
g_strfreev (path);
+ dbus_db->notifications = g_hash_table_new (g_str_hash, g_str_equal);
+
+ dbus_connection_add_filter (conn,
+ (DBusHandleMessageFunction)database_filter_func,
+ dbus_db, NULL);
+
return dbus_db;
}
@@ -578,8 +778,11 @@ gconf_database_dbus_notify_listeners (GConfDatabase *db,
gboolean is_default,
gboolean is_writable)
{
- DBusMessage *signal;
GConfDatabaseDBus *dbus_db = NULL;
+ char *dir, *sep;
+ GList *l;
+ NotificationData *notification;
+ DBusMessage *message;
if (db == default_db->db)
dbus_db = default_db;
@@ -589,17 +792,51 @@ gconf_database_dbus_notify_listeners (GConfDatabase *db,
if (!dbus_db)
return;
- signal = dbus_message_new_signal (dbus_db->object_path,
- GCONF_DBUS_DATABASE_INTERFACE,
- "Notify");
-
- gconf_dbus_message_append_entry (signal,
- key,
- value,
- is_default,
- is_writable,
- NULL);
+ dir = g_strdup (key);
+
+ /* Lookup the key in the namespace hierarchy, start with the full key and then
+ * remove the leaf, lookup again, remove the leaf, and so on until a match is
+ * found. Notify the clients (identified by their base service) that
+ * correspond to the found namespace.
+ */
+ while (1)
+ {
+ notification = g_hash_table_lookup (dbus_db->notifications, dir);
+
+ if (notification)
+ {
+ for (l = notification->clients; l; l = l->next)
+ {
+ const char *base_service = l->data;
+
+ message = dbus_message_new_method_call (base_service,
+ GCONF_DBUS_CLIENT_OBJECT,
+ GCONF_DBUS_CLIENT_INTERFACE,
+ "Notify");
+
+ dbus_message_append_args (message,
+ DBUS_TYPE_STRING, dbus_db->object_path,
+ DBUS_TYPE_STRING, dir,
+ DBUS_TYPE_INVALID);
+
+ gconf_dbus_message_append_entry (message,
+ key,
+ value,
+ is_default,
+ is_writable,
+ NULL);
+
+ dbus_connection_send (dbus_db->conn, message, NULL);
+ dbus_message_unref (message);
+ }
+ }
+
+ sep = strrchr (dir, '/');
+ if (sep == dir)
+ break;
+
+ *sep = '\0';
+ }
- dbus_connection_send (dbus_db->conn, signal, NULL);
- dbus_message_unref (signal);
+ g_free (dir);
}
diff --git a/gconf/gconf-dbus-utils.h b/gconf/gconf-dbus-utils.h
index 811b499a..e0df9742 100644
--- a/gconf/gconf-dbus-utils.h
+++ b/gconf/gconf-dbus-utils.h
@@ -45,9 +45,17 @@
#define GCONF_DBUS_DATABASE_GET_ALL_ENTRIES "AllEntries"
#define GCONF_DBUS_DATABASE_GET_ALL_DIRS "AllDirs"
#define GCONF_DBUS_DATABASE_SET_SCHEMA "SetSchema"
+
+#define GCONF_DBUS_DATABASE_ADD_NOTIFY "AddNotify"
+#define GCONF_DBUS_DATABASE_REMOVE_NOTIFY "RemoveNotify"
#define GCONF_DBUS_LISTENER_NOTIFY "Notify"
-
+
+#define GCONF_DBUS_CLIENT_SERVICE "org.gnome.GConf.ClientService"
+#define GCONF_DBUS_CLIENT_OBJECT "/org/gnome/GConf/Client"
+#define GCONF_DBUS_CLIENT_INTERFACE "org.gnome.GConf.Client"
+
+
#define GCONF_DBUS_UNSET_INCLUDING_SCHEMA_NAMES 0x1
#define GCONF_DBUS_ERROR_FAILED "org.gnome.GConf.Error.Failed"
diff --git a/gconf/gconf-dbus.c b/gconf/gconf-dbus.c
index 1037a9b7..129b0ae6 100644
--- a/gconf/gconf-dbus.c
+++ b/gconf/gconf-dbus.c
@@ -36,13 +36,10 @@
#include <unistd.h>
#include <dbus/dbus.h>
-#define d(x)
-
-/* Maximum number of times to try re-spawning the server if it's down. */
-#define MAX_RETRIES 1
+#define d(x) x
#define BUS_RULE "type='signal',sender='org.freedesktop.DBus',interface='org.freedesktop.DBus'"
-#define NOTIFY_RULE "type='signal',interface='org.gnome.GConf.Database'"
+#define NOTIFY_RULE "type='method_call',interface='org.gnome.GConf.Database'"
struct _GConfEngine {
guint refcount;
@@ -73,8 +70,6 @@ struct _GConfEngine {
* has no ctable and no notifications)
*/
guint is_local : 1;
-
- guint has_filter : 1;
};
typedef struct {
@@ -91,27 +86,29 @@ typedef struct {
} CnxnsData;
-static DBusConnection *glob_conn = NULL;
+static DBusConnection *global_conn = NULL;
static gboolean service_running = FALSE;
+static gboolean needs_reconnect = FALSE;
static GConfEngine *default_engine = NULL;
static GHashTable *engines_by_db = NULL;
static GHashTable *engines_by_address = NULL;
static gboolean ensure_dbus_connection (void);
-static gboolean gconf_activate_service (gboolean start_if_not_found,
- GError **err);
-static const gchar *gconf_get_config_server (gboolean start_if_not_found,
+static gboolean ensure_service (gboolean start_if_not_found,
GError **err);
-static void gconf_engine_detach (GConfEngine *conf);
-static gboolean gconf_engine_connect (GConfEngine *conf,
+static gboolean ensure_database (GConfEngine *conf,
gboolean start_if_not_found,
GError **err);
+static void gconf_engine_detach (GConfEngine *conf);
static void gconf_engine_set_database (GConfEngine *conf,
const gchar *db);
static const gchar *gconf_engine_get_database (GConfEngine *conf,
gboolean start_if_not_found,
GError **err);
+
+
+
static void register_engine (GConfEngine *conf);
static void unregister_engine (GConfEngine *conf);
static GConfCnxn * gconf_cnxn_new (GConfEngine *conf,
@@ -132,22 +129,22 @@ static void gconf_cnxn_insert (GConfEngine *conf,
GConfCnxn *cnxn);
static void gconf_cnxn_remove (GConfEngine *conf,
GConfCnxn *cnxn);
-static DBusHandlerResult
-gconf_dbus_notify_filter (DBusConnection *dbus_conn,
- DBusMessage *message,
- gpointer user_data);
+static gboolean send_notify_add (GConfEngine *conf,
+ GConfCnxn *cnxn,
+ GError **err);
+static void reinitialize_databases (void);
static DBusHandlerResult
gconf_dbus_message_filter (DBusConnection *dbus_conn,
DBusMessage *message,
gpointer user_data);
-static GConfEngine *lookup_engine (const gchar *address);
-/*static GConfEngine *lookup_engine_by_database (const gchar *db);*/
+static GConfEngine *lookup_engine_by_address (const gchar *address);
+static GConfEngine *lookup_engine_by_database (const gchar *db);
static gboolean gconf_handle_dbus_exception (DBusMessage *message,
DBusError *derr,
GError **gerr);
-static gboolean gconf_server_broken (DBusMessage *message);
static void gconf_detach_config_server (void);
-static DBusHandlerResult handle_notify (DBusConnection *connection,
+static DBusHandlerResult
+ handle_notify (DBusConnection *connection,
DBusMessage *message,
GConfEngine *conf);
@@ -194,40 +191,10 @@ dbus_error_name_to_gconf_errno (const char *name)
return GCONF_ERROR_SUCCESS;
}
-/* Just returns TRUE if there's an exception indicating the server is probably
- * hosed; no side effects.
+/* If no error is detected, return FALSE with no side-effects. If an error is
+ * detected, return TRUE, set gerr, unref message and free derr.
*/
static gboolean
-gconf_server_broken (DBusMessage *message)
-{
- const char *name;
-
- /* A server that doesn't reply is a broken server. */
- if (!message)
- {
- service_running = FALSE;
- d(g_print ("server broken!\n"));
- return TRUE;
- }
-
- if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_ERROR)
- return FALSE;
-
- name = dbus_message_get_member (message);
-
- if (g_str_has_prefix (name, "org.freedesktop.DBus.Error"))
- {
- service_running = FALSE;
- return TRUE;
- }
- else if (strcmp (name, GCONF_DBUS_ERROR_IN_SHUTDOWN) != 0)
- return TRUE;
- else
- return FALSE;
-}
-
-/* Returns TRUE if there was an error and sets err. Also frees derr. */
-static gboolean
gconf_handle_dbus_exception (DBusMessage *message, DBusError *derr, GError **gerr)
{
char *error_string;
@@ -255,7 +222,7 @@ gconf_handle_dbus_exception (DBusMessage *message, DBusError *derr, GError **ger
return TRUE;
}
- if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_ERROR)
+ if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_ERROR)
return FALSE;
name = dbus_message_get_member (message);
@@ -287,6 +254,8 @@ gconf_handle_dbus_exception (DBusMessage *message, DBusError *derr, GError **ger
name, error_string);
}
+ dbus_message_unref (message);
+
return TRUE;
}
@@ -297,7 +266,7 @@ gconf_engine_blank (gboolean remote)
_gconf_init_i18n ();
- conf = g_new0(GConfEngine, 1);
+ conf = g_new0 (GConfEngine, 1);
conf->refcount = 1;
@@ -358,7 +327,6 @@ gconf_engine_pop_owner_usage (GConfEngine *engine,
engine->owner_use_count -= 1;
}
-#if 0
static GConfEngine *
lookup_engine_by_database (const gchar *db)
{
@@ -367,18 +335,18 @@ lookup_engine_by_database (const gchar *db)
else
return NULL;
}
-#endif
static void
database_hash_value_destroy (gpointer value)
{
GConfEngine *conf = value;
+ g_print ("DESTROY FUNC FOR %s\n", conf->database);
+
g_free (conf->database);
conf->database = NULL;
}
-/* This takes ownership of the ConfigDatabase */
static void
gconf_engine_set_database (GConfEngine *conf,
const gchar *db)
@@ -406,104 +374,189 @@ gconf_engine_detach (GConfEngine *conf)
}
static gboolean
-gconf_engine_connect (GConfEngine *conf,
- gboolean start_if_not_found,
- GError **err)
+ensure_dbus_connection (void)
+{
+ if (global_conn != NULL)
+ return TRUE;
+
+ global_conn = dbus_bus_get_with_g_main (DBUS_BUS_SESSION, NULL);
+
+ if (global_conn == NULL)
+ return FALSE;
+
+ dbus_bus_add_match (global_conn, BUS_RULE, NULL);
+ dbus_bus_add_match (global_conn, NOTIFY_RULE, NULL);
+
+ dbus_connection_add_filter (global_conn, gconf_dbus_message_filter,
+ NULL, NULL);
+
+ return TRUE;
+}
+
+static gboolean
+ensure_service (gboolean start_if_not_found,
+ GError **err)
{
- const gchar *cs;
- const gchar *db = NULL;
- int tries = 0;
- DBusMessage *message, *reply;
DBusError error;
+ DBusMessage *message, *reply;
- g_return_val_if_fail (!conf->is_local, TRUE);
+ if (global_conn == NULL)
+ {
+ if (!ensure_dbus_connection ())
+ {
+ g_set_error (err, GCONF_ERROR,
+ GCONF_ERROR_NO_SERVER,
+ _("No D-BUS daemon running\n"));
+ return FALSE;
+ }
- if (conf->database != NULL)
+ g_assert (global_conn != NULL);
+ }
+
+ if (service_running)
return TRUE;
- RETRY:
+ if (start_if_not_found)
+ {
+ d(g_print ("* activate_service, activating\n"));
+
+ message = dbus_message_new_method_call (DBUS_SERVICE_ORG_FREEDESKTOP_DBUS,
+ DBUS_PATH_ORG_FREEDESKTOP_DBUS,
+ DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
+ "ActivateService");
- cs = gconf_get_config_server (start_if_not_found, err);
+ dbus_message_append_args (message,
+ DBUS_TYPE_STRING, GCONF_DBUS_SERVICE,
+ DBUS_TYPE_UINT32, 0,
+ 0);
+
+ dbus_error_init (&error);
+
+ reply = dbus_connection_send_with_reply_and_block (global_conn,
+ message, -1,
+ &error);
+
+ dbus_message_unref (message);
+
+ if (reply == NULL)
+ {
+ const gchar *msg;
+
+ if (dbus_error_is_set (&error))
+ msg = error.message;
+ else
+ msg = _("Unknown error");
+
+ g_set_error (err, GCONF_ERROR,
+ GCONF_ERROR_NO_SERVER,
+ _("Failed to activate configuration server: %s\n"),
+ msg);
- if (cs == NULL)
- return FALSE; /* Error should already be set */
+ if (dbus_error_is_set (&error))
+ dbus_error_free (&error);
+
+ return FALSE;
+ }
+
+ if (dbus_message_get_type (reply) == DBUS_MESSAGE_TYPE_ERROR)
+ {
+ gchar *error_message;
+
+ dbus_message_get_args (reply, NULL,
+ DBUS_TYPE_STRING, &error_message,
+ 0);
+ g_set_error (err, GCONF_ERROR,
+ GCONF_ERROR_NO_SERVER,
+ _("Failed to activate configuration server: %s\n"),
+ error_message);
+ dbus_free (error_message);
+ dbus_message_unref (reply);
+ return FALSE;
+ }
+
+ service_running = TRUE;
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static gboolean
+ensure_database (GConfEngine *conf,
+ gboolean start_if_not_found,
+ GError **err)
+{
+ DBusMessage *message, *reply;
+ DBusError error;
+ gchar *db;
+
+ g_return_val_if_fail (!conf->is_local, TRUE);
+
+ if (!ensure_service (start_if_not_found, err))
+ return FALSE;
+
+ if (needs_reconnect)
+ {
+ /* Re-connect notifications and re-get database names from the previous
+ * (if any) instance of the GConf service.
+ */
+ needs_reconnect = FALSE;
+ reinitialize_databases ();
+ }
+
+ if (conf->database != NULL)
+ return TRUE;
+
if (conf->is_default)
{
- d(g_print ("get default db, %s\n", cs));
-
message = dbus_message_new_method_call (GCONF_DBUS_SERVICE,
- cs,
+ GCONF_DBUS_SERVER_OBJECT,
GCONF_DBUS_SERVER_INTERFACE,
GCONF_DBUS_SERVER_GET_DEFAULT_DB);
-
- dbus_error_init (&error);
- reply = dbus_connection_send_with_reply_and_block (glob_conn, message, -1, &error);
}
else
{
message = dbus_message_new_method_call (GCONF_DBUS_SERVICE,
- cs,
+ GCONF_DBUS_SERVER_OBJECT,
GCONF_DBUS_SERVER_INTERFACE,
GCONF_DBUS_SERVER_GET_DB);
dbus_message_append_args (message,
DBUS_TYPE_STRING, conf->address,
DBUS_TYPE_INVALID);
-
- dbus_error_init (&error);
- reply = dbus_connection_send_with_reply_and_block (glob_conn, message, -1, &error);
}
- d(g_print ("got reply from get_db/get_default_db %p\n", reply));
+ dbus_error_init (&error);
+ reply = dbus_connection_send_with_reply_and_block (global_conn,
+ message, -1, &error);
dbus_message_unref (message);
- if (gconf_server_broken (reply))
- {
- if (tries < MAX_RETRIES)
- {
- ++tries;
- gconf_detach_config_server ();
- goto RETRY;
- }
- }
-
- d(g_print ("got db reply, %p, %s\n", reply, error.message));
-
if (gconf_handle_dbus_exception (reply, &error, err))
- {
- if (reply)
- dbus_message_unref (reply);
- return FALSE;
- }
+ return FALSE;
dbus_message_get_args (reply,
NULL,
DBUS_TYPE_STRING, &db,
DBUS_TYPE_INVALID);
-
- d(g_print ("db = %s\n", db));
-
+
+ dbus_message_unref (reply);
+
if (db == NULL)
{
if (err)
- *err = gconf_error_new(GCONF_ERROR_BAD_ADDRESS,
- _("Server couldn't resolve the address `%s'"),
- conf->address ? conf->address : "default");
+ *err = gconf_error_new (GCONF_ERROR_BAD_ADDRESS,
+ _("Server couldn't resolve the address `%s'"),
+ conf->address ? conf->address : "default");
return FALSE;
}
gconf_engine_set_database (conf, db);
- /* Add the per-engine notify filter. */
- if (!conf->has_filter)
- {
- dbus_connection_add_filter (glob_conn, gconf_dbus_notify_filter,
- conf, NULL);
- conf->has_filter = TRUE;
- }
-
+ dbus_free (db);
+
return TRUE;
}
@@ -512,14 +565,14 @@ gconf_engine_get_database (GConfEngine *conf,
gboolean start_if_not_found,
GError **err)
{
- if (!gconf_engine_connect (conf, start_if_not_found, err))
+ if (!ensure_database (conf, start_if_not_found, err))
return NULL;
else
return conf->database;
}
static gboolean
-gconf_engine_is_local(GConfEngine* conf)
+gconf_engine_is_local (GConfEngine* conf)
{
return conf->is_local;
}
@@ -552,7 +605,7 @@ unregister_engine (GConfEngine *conf)
}
static GConfEngine *
-lookup_engine (const gchar *address)
+lookup_engine_by_address (const gchar *address)
{
if (engines_by_address)
return g_hash_table_lookup (engines_by_address, address);
@@ -676,20 +729,20 @@ GConfEngine*
gconf_engine_get_local (const gchar* address,
GError** err)
{
- GConfEngine* conf;
- GConfSource* source;
+ GConfEngine *conf;
+ GConfSource *source;
- g_return_val_if_fail(address != NULL, NULL);
- g_return_val_if_fail(err == NULL || *err == NULL, NULL);
+ g_return_val_if_fail (address != NULL, NULL);
+ g_return_val_if_fail (err == NULL || *err == NULL, NULL);
- source = gconf_resolve_address(address, err);
+ source = gconf_resolve_address (address, err);
if (source == NULL)
return NULL;
- conf = gconf_engine_blank(FALSE);
+ conf = gconf_engine_blank (FALSE);
- conf->local_sources = gconf_sources_new_from_source(source);
+ conf->local_sources = gconf_sources_new_from_source (source);
g_assert (gconf_engine_is_local (conf));
@@ -708,18 +761,9 @@ gconf_engine_get_default (void)
{
conf = gconf_engine_blank (TRUE);
- if (!ensure_dbus_connection ())
- return NULL;
-
conf->is_default = TRUE;
default_engine = conf;
-
- /* Ignore errors, we never return a NULL default database, and
- * since we aren't starting if it isn't found, we'll probably
- * get errors half the time anyway.
- */
- gconf_engine_connect (conf, FALSE, NULL);
}
else
conf->refcount += 1;
@@ -732,21 +776,21 @@ gconf_engine_get_for_address (const gchar* address, GError** err)
{
GConfEngine* conf;
- conf = lookup_engine (address);
+ conf = lookup_engine_by_address (address);
if (conf == NULL)
{
- conf = gconf_engine_blank(TRUE);
+ conf = gconf_engine_blank (TRUE);
conf->is_default = FALSE;
conf->address = g_strdup (address);
- if (!gconf_engine_connect (conf, TRUE, err))
+ if (!ensure_database (conf, TRUE, err))
{
gconf_engine_unref (conf);
return NULL;
}
-
+
register_engine (conf);
}
else
@@ -756,28 +800,28 @@ gconf_engine_get_for_address (const gchar* address, GError** err)
}
void
-gconf_engine_ref(GConfEngine* conf)
+gconf_engine_ref (GConfEngine* conf)
{
- g_return_if_fail(conf != NULL);
- g_return_if_fail(conf->refcount > 0);
+ g_return_if_fail (conf != NULL);
+ g_return_if_fail (conf->refcount > 0);
conf->refcount += 1;
}
void
-gconf_engine_unref(GConfEngine* conf)
+gconf_engine_unref (GConfEngine* conf)
{
- g_return_if_fail(conf != NULL);
- g_return_if_fail(conf->refcount > 0);
+ g_return_if_fail (conf != NULL);
+ g_return_if_fail (conf->refcount > 0);
conf->refcount -= 1;
if (conf->refcount == 0)
{
- if (gconf_engine_is_local(conf))
+ if (gconf_engine_is_local (conf))
{
if (conf->local_sources != NULL)
- gconf_sources_free(conf->local_sources);
+ gconf_sources_free (conf->local_sources);
}
else
{
@@ -786,12 +830,6 @@ gconf_engine_unref(GConfEngine* conf)
/* FIXME: remove notify_ids from hash when we have
add/remove_notify. */
- if (conf->has_filter)
- {
- dbus_connection_remove_filter (glob_conn, gconf_dbus_message_filter, conf);
- conf->has_filter = FALSE;
- }
-
if (conf->dnotify)
{
(* conf->dnotify) (conf->user_data);
@@ -838,6 +876,46 @@ gconf_engine_get_user_data (GConfEngine *engine)
return engine->user_data;
}
+static gboolean
+send_notify_add (GConfEngine *conf,
+ GConfCnxn *cnxn,
+ GError **err)
+{
+ const gchar *db;
+ DBusMessage *message, *reply;
+ DBusError error;
+
+ db = gconf_engine_get_database (conf, TRUE, err);
+
+ if (db == NULL)
+ {
+ g_return_val_if_fail(err == NULL || *err != NULL, 0);
+
+ return FALSE;
+ }
+
+ message = dbus_message_new_method_call (GCONF_DBUS_SERVICE,
+ db,
+ GCONF_DBUS_DATABASE_INTERFACE,
+ GCONF_DBUS_DATABASE_ADD_NOTIFY);
+
+ dbus_message_append_args (message,
+ DBUS_TYPE_STRING, cnxn->namespace_section,
+ DBUS_TYPE_INVALID);
+
+ dbus_error_init (&error);
+ reply = dbus_connection_send_with_reply_and_block (global_conn,
+ message, -1, &error);
+ dbus_message_unref (message);
+
+ if (gconf_handle_dbus_exception (reply, &error, err))
+ return FALSE;
+
+ dbus_message_unref (reply);
+
+ return TRUE;
+}
+
guint
gconf_engine_notify_add (GConfEngine* conf,
const gchar* namespace_section,
@@ -845,7 +923,6 @@ gconf_engine_notify_add (GConfEngine* conf,
gpointer user_data,
GError** err)
{
- const gchar *db;
GConfCnxn *cnxn;
g_return_val_if_fail (!gconf_engine_is_local (conf), 0);
@@ -861,21 +938,14 @@ gconf_engine_notify_add (GConfEngine* conf,
return 0;
}
- db = gconf_engine_get_database (conf, TRUE, err);
+ cnxn = gconf_cnxn_new (conf, namespace_section, func, user_data);
+ gconf_cnxn_insert (conf, namespace_section, cnxn->client_id, cnxn);
- if (db == NULL)
+ if (!send_notify_add (conf, cnxn, err))
{
- g_return_val_if_fail(err == NULL || *err != NULL, 0);
-
+ gconf_cnxn_remove (conf, cnxn);
return 0;
}
-
- /*add_listener (conf, db, namespace_section, err);*/
-
- cnxn = gconf_cnxn_new (conf, namespace_section, func, user_data);
- gconf_cnxn_insert (conf, namespace_section, cnxn->client_id, cnxn);
-
- d(g_print ("notify_add, id = %d\n", cnxn->client_id));
return cnxn->client_id;
}
@@ -886,12 +956,24 @@ gconf_engine_notify_remove (GConfEngine* conf,
{
GConfCnxn *cnxn;
const gchar *db;
+ gchar *namespace_section = NULL;
+ DBusMessage *message, *reply;
+ DBusError error;
CHECK_OWNER_USE (conf);
if (gconf_engine_is_local(conf))
return;
+ cnxn = gconf_cnxn_lookup_id (conf, client_id);
+ if (cnxn != NULL)
+ {
+ namespace_section = g_strdup (cnxn->namespace_section);
+ gconf_cnxn_remove (conf, cnxn);
+ }
+
+ g_return_if_fail (cnxn != NULL);
+
db = gconf_engine_get_database (conf, TRUE, NULL);
if (db == NULL)
@@ -899,12 +981,25 @@ gconf_engine_notify_remove (GConfEngine* conf,
d(g_print ("notify_remove, id = %d\n", client_id));
- /*remove_listener (conf, db, namespace_section, err);*/
+ message = dbus_message_new_method_call (GCONF_DBUS_SERVICE,
+ db,
+ GCONF_DBUS_DATABASE_INTERFACE,
+ GCONF_DBUS_DATABASE_REMOVE_NOTIFY);
+
+ dbus_message_append_args (message,
+ DBUS_TYPE_STRING, namespace_section,
+ DBUS_TYPE_INVALID);
- cnxn = gconf_cnxn_lookup_id (conf, client_id);
- g_return_if_fail (cnxn != NULL);
- if (cnxn != NULL)
- gconf_cnxn_remove (conf, cnxn);
+ dbus_error_init (&error);
+ reply = dbus_connection_send_with_reply_and_block (global_conn, message, -1, &error);
+ dbus_message_unref (message);
+
+ if (dbus_error_is_set (&error))
+ dbus_error_free (&error);
+
+ g_free (namespace_section);
+
+ dbus_message_unref (reply);
}
GConfValue *
@@ -919,12 +1014,12 @@ gconf_engine_get_fuller (GConfEngine *conf,
{
GConfValue* val;
const gchar *db;
- gint tries = 0;
gboolean is_default = FALSE;
gboolean is_writable = TRUE;
gchar *schema_name = NULL;
DBusMessage *message, *reply;
DBusError error;
+ DBusMessageIter iter;
gboolean success;
g_return_val_if_fail(conf != NULL, NULL);
@@ -933,23 +1028,23 @@ gconf_engine_get_fuller (GConfEngine *conf,
CHECK_OWNER_USE (conf);
- if (!gconf_key_check(key, err))
+ if (!gconf_key_check (key, err))
return NULL;
- if (gconf_engine_is_local(conf))
+ if (gconf_engine_is_local (conf))
{
- gchar** locale_list;
+ gchar **locale_list;
- locale_list = gconf_split_locale(locale);
+ locale_list = gconf_split_locale (locale);
- val = gconf_sources_query_value(conf->local_sources,
- key,
- (const gchar**)locale_list,
- use_schema_default,
- &is_default,
- &is_writable,
- schema_name_p ? &schema_name : NULL,
- err);
+ val = gconf_sources_query_value (conf->local_sources,
+ key,
+ (const gchar**)locale_list,
+ use_schema_default,
+ &is_default,
+ &is_writable,
+ schema_name_p ? &schema_name : NULL,
+ err);
if (locale_list != NULL)
g_strfreev(locale_list);
@@ -968,16 +1063,13 @@ gconf_engine_get_fuller (GConfEngine *conf,
return val;
}
- g_assert(!gconf_engine_is_local(conf));
+ g_assert (!gconf_engine_is_local (conf));
- RETRY:
-
db = gconf_engine_get_database (conf, TRUE, err);
if (db == NULL)
{
g_return_val_if_fail(err == NULL || *err != NULL, NULL);
-
return NULL;
}
@@ -996,72 +1088,52 @@ gconf_engine_get_fuller (GConfEngine *conf,
DBUS_TYPE_INVALID);
dbus_error_init (&error);
- reply = dbus_connection_send_with_reply_and_block (glob_conn, message, -1, &error);
+ reply = dbus_connection_send_with_reply_and_block (global_conn, message, -1, &error);
dbus_message_unref (message);
- if (gconf_server_broken (reply))
- if (tries < MAX_RETRIES)
- {
- ++tries;
- if (reply)
- dbus_message_unref (reply);
- dbus_error_free (&error);
- gconf_engine_detach (conf);
- goto RETRY;
- }
-
if (gconf_handle_dbus_exception (reply, &error, err))
+ return NULL;
+
+ dbus_message_iter_init (reply, &iter);
+ success = gconf_dbus_get_entry_values_from_message_iter (&iter,
+ NULL,
+ &val,
+ &is_default,
+ &is_writable,
+ &schema_name);
+
+ dbus_message_unref (reply);
+
+ if (!success)
{
- if (reply)
- dbus_message_unref (reply);
+ if (err)
+ g_set_error (err, GCONF_ERROR,
+ GCONF_ERROR_FAILED,
+ _("Couldn't get value"));
+
+ g_free (schema_name);
+
return NULL;
}
- else
+
+ if (is_default_p)
+ *is_default_p = !!is_default;
+
+ if (is_writable_p)
+ *is_writable_p = !!is_writable;
+
+ if (schema_name && schema_name[0] != '/')
{
- DBusMessageIter iter;
-
- dbus_message_iter_init (reply, &iter);
-
- success = gconf_dbus_get_entry_values_from_message_iter (&iter,
- NULL,
- &val,
- &is_default,
- &is_writable,
- &schema_name);
-
- dbus_message_unref (reply);
-
- if (!success)
- {
- if (err)
- g_set_error (err, GCONF_ERROR,
- GCONF_ERROR_FAILED,
- _("Couldn't get value"));
-
- g_free (schema_name);
-
- return NULL;
- }
-
- if (is_default_p)
- *is_default_p = !!is_default;
-
- if (is_writable_p)
- *is_writable_p = !!is_writable;
-
- if (schema_name && schema_name[0] != '/')
- {
- g_free (schema_name);
- schema_name = NULL;
- }
-
- if (schema_name_p)
- *schema_name_p = schema_name;
- else
- g_free (schema_name);
-
- return val;
+ g_free (schema_name);
+ schema_name = NULL;
}
+
+ if (schema_name_p)
+ *schema_name_p = schema_name;
+ else
+ g_free (schema_name);
+
+ return val;
}
GConfValue *
@@ -1105,12 +1177,12 @@ gconf_engine_get_entry (GConfEngine* conf,
return NULL;
}
- entry = gconf_entry_new_nocopy (g_strdup (key),
- val);
+ entry = gconf_entry_new_nocopy (g_strdup (key), val);
gconf_entry_set_is_default (entry, is_default);
gconf_entry_set_is_writable (entry, is_writable);
gconf_entry_set_schema_name (entry, schema_name);
+
g_free (schema_name);
return entry;
@@ -1153,7 +1225,6 @@ gconf_engine_set (GConfEngine* conf, const gchar* key,
const GConfValue* value, GError** err)
{
const gchar *db;
- gint tries = 0;
DBusMessage *message, *reply;
DBusError error;
@@ -1169,17 +1240,17 @@ gconf_engine_set (GConfEngine* conf, const gchar* key,
CHECK_OWNER_USE (conf);
- if (!gconf_key_check(key, err))
+ if (!gconf_key_check (key, err))
return FALSE;
if (!gconf_value_validate (value, err))
return FALSE;
- if (gconf_engine_is_local(conf))
+ if (gconf_engine_is_local (conf))
{
GError* error = NULL;
- gconf_sources_set_value(conf->local_sources, key, value, &error);
+ gconf_sources_set_value (conf->local_sources, key, value, &error);
if (error != NULL)
{
@@ -1187,7 +1258,7 @@ gconf_engine_set (GConfEngine* conf, const gchar* key,
*err = error;
else
{
- g_error_free(error);
+ g_error_free (error);
}
return FALSE;
}
@@ -1195,9 +1266,7 @@ gconf_engine_set (GConfEngine* conf, const gchar* key,
return TRUE;
}
- g_assert(!gconf_engine_is_local(conf));
-
- RETRY:
+ g_assert (!gconf_engine_is_local (conf));
db = gconf_engine_get_database (conf, TRUE, err);
@@ -1220,26 +1289,13 @@ gconf_engine_set (GConfEngine* conf, const gchar* key,
gconf_dbus_message_append_gconf_value (message, value);
dbus_error_init (&error);
- reply = dbus_connection_send_with_reply_and_block (glob_conn, message, -1, &error);
+ reply = dbus_connection_send_with_reply_and_block (global_conn, message, -1, &error);
dbus_message_unref (message);
- if (gconf_server_broken (reply))
- if (tries < MAX_RETRIES)
- {
- ++tries;
- if (reply)
- dbus_message_unref (reply);
- gconf_engine_detach (conf);
- goto RETRY;
- }
-
if (gconf_handle_dbus_exception (reply, &error, err))
- {
- if (reply)
- dbus_message_unref (reply);
- return FALSE;
- }
- g_return_val_if_fail(err == NULL || *err == NULL, FALSE);
+ return FALSE;
+
+ g_return_val_if_fail (err == NULL || *err == NULL, FALSE);
dbus_message_unref (reply);
@@ -1250,7 +1306,6 @@ gboolean
gconf_engine_unset (GConfEngine* conf, const gchar* key, GError** err)
{
const gchar *db;
- gint tries = 0;
DBusMessage *message, *reply;
DBusError error;
@@ -1260,14 +1315,14 @@ gconf_engine_unset (GConfEngine* conf, const gchar* key, GError** err)
CHECK_OWNER_USE (conf);
- if (!gconf_key_check(key, err))
+ if (!gconf_key_check (key, err))
return FALSE;
- if (gconf_engine_is_local(conf))
+ if (gconf_engine_is_local (conf))
{
GError* error = NULL;
- gconf_sources_unset_value(conf->local_sources, key, NULL, &error);
+ gconf_sources_unset_value (conf->local_sources, key, NULL, &error);
if (error != NULL)
{
@@ -1275,7 +1330,7 @@ gconf_engine_unset (GConfEngine* conf, const gchar* key, GError** err)
*err = error;
else
{
- g_error_free(error);
+ g_error_free (error);
}
return FALSE;
}
@@ -1285,8 +1340,6 @@ gconf_engine_unset (GConfEngine* conf, const gchar* key, GError** err)
g_assert(!gconf_engine_is_local(conf));
- RETRY:
-
db = gconf_engine_get_database (conf, TRUE, err);
if (db == NULL)
@@ -1307,25 +1360,12 @@ gconf_engine_unset (GConfEngine* conf, const gchar* key, GError** err)
DBUS_TYPE_INVALID);
dbus_error_init (&error);
- reply = dbus_connection_send_with_reply_and_block (glob_conn, message, -1, &error);
+ reply = dbus_connection_send_with_reply_and_block (global_conn, message, -1, &error);
dbus_message_unref (message);
- if (gconf_server_broken (reply))
- {
- if (tries < MAX_RETRIES)
- {
- ++tries;
- gconf_engine_detach(conf);
- goto RETRY;
- }
- }
-
if (gconf_handle_dbus_exception (reply, &error, err))
- {
- if (reply)
- dbus_message_unref (reply);
- return FALSE;
- }
+ return FALSE;
+
g_return_val_if_fail (err == NULL || *err == NULL, FALSE);
dbus_message_unref (reply);
@@ -1353,7 +1393,6 @@ gconf_engine_recursive_unset (GConfEngine *conf,
GError **err)
{
const gchar *db;
- gint tries = 0;
DBusMessage *message, *reply;
DBusError error;
guint dbus_flags;
@@ -1394,8 +1433,6 @@ gconf_engine_recursive_unset (GConfEngine *conf,
if (flags & GCONF_UNSET_INCLUDING_SCHEMA_NAMES)
dbus_flags |= GCONF_DBUS_UNSET_INCLUDING_SCHEMA_NAMES;
- RETRY:
-
db = gconf_engine_get_database (conf, TRUE, err);
if (db == NULL)
@@ -1417,25 +1454,12 @@ gconf_engine_recursive_unset (GConfEngine *conf,
DBUS_TYPE_INVALID);
dbus_error_init (&error);
- reply = dbus_connection_send_with_reply_and_block (glob_conn, message, -1, &error);
+ reply = dbus_connection_send_with_reply_and_block (global_conn, message, -1, &error);
dbus_message_unref (message);
- if (gconf_server_broken (reply))
- {
- if (tries < MAX_RETRIES)
- {
- ++tries;
- gconf_engine_detach(conf);
- goto RETRY;
- }
- }
+ if (gconf_handle_dbus_exception (reply, &error, err))
+ return FALSE;
- if (gconf_handle_dbus_exception (reply, &error, err))
- {
- if (reply)
- dbus_message_unref (reply);
- return FALSE;
- }
g_return_val_if_fail (err == NULL || *err == NULL, FALSE);
dbus_message_unref (reply);
@@ -1448,7 +1472,6 @@ gconf_engine_associate_schema (GConfEngine* conf, const gchar* key,
const gchar* schema_key, GError** err)
{
const gchar *db;
- gint tries = 0;
DBusMessage *message, *reply;
DBusError error;
@@ -1484,8 +1507,6 @@ gconf_engine_associate_schema (GConfEngine* conf, const gchar* key,
g_assert (!gconf_engine_is_local (conf));
- RETRY:
-
db = gconf_engine_get_database (conf, TRUE, err);
if (db == NULL)
@@ -1507,25 +1528,12 @@ gconf_engine_associate_schema (GConfEngine* conf, const gchar* key,
DBUS_TYPE_INVALID);
dbus_error_init (&error);
- reply = dbus_connection_send_with_reply_and_block (glob_conn, message, -1, &error);
+ reply = dbus_connection_send_with_reply_and_block (global_conn, message, -1, &error);
dbus_message_unref (message);
- if (gconf_server_broken (reply))
- {
- if (tries < MAX_RETRIES)
- {
- ++tries;
- gconf_engine_detach(conf);
- goto RETRY;
- }
- }
-
- if (gconf_handle_dbus_exception (reply, &error, err))
- {
- if (reply)
- dbus_message_unref (reply);
- return FALSE;
- }
+ if (gconf_handle_dbus_exception (reply, &error, err))
+ return FALSE;
+
g_return_val_if_fail (err == NULL || *err == NULL, FALSE);
dbus_message_unref (reply);
@@ -1537,6 +1545,7 @@ static void
qualify_entries (GSList *entries, const char *dir)
{
GSList *tmp = entries;
+
while (tmp != NULL)
{
GConfEntry *entry = tmp->data;
@@ -1556,7 +1565,6 @@ gconf_engine_all_entries (GConfEngine* conf, const gchar* dir, GError** err)
{
GSList* entries = NULL;
const gchar *db;
- gint tries = 0;
DBusMessage *message, *reply;
DBusError error;
DBusMessageIter iter;
@@ -1573,7 +1581,6 @@ gconf_engine_all_entries (GConfEngine* conf, const gchar* dir, GError** err)
if (!gconf_key_check(dir, err))
return NULL;
-
if (gconf_engine_is_local(conf))
{
GError* error = NULL;
@@ -1611,8 +1618,6 @@ gconf_engine_all_entries (GConfEngine* conf, const gchar* dir, GError** err)
g_assert(!gconf_engine_is_local(conf));
- RETRY:
-
db = gconf_engine_get_database (conf, TRUE, err);
if (db == NULL)
@@ -1633,25 +1638,12 @@ gconf_engine_all_entries (GConfEngine* conf, const gchar* dir, GError** err)
DBUS_TYPE_INVALID);
dbus_error_init (&error);
- reply = dbus_connection_send_with_reply_and_block (glob_conn, message, -1, &error);
+ reply = dbus_connection_send_with_reply_and_block (global_conn, message, -1, &error);
dbus_message_unref (message);
- if (gconf_server_broken (reply))
- {
- if (tries < MAX_RETRIES)
- {
- ++tries;
- gconf_engine_detach (conf);
- goto RETRY;
- }
- }
-
if (gconf_handle_dbus_exception (reply, &error, err))
- {
- if (reply)
- dbus_message_unref (reply);
- return FALSE;
- }
+ return FALSE;
+
g_return_val_if_fail (err == NULL || *err == NULL, FALSE);
dbus_message_iter_init (reply, &iter);
@@ -1675,7 +1667,7 @@ gconf_engine_all_entries (GConfEngine* conf, const gchar* dir, GError** err)
gconf_entry_set_is_default (entry, is_default);
gconf_entry_set_is_writable (entry, is_writable);
- /* empty string means no schema name */
+ /* Empty string means no schema name. */
if (*schema_name != '\0')
gconf_entry_set_schema_name (entry, schema_name);
@@ -1716,7 +1708,6 @@ gconf_engine_all_dirs(GConfEngine* conf, const gchar* dir, GError** err)
{
GSList* subdirs = NULL;
const gchar *db;
- gint tries = 0;
DBusMessage *message, *reply;
DBusError error;
DBusMessageIter iter;
@@ -1760,14 +1751,12 @@ gconf_engine_all_dirs(GConfEngine* conf, const gchar* dir, GError** err)
}
g_assert(!gconf_engine_is_local(conf));
-
- RETRY:
-
+
db = gconf_engine_get_database (conf, TRUE, err);
-
+
if (db == NULL)
{
- g_return_val_if_fail(((err == NULL) || (*err && ((*err)->code == GCONF_ERROR_NO_SERVER))), NULL);
+ g_return_val_if_fail (err == NULL || *err != NULL, NULL);
return NULL;
}
@@ -1782,25 +1771,12 @@ gconf_engine_all_dirs(GConfEngine* conf, const gchar* dir, GError** err)
DBUS_TYPE_INVALID);
dbus_error_init (&error);
- reply = dbus_connection_send_with_reply_and_block (glob_conn, message, -1, &error);
+ reply = dbus_connection_send_with_reply_and_block (global_conn, message, -1, &error);
dbus_message_unref (message);
- if (gconf_server_broken (reply))
- {
- if (tries < MAX_RETRIES)
- {
- ++tries;
- gconf_engine_detach (conf);
- goto RETRY;
- }
- }
-
if (gconf_handle_dbus_exception (reply, &error, err))
- {
- if (reply)
- dbus_message_unref (reply);
- return FALSE;
- }
+ return FALSE;
+
g_return_val_if_fail (err == NULL || *err == NULL, FALSE);
dbus_message_iter_init (reply, &iter);
@@ -1926,7 +1902,6 @@ gconf_engine_dir_exists (GConfEngine *conf, const gchar *dir, GError** err)
{
const gchar *db;
dbus_bool_t exists;
- gint tries = 0;
DBusMessage *message, *reply;
DBusError error;
@@ -1948,8 +1923,6 @@ gconf_engine_dir_exists (GConfEngine *conf, const gchar *dir, GError** err)
g_assert(!gconf_engine_is_local(conf));
- RETRY:
-
db = gconf_engine_get_database(conf, TRUE, err);
if (db == NULL)
@@ -1969,25 +1942,12 @@ gconf_engine_dir_exists (GConfEngine *conf, const gchar *dir, GError** err)
DBUS_TYPE_INVALID);
dbus_error_init (&error);
- reply = dbus_connection_send_with_reply_and_block (glob_conn, message, -1, &error);
+ reply = dbus_connection_send_with_reply_and_block (global_conn, message, -1, &error);
dbus_message_unref (message);
-
- if (gconf_server_broken (reply))
- {
- if (tries < MAX_RETRIES)
- {
- ++tries;
- gconf_engine_detach (conf);
- goto RETRY;
- }
- }
-
+
if (gconf_handle_dbus_exception (reply, &error, err))
- {
- if (reply)
- dbus_message_unref (reply);
- return FALSE;
- }
+ return FALSE;
+
g_return_val_if_fail (err == NULL || *err == NULL, FALSE);
dbus_message_get_args (reply,
@@ -2020,242 +1980,156 @@ gconf_engine_remove_dir (GConfEngine* conf,
}
}
-/* Temporary solution until we have add/remove notify on the server. So we have
- * one global (per connection) filter function for handling ServiceDeleted, etc,
- * and one per notify added so handle notification.
- */
-static DBusHandlerResult
-gconf_dbus_message_filter (DBusConnection *dbus_conn,
- DBusMessage *message,
- gpointer user_data)
+static void
+cnxn_get_all_func (gpointer key,
+ gpointer value,
+ gpointer user_data)
{
- d(g_print ("message to filter: %s, from %s\n",
- dbus_message_get_member (message),
- dbus_message_get_sender (message)));
+ GList **list = user_data;
- if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_SIGNAL)
- return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+ *list = g_list_prepend (*list, value);
+}
+
+static void
+engines_by_db_get_all_func (gpointer key,
+ gpointer value,
+ gpointer user_data)
+{
+ GList **list = user_data;
+
+ *list = g_list_prepend (*list, value);
+}
+
+static void
+reinitialize_databases (void)
+{
+ GList *engines = NULL, *engine;
+ GList *cnxns, *l;
+ GConfEngine *conf;
+
+ if (engines_by_db)
+ g_hash_table_foreach (engines_by_db,
+ engines_by_db_get_all_func,
+ &engines);
- if (dbus_message_is_signal (message,
- DBUS_INTERFACE_ORG_FREEDESKTOP_LOCAL,
- "Disconnected"))
+ /* Reset databases. */
+ for (engine = engines; engine; engine = engine->next)
{
- /* FIXME: We never seem to get this signal. */
-
- dbus_connection_unref (glob_conn);
- glob_conn = NULL;
- service_running = FALSE;
+ conf = engine->data;
- d(g_print ("****** Disconnected!\n"));
- return DBUS_HANDLER_RESULT_HANDLED;
+ g_hash_table_remove (engines_by_db, conf->database);
+ ensure_database (conf, FALSE, NULL);
}
- if (dbus_message_is_signal (message,
- DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
- "ServiceDeleted"))
+ /* Re-add notifications. */
+ for (engine = engines; engine; engine = engine->next)
{
- DBusMessageIter iter;
- gchar *service;
-
- dbus_message_iter_init (message, &iter);
- service = dbus_message_iter_get_string (&iter);
-
- if (strcmp (service, GCONF_DBUS_SERVICE) == 0)
- {
- service_running = FALSE;
+ conf = engine->data;
- /* FIXME: Re-add notifications when we have add/remove notify on the
- * server.
- */
- d(g_print ("* GConf Service deleted\n"));
-
- dbus_free (service);
+ cnxns = NULL;
+ g_hash_table_foreach (conf->notify_ids,
+ cnxn_get_all_func,
+ &cnxns);
+
+ for (l = cnxns; l; l = l->next)
+ {
+ GConfCnxn *cnxn = l->data;
- return DBUS_HANDLER_RESULT_HANDLED;
+ send_notify_add (conf, cnxn, NULL);
}
-
- dbus_free (service);
+
+ g_list_free (cnxns);
}
- return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+ g_list_free (engines);
}
static DBusHandlerResult
-gconf_dbus_notify_filter (DBusConnection *dbus_conn,
- DBusMessage *message,
- gpointer user_data)
+gconf_dbus_message_filter (DBusConnection *dbus_conn,
+ DBusMessage *message,
+ gpointer user_data)
{
- GConfEngine *conf = user_data;
+ DBusMessageIter iter;
+ char *service;
- d(g_print ("notify to filter: %s, from %s\n",
- dbus_message_get_member (message),
- dbus_message_get_sender (message)));
-
- if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_SIGNAL)
- return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+#if 0
+ d(g_print ("Message: %s, from %s\n",
+ dbus_message_get_member (message),
+ dbus_message_get_sender (message)));
+#endif
- if (dbus_message_is_signal (message,
- GCONF_DBUS_DATABASE_INTERFACE,
- "Notify"))
+ if (dbus_message_is_method_call (message,
+ GCONF_DBUS_CLIENT_INTERFACE,
+ "Notify"))
{
- if (conf)
- return handle_notify (dbus_conn, message, conf);
+ return handle_notify (dbus_conn, message, NULL);
}
-
- return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
-}
-
-static gboolean
-ensure_dbus_connection (void)
-{
- DBusError error;
- GError *gerror = NULL;
-
- if (glob_conn)
- return TRUE;
-
- dbus_error_init (&error);
-
- glob_conn = dbus_bus_get_with_g_main (DBUS_BUS_SESSION, &gerror);
-
- d(g_print ("ensure, got connection %p (%d)\n", glob_conn, getpid()));
-
- if (!glob_conn)
+ else if (dbus_message_is_signal (message,
+ DBUS_INTERFACE_ORG_FREEDESKTOP_LOCAL,
+ "Disconnected"))
{
- g_warning ("Failed to connect to the D-BUS bus daemon: %s\n.",
- gerror->message);
- return FALSE;
- }
-
- dbus_bus_add_match (glob_conn, BUS_RULE, NULL);
- dbus_bus_add_match (glob_conn, NOTIFY_RULE, NULL);
-
- dbus_connection_add_filter (glob_conn, gconf_dbus_message_filter,
- NULL, NULL);
-
- return TRUE;
-}
-
-static gboolean
-gconf_activate_service (gboolean start_if_not_found,
- GError **err)
-{
- DBusError error;
- DBusMessage *message, *reply;
-
- dbus_error_init (&error);
+ /* Note: This is a terminal situation. We can't live without the bus and
+ * we don't support starting it after the client. We could add support for
+ * that though.
+ */
- if (glob_conn)
+ dbus_connection_unref (global_conn);
+ global_conn = NULL;
+ service_running = FALSE;
+
+ d(g_print ("****** Disconnected!\n"));
+ return DBUS_HANDLER_RESULT_HANDLED;
+ }
+ else if (dbus_message_is_signal (message,
+ DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
+ "ServiceDeleted"))
{
- if (dbus_bus_service_exists (glob_conn, GCONF_DBUS_SERVICE, &error))
- {
- d(g_print ("* activate_service, already active\n"));
- return TRUE;
- }
+ dbus_message_iter_init (message, &iter);
+ service = dbus_message_iter_get_string (&iter);
- if (dbus_error_is_set (&error))
+ if (strcmp (service, GCONF_DBUS_SERVICE) == 0)
{
- g_set_error (err, GCONF_ERROR,
- GCONF_ERROR_NO_SERVER,
- _("Failed to activate configuration server: %s\n"),
- error.message);
-
- dbus_error_free (&error);
- return FALSE;
+ /* GConfd is gone, set the state so we can detect that we're down. */
+ service_running = FALSE;
+ needs_reconnect = TRUE;
+
+ d(g_print ("* GConf Service deleted\n"));
}
+
+ dbus_free (service);
+
+ return DBUS_HANDLER_RESULT_HANDLED;
}
- else
+ else if (dbus_message_is_signal (message,
+ DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
+ "ServiceCreated"))
{
- d(g_print ("connection = NULL in activate_service (%d) %s\n", getpid(), g_get_prgname()));
- }
+ dbus_message_iter_init (message, &iter);
+ service = dbus_message_iter_get_string (&iter);
- if (start_if_not_found)
- {
- d(g_print ("* activate_service, activating\n"));
-
- message = dbus_message_new_method_call (DBUS_SERVICE_ORG_FREEDESKTOP_DBUS,
- DBUS_PATH_ORG_FREEDESKTOP_DBUS,
- DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
- "ActivateService");
-
- dbus_message_append_args (message,
- DBUS_TYPE_STRING, GCONF_DBUS_SERVICE,
- DBUS_TYPE_UINT32, 0,
- 0);
-
- reply = dbus_connection_send_with_reply_and_block (glob_conn,
- message, -1, &error);
-
- dbus_message_unref (message);
-
- if (reply == NULL)
+ if (strcmp (service, GCONF_DBUS_SERVICE) == 0)
{
- const gchar *msg;
-
- if (dbus_error_is_set (&error))
- msg = error.message;
- else
- msg = _("Unknown error");
-
- g_set_error (err, GCONF_ERROR,
- GCONF_ERROR_NO_SERVER,
- _("Failed to activate configuration server: %s\n"),
- msg);
+ /* GConfd is back. */
+ service_running = TRUE;
- if (dbus_error_is_set (&error))
- dbus_error_free (&error);
+ if (needs_reconnect)
+ {
+ needs_reconnect = FALSE;
+ reinitialize_databases ();
+ }
- return FALSE;
+ d(g_print ("* Gconf Service created\n"));
}
- if (dbus_message_get_type (reply) == DBUS_MESSAGE_TYPE_ERROR)
- {
- gchar *error_message;
-
- dbus_message_get_args (reply, NULL,
- DBUS_TYPE_STRING, &error_message,
- 0);
- g_set_error (err, GCONF_ERROR,
- GCONF_ERROR_NO_SERVER,
- _("Failed to activate configuration server: %s\n"),
- error_message);
- dbus_free (error_message);
- dbus_message_unref (reply);
+ dbus_free (service);
- return FALSE;
- }
- else
- {
- if (dbus_bus_service_exists (glob_conn, GCONF_DBUS_SERVICE, NULL))
- {
- d(g_print ("Seems to work, got service\n"));
- }
- dbus_message_unref (reply);
- return TRUE;
- }
+ return DBUS_HANDLER_RESULT_HANDLED;
}
+
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
- return FALSE;
-}
-
-/* All errors set in here should be GCONF_ERROR_NO_SERVER; should
- only set errors if start_if_not_found is TRUE */
-static const gchar *
-gconf_get_config_server (gboolean start_if_not_found, GError** err)
-{
- g_return_val_if_fail(err == NULL || *err == NULL, NULL);
-
- if (service_running)
- return GCONF_DBUS_SERVER_OBJECT;
-
- if (!gconf_activate_service (start_if_not_found, err))
- return NULL;
-
- service_running = TRUE;
-
- return GCONF_DBUS_SERVER_OBJECT;
-}
-
+/* FIXME: What should this do in the D-BUS case? */
static void
gconf_detach_config_server(void)
{
@@ -2284,80 +2158,90 @@ gconf_debug_shutdown (void)
static DBusHandlerResult
handle_notify (DBusConnection *connection,
DBusMessage *message,
- GConfEngine *conf)
+ GConfEngine *conf2)
{
+ GConfEngine *conf;
gchar *key, *schema_name;
gboolean is_default, is_writable;
DBusMessageIter iter;
GConfValue *value;
GConfEntry* entry;
- gchar *dir, *sep;
GList *list, *l;
gboolean match = FALSE;
+ gchar *namespace_section, *db;
- g_return_val_if_fail (conf != NULL, DBUS_HANDLER_RESULT_NOT_YET_HANDLED);
-
dbus_message_iter_init (message, &iter);
+ db = dbus_message_iter_get_string (&iter);
+
+ if (!dbus_message_iter_next (&iter))
+ {
+ dbus_free (db);
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+ }
+
+ namespace_section = dbus_message_iter_get_string (&iter);
+
+ if (!dbus_message_iter_next (&iter))
+ {
+ dbus_free (db);
+ dbus_free (namespace_section);
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+ }
+
+ conf = lookup_engine_by_database (db);
+
+ g_return_val_if_fail (conf != NULL, DBUS_HANDLER_RESULT_NOT_YET_HANDLED);
+ if (conf == NULL)
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+ dbus_free (db);
+
if (!gconf_dbus_get_entry_values_from_message_iter (&iter,
&key,
&value,
&is_default,
&is_writable,
&schema_name))
- return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
-
+ {
+ dbus_free (namespace_section);
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+ }
+
if (value == NULL)
{
g_free (key);
g_free (schema_name);
+ dbus_free (namespace_section);
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}
- d(g_print ("Got notify on %s\n", key));
-
- dir = g_strdup (key);
+ d(g_print ("Got notify on %s (%s)\n", key, namespace_section));
- while (1)
+ list = gconf_cnxn_lookup_dir (conf, namespace_section);
+ for (l = list; l; l = l->next)
{
- d(g_print ("try %s\n", dir));
+ GConfCnxn *cnxn = l->data;
- /* All notifications we get here are for the right engine, we just
- * need to go through the list of dirs and emit notification for those
- * entries that match.
- */
+ d(g_print ("match? %s\n", cnxn->namespace_section));
- list = gconf_cnxn_lookup_dir (conf, dir);
- for (l = list; l; l = l->next)
+ if (strcmp (cnxn->namespace_section, namespace_section) == 0)
{
- GConfCnxn *cnxn = l->data;
-
- d(g_print ("match? %s\n", cnxn->namespace_section));
-
- if (strcmp (cnxn->namespace_section, dir) == 0)
- {
- d(g_print ("yay! %s\n", dir));
-
- entry = gconf_entry_new (g_strdup (key), value);
- gconf_cnxn_notify (cnxn, entry);
- gconf_entry_free (entry);
-
- match = TRUE;
- }
+ d(g_print ("yes: %s\n", key));
+
+ entry = gconf_entry_new (g_strdup (key), value);
+ gconf_cnxn_notify (cnxn, entry);
+ gconf_entry_free (entry);
+
+ match = TRUE;
}
-
- sep = strrchr (dir, '/');
- if (sep == dir)
- break;
-
- *sep = '\0';
}
gconf_value_free (value);
- g_free (dir);
g_free (key);
g_free (schema_name);
+ dbus_free (namespace_section);
if (!match)
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
@@ -2373,60 +2257,33 @@ handle_notify (DBusConnection *connection,
void
gconf_shutdown_daemon (GError** err)
{
- const gchar *cs;
DBusMessage *message;
/* Don't want to spawn it if it's already down */
- cs = gconf_get_config_server (FALSE, err);
-
- if (err && *err && (*err)->code == GCONF_ERROR_NO_SERVER)
- {
- /* No server is hardly an error here */
- g_error_free (*err);
- *err = NULL;
- }
-
- if (cs == NULL)
+ if (global_conn == NULL || !service_running)
return;
message = dbus_message_new_method_call (GCONF_DBUS_SERVICE,
- cs,
+ GCONF_DBUS_SERVER_OBJECT,
GCONF_DBUS_SERVER_INTERFACE,
GCONF_DBUS_SERVER_SHUTDOWN);
- dbus_connection_send (glob_conn, message, 0);
- dbus_connection_flush (glob_conn);
+ dbus_connection_send (global_conn, message, 0);
+ dbus_connection_flush (global_conn);
+
+ dbus_message_unref (message);
}
-/* FIXME: Do we really need to ping the dbus service? */
gboolean
gconf_ping_daemon (void)
{
- const gchar *cs;
-
- /* ignore error, since whole point is to see if server is reachable */
- cs = gconf_get_config_server (FALSE, NULL);
-
- if (cs == NULL)
- return FALSE;
- else
- return TRUE;
+ return service_running;
}
gboolean
-gconf_spawn_daemon (GError** err)
+gconf_spawn_daemon (GError **err)
{
- const gchar *cs;
-
- cs = gconf_get_config_server (TRUE, err);
-
- if (cs == NULL)
- {
- g_return_val_if_fail(err == NULL || *err != NULL, FALSE);
- return FALSE; /* Failed to spawn, error should be set */
- }
- else
- return TRUE;
+ return ensure_service (TRUE, err);
}
diff --git a/gconf/gconfd-dbus.c b/gconf/gconfd-dbus.c
index 32d3aed7..0c569ed2 100644
--- a/gconf/gconfd-dbus.c
+++ b/gconf/gconfd-dbus.c
@@ -28,6 +28,10 @@ static DBusConnection *bus_conn;
static const char *server_path[] = { "org", "gnome", "GConf", "Server", NULL };
static gint nr_of_connections = 0;
+#define SERVICE_DELETED_RULE "type='signal',member='ServiceDeleted'," \
+ "sender='org.freedesktop.DBus',interface='org.freedesktop.DBus'"
+
+
static void server_unregistered_func (DBusConnection *connection,
void *user_data);
static DBusHandlerResult server_message_func (DBusConnection *connection,
@@ -177,7 +181,7 @@ gconfd_dbus_init (void)
dbus_error_init (&error);
bus_conn = dbus_bus_get (DBUS_BUS_SESSION, &error);
-
+
if (!bus_conn)
{
gconf_log (GCL_ERR, _("Failed to connect to the D-BUS daemon: %s"),
@@ -194,6 +198,9 @@ gconfd_dbus_init (void)
return FALSE;
}
+ /* Add filter for ServiceDeleted so we get notified when the clients go away. */
+ dbus_bus_add_match (bus_conn, SERVICE_DELETED_RULE, NULL);
+
dbus_bus_acquire_service (bus_conn, GCONF_DBUS_SERVICE, 0, &error);
if (dbus_error_is_set (&error))
{