Re: supporting notifications from backends
- From: Mark McLoughlin <mark skynet ie>
- To: Cyrille Moureaux <Cyrille Moureaux Sun COM>
- Cc: gconf-list gnome org
- Subject: Re: supporting notifications from backends
- Date: Mon, 29 Mar 2004 10:59:33 +0100
Hi Cyrille,
On Fri, 2004-03-26 at 09:40, Cyrille Moureaux wrote:
> From the point of view of the relationship between the backend and the
> daemon, the addition of yet another client listener for
> /apps/metacity/general when there's already a client listening for
> /apps/metacity shouldn't change the state of the backend, it should
> still only report changes to anything below /apps/metacity to the daemon
> for further action.
>
> If there's an add_listener called for each client listener, all backends
> have to do some comparisons to realise that the same callback/user data
> pair is being passed each time so that they can ignore most of the
> requests, otherwise if they just assume all listeners passed are somehow
> different, everytime something changes in the store the daemon is going
> to be called once per client listening to that point.
Ah, I hadn't thought of that extra complexity for the backends. Because
of that and the fact that, as you say, allowing a different callback per
listener is useless I've added back a set_notify_func() vtable member.
> + GList *tmp;
> +
> + tmp = sources->sources;
> +
> + while (sources != NULL)
>
> I think it should be "while (tmp != NULL)" since sources is unlikely to
> change (hopefully) and it's a bit late to check its nullity when it's
> already been dereferenced.
Well spotted, thanks.
Attaching how she's looking now. Let me know if you see any further
problems with this.
It should be in CVS by tommorrow. I'd really appreciate it if you could
try updating your backend then and making sure everything is okay.
Thanks,
Mark.
Index: ChangeLog
===================================================================
RCS file: /home/markmc/gnome-devel/local-repository/gconf/ChangeLog,v
retrieving revision 1.490
retrieving revision 1.494
diff -u -p -r1.490 -r1.494
--- ChangeLog 24 Mar 2004 20:02:56 -0000 1.490
+++ ChangeLog 29 Mar 2004 09:52:54 -0000 1.494
@@ -1,1 +1,65 @@
+2004-03-29 Mark McLoughlin <mark skynet ie>
+
+ * backends/markup-backend.c,
+ backends/xml-backend.c: initialize the set_notify_func
+ vtable member.
+
+2004-03-29 Mark McLoughlin <mark skynet ie>
+
+ Re-work the notifications-from-backends patch so that the
+ backend doesn't have to keep track of a callback per
+ listener as suggested by Cyrille.
+
+ * gconf/gconf-backend.h: add a set_notify_func() member to
+ the vtable and remove the callback arg from add_listener().
+
+ * gconf/gconf-database.c:
+ (gconf_database_new): set the notification callback here.
+ (gconf_database_readd_listener): upd.
+
+ * gconf/gconf-sources.[ch]:
+ (gconf_source_set_notify_func): add.
+ (gconf_source_add_listener): upd.
+ (gconf_sources_set_notify_func): add.
+ (gconf_sources_add_listener): upd.
+
+2004-03-26 Mark McLoughlin <mark skynet ie>
+
+ * gconf/gconf-database.c: (source_notify_cb): don't leak
+ the schema name.
+
+ * gconf/gconf-sources.c:
+ (gconf_sources_add_listener),
+ (gconf_sources_remove_listener): fix mistake pointed out
+ by Cyrille.
+
+2004-03-25 Mark McLoughlin <mark skynet ie>
+
+ Allow backends to notify the daemon of changes to entries.
+ Based on a patch from Cyrille Moureaux <Cyrille Moureaux Sun COM>
+ in bug #07692.
+
+ * gconf/gconf-backend.h: add add_listener() and
+ remove_listener() members to the vtable.
+
+ * gconf/gconf-database.c:
+ (source_notify_cb): re-compute the value and notify
+ listeners when the backend reports the key has changed.
+ (gconf_database_readd_listener),
+ (gconf_database_remove_listener): add/remove backend
+ listeners.
+
+ * gconf/gconf-sources.[c]:
+ (gconf_source_add_listener),
+ (gconf_source_remove_listener),
+ (gconf_sources_add_listener),
+ (gconf_sources_remove_listener): impl. the glue.
+
+ * doc/gconf/tmpl/gconf-backend.sgml: update the backend
+ documentation.
+
+ * backends/markup-backend.c,
+ backends/xml-backend.c: set the add_listener() and
+ remove_listener() members to NULL.
+
Index: backends/markup-backend.c
===================================================================
RCS file: /home/markmc/gnome-devel/local-repository/gconf/backends/markup-backend.c,v
retrieving revision 1.8
retrieving revision 1.10
diff -u -p -r1.8 -r1.10
--- backends/markup-backend.c 24 Mar 2004 20:03:01 -0000 1.8
+++ backends/markup-backend.c 29 Mar 2004 09:52:58 -0000 1.10
@@ -151,7 +151,10 @@ static GConfBackendVTable markup_vtable
sync_all,
destroy_source,
clear_cache,
- blow_away_locks
+ blow_away_locks,
+ NULL, /* set_notify_func */
+ NULL, /* add_listener */
+ NULL /* remove_listener */
};
static void
Index: backends/xml-backend.c
===================================================================
RCS file: /home/markmc/gnome-devel/local-repository/gconf/backends/xml-backend.c,v
retrieving revision 1.86
retrieving revision 1.88
diff -u -p -r1.86 -r1.88
--- backends/xml-backend.c 24 Mar 2004 20:03:01 -0000 1.86
+++ backends/xml-backend.c 29 Mar 2004 09:52:58 -0000 1.88
@@ -228,7 +228,10 @@ static GConfBackendVTable xml_vtable = {
sync_all,
destroy_source,
clear_cache,
- blow_away_locks
+ blow_away_locks,
+ NULL, /* set_notify_func */
+ NULL, /* add_listener */
+ NULL /* remove_listener */
};
static void
Index: doc/gconf/tmpl/gconf-backend.sgml
===================================================================
RCS file: /home/markmc/gnome-devel/local-repository/gconf/doc/gconf/tmpl/gconf-backend.sgml,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -p -r1.8 -r1.9
--- doc/gconf/tmpl/gconf-backend.sgml 24 Mar 2004 20:03:05 -0000 1.8
+++ doc/gconf/tmpl/gconf-backend.sgml 25 Mar 2004 17:59:07 -0000 1.9
@@ -23,13 +23,23 @@ called gconf_backend_get_vtable() that r
</para>
<para>
-Here are the methods the backend must implement, and their specification:
+Here is the specification of the vtable members:
<informaltable pgwide="1" frame="none">
<tgroup cols="2"><colspec colwidth="2*"/><colspec colwidth="8*"/>
<tbody>
<row>
+<entry>@vtable_size</entry>
+<entry>
+The size of the vtable structure. This is used by the daemon to ensure that
+a mismatch between the version of GConf the backend was compiled against and
+the version the daemon was compiled against can be handled gracefully. Set
+this field to sizeof (GConfBackendVtable).
+</entry>
+</row>
+
+<row>
<entry>@shutdown</entry>
<entry>Called prior to unloading the dynamic
module. Should ensure that no functions or static/global variables from the
@@ -227,7 +237,67 @@ Should destroy a source obtained with @r
</row>
+<row>
+<entry>@clear_cache</entry>
+
+<entry>
+Discard any cached data after saving the data to permanent storage.
+</entry>
+
+</row>
+
+<row>
+<entry>@blow_away_locks</entry>
+
+<entry>
+Unconditionally discard any locks whether they are stale or otherwise in
+order to force the backend to be able to obtain access to its data store.
+</entry>
+
+</row>
+
+<row>
+<entry>@add_listener</entry>
+
+<entry>
+If it is possible for entries to be changed concurrently by another
+daemon, the backend may support notifying the daemon (and any listening
+clients) of such changes. This function should add a listener to a
+section of the tree and when any of the following events occur, the
+backend should invoke the notify function with the key that has changed:
+ <itemizedlist mark="bullet">
+ <listitem>
+ <para>If the entry is set or unset</para>
+ </listitem>
+ <listitem>
+ <para>If the entry's value changes</para>
+ </listitem>
+ <listitem>
+ <para>If the entry's schema name changes</para>
+ </listitem>
+ <listitem>
+ <para>
+ If the entry is a schema and its value in <emphasis>any</emphasis>
+ locale changes
+ </para>
+ </listitem>
+ </itemizedlist>
+Note, the backend should <emphasis>not</emphasis> notify the daemon of
+any changes that originated from the daemon itself.
+</entry>
+
+</row>
+
+<row>
+<entry>@remove_listener</entry>
+
+<entry>
+Remove a listener added with @add_listener. The listener is identified
+by the integer supplied.
+</entry>
+</row>
+
</tbody></tgroup></informaltable>
</para>
@@ -251,6 +321,8 @@ Should destroy a source obtained with @r
@destroy_source:
@clear_cache:
@blow_away_locks:
+ add_listener:
+ remove_listener:
<!-- ##### STRUCT GConfBackend ##### -->
<para>
Index: gconf/gconf-backend.h
===================================================================
RCS file: /home/markmc/gnome-devel/local-repository/gconf/gconf/gconf-backend.h,v
retrieving revision 1.31
retrieving revision 1.33
diff -u -p -r1.31 -r1.33
--- gconf/gconf-backend.h 24 Mar 2004 20:03:09 -0000 1.31
+++ gconf/gconf-backend.h 29 Mar 2004 09:47:33 -0000 1.33
@@ -133,6 +133,17 @@ struct _GConfBackendVTable {
/* used by gconf-sanity-check */
void (* blow_away_locks) (const char *address);
+
+ void (* set_notify_func) (GConfSource *source,
+ GConfSourceNotifyFunc notify_func,
+ gpointer user_data);
+
+ void (* add_listener) (GConfSource *source,
+ guint id,
+ const gchar *namespace_section);
+
+ void (* remove_listener) (GConfSource *source,
+ guint id);
};
struct _GConfBackend {
Index: gconf/gconf-database.c
===================================================================
RCS file: /home/markmc/gnome-devel/local-repository/gconf/gconf/gconf-database.c,v
retrieving revision 1.33
retrieving revision 1.36
diff -u -p -r1.33 -r1.36
--- gconf/gconf-database.c 24 Mar 2004 20:03:10 -0000 1.33
+++ gconf/gconf-database.c 29 Mar 2004 09:47:34 -0000 1.36
@@ -800,7 +800,10 @@ static POA_ConfigDatabase3__epv server3_
static POA_ConfigDatabase3__vepv poa_server_vepv = { &base_epv, &server_epv, &server2_epv, &server3_epv };
-static void gconf_database_really_sync(GConfDatabase* db);
+static void gconf_database_really_sync (GConfDatabase *db);
+static void source_notify_cb (GConfSource *source,
+ const gchar *location,
+ GConfDatabase *db);
GConfDatabase*
gconf_database_new (GConfSources *sources)
@@ -832,6 +835,10 @@ gconf_database_new (GConfSources *sourc
db->sources = sources;
+ gconf_sources_set_notify_func (db->sources,
+ (GConfSourceNotifyFunc) source_notify_cb,
+ db);
+
db->last_access = time(NULL);
db->sync_idle = 0;
@@ -1027,6 +1034,58 @@ gconf_database_schedule_sync(GConfDataba
}
}
+static void
+source_notify_cb (GConfSource *source,
+ const gchar *location,
+ GConfDatabase *db)
+{
+ GConfValue *value;
+ ConfigValue *cvalue;
+ GError *error;
+ gboolean is_default;
+ gboolean is_writable;
+
+ g_return_if_fail (source != NULL);
+ g_return_if_fail (location != NULL);
+ g_return_if_fail (db != NULL);
+
+ error = NULL;
+ is_default = is_writable = FALSE;
+
+ /* FIXME: only notify if this location isn't already set
+ * in a source above this one.
+ */
+
+ value = gconf_database_query_value (db,
+ location,
+ NULL,
+ TRUE,
+ NULL,
+ &is_default,
+ &is_writable,
+ &error);
+ if (error != NULL)
+ {
+ gconf_log (GCL_WARNING,
+ _("Error obtaining new value for `%s' after change notification from backend `%s': %s"),
+ location,
+ source->address,
+ error->message);
+ g_error_free (error);
+ return;
+ }
+
+ cvalue = gconf_corba_value_from_gconf_value (value);
+ gconf_database_notify_listeners (db,
+ location,
+ cvalue,
+ is_default,
+ is_writable);
+
+ CORBA_free (cvalue);
+ gconf_value_free (value);
+}
+
CORBA_unsigned_long
gconf_database_readd_listener (GConfDatabase *db,
ConfigListener who,
@@ -1047,6 +1106,8 @@ gconf_database_readd_listener (GConfDa
cnxn = gconf_listeners_add (db->listeners, where, l,
(GFreeFunc)listener_destroy);
+ gconf_sources_add_listener (db->sources, cnxn, where);
+
if (l->name == NULL)
l->name = g_strdup_printf ("%u", cnxn);
@@ -1130,6 +1191,8 @@ gconf_database_remove_listener (GConfDat
g_error_free (err);
}
+ gconf_sources_remove_listener (db->sources, cnxn);
+
/* calls destroy notify */
gconf_listeners_remove (db->listeners, cnxn);
}
Index: gconf/gconf-sources.c
===================================================================
RCS file: /home/markmc/gnome-devel/local-repository/gconf/gconf/gconf-sources.c,v
retrieving revision 1.44
retrieving revision 1.47
diff -u -p -r1.44 -r1.47
--- gconf/gconf-sources.c 24 Mar 2004 20:03:10 -0000 1.44
+++ gconf/gconf-sources.c 29 Mar 2004 09:47:34 -0000 1.47
@@ -288,6 +288,46 @@ gconf_source_sync_all (GConfSour
return (*source->backend->vtable.sync_all)(source, err);
}
+static void
+gconf_source_set_notify_func (GConfSource *source,
+ GConfSourceNotifyFunc notify_func,
+ gpointer user_data)
+{
+ g_return_if_fail (source != NULL);
+
+ if (source->backend->vtable.set_notify_func)
+ {
+ (*source->backend->vtable.set_notify_func) (source, notify_func, user_data);
+ }
+}
+
+static void
+gconf_source_add_listener (GConfSource *source,
+ guint id,
+ const gchar *namespace_section)
+{
+ g_return_if_fail (source != NULL);
+ g_return_if_fail (id > 0);
+
+ if (source->backend->vtable.add_listener)
+ {
+ (*source->backend->vtable.add_listener) (source, id, namespace_section);
+ }
+}
+
+static void
+gconf_source_remove_listener (GConfSource *source,
+ guint id)
+{
+ g_return_if_fail (source != NULL);
+ g_return_if_fail (id > 0);
+
+ if (source->backend->vtable.remove_listener)
+ {
+ (*source->backend->vtable.remove_listener) (source, id);
+ }
+}
+
/*
* Source stacks
*/
@@ -1548,5 +1588,52 @@ gconf_sources_query_default_value(GConfS
gconf_meta_info_free(mi);
return NULL;
+ }
+}
+
+void
+gconf_sources_set_notify_func (GConfSources *sources,
+ GConfSourceNotifyFunc notify_func,
+ gpointer user_data)
+{
+ GList *tmp;
+
+ tmp = sources->sources;
+ while (tmp != NULL)
+ {
+ gconf_source_set_notify_func (tmp->data, notify_func, user_data);
+
+ tmp = tmp->next;
+ }
+}
+
+void
+gconf_sources_add_listener (GConfSources *sources,
+ guint id,
+ const gchar *namespace_section)
+{
+ GList *tmp;
+
+ tmp = sources->sources;
+ while (tmp != NULL)
+ {
+ gconf_source_add_listener (tmp->data, id, namespace_section);
+
+ tmp = tmp->next;
+ }
+}
+
+void
+gconf_sources_remove_listener (GConfSources *sources,
+ guint id)
+{
+ GList *tmp;
+
+ tmp = sources->sources;
+ while (tmp != NULL)
+ {
+ gconf_source_remove_listener (tmp->data, id);
+
+ tmp = tmp->next;
}
}
Index: gconf/gconf-sources.h
===================================================================
RCS file: /home/markmc/gnome-devel/local-repository/gconf/gconf/gconf-sources.h,v
retrieving revision 1.21
retrieving revision 1.23
diff -u -p -r1.21 -r1.23
--- gconf/gconf-sources.h 18 Jun 2003 10:39:40 -0000 1.21
+++ gconf/gconf-sources.h 29 Mar 2004 09:47:34 -0000 1.23
@@ -24,6 +24,7 @@
#include <glib.h>
#include "gconf-error.h"
#include "gconf-value.h"
+#include "gconf-listeners.h"
/* Sources are not interchangeable; different backend engines will return
* GConfSource with different private elements.
@@ -50,6 +51,10 @@ typedef enum {
GCONF_SOURCE_ALL_FLAGS = ((1 << 0) | (1 << 1))
} GConfSourceFlags;
+typedef void (* GConfSourceNotifyFunc) (GConfSource *source,
+ const gchar *location,
+ gpointer user_data);
+
GConfSource* gconf_resolve_address (const gchar* address,
GError** err);
@@ -124,11 +129,13 @@ GConfValue* gconf_sources_query_defaul
gboolean* is_writable,
GError** err);
-#endif
-
-
-
-
-
-
+void gconf_sources_set_notify_func (GConfSources *sources,
+ GConfSourceNotifyFunc notify_func,
+ gpointer user_data);
+void gconf_sources_add_listener (GConfSources *sources,
+ guint id,
+ const gchar *location);
+void gconf_sources_remove_listener (GConfSources *sources,
+ guint id);
+#endif
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]