GUADEC cancelled due to beer shortage



Hey,
	Well, no. I lie. But I got your attention :-)

	If you care about GConf preferences being shareable between pre-2.6 and
2.8 (or later) logins - or if you think someone might shout at you if it
doesn't work - you need to read this email.


	In GNOME 2.6 we introduced a feature into GConf's default backend
whereby you could tell it to save a part of the GConf tree to a single
file (%gconf-tree.xml) rather than to a file (%gconf.xml) in every
directory of that part of the tree. See:

  http://mail.gnome.org/archives/gconf-list/2003-July/msg00001.html

	And we had a huge thread on this list which was related, but I didn't
really understand what was going on there:

  http://mail.gnome.org/archives/desktop-devel-list/2003-October/thread.html#00084


	Anyway, the plan now is that we're going to switch this feature on very
soon. See:

  http://bugzilla.gnome.org/show_bug.cgi?id=138498

	The way its going to work is that, we have a hardcoded list of
directories and we will coalesce the contents of each of those
directories *sub-directories* when we next go to save a change. e.g. the
list contains "/apps", so the next time you change
/apps/metacity/general/theme you'll find a %gconf-tree.xml file in
~/.gconf/apps/metacity.


	Effectively, this means that changes made to your preferences using
GNOME 2.8 will not be visible if you log back into GNOME 2.4 or earlier.

	To disable this behaviour you can pass a "nomerge" flag to the backend
e.g. change

  xml:readwrite:$(HOME)/.gconf

	to

  xml:readwrite,nomerge:$(HOME)/.gconf

	I'll be committing the patch below as soon as I've given it a decent
hammering. Initial testing suggests its okay, however.

	Rational for the change is twofold:

  1) Lessen the pain of sharing a homedir between simultaneous logins by
     saving apps configuration as atomic units. This then gives us the
     same hypothetically-broken-but-usually-OK behaviour as regular dotfiles.

  2) Performance improvements


Cheers,
Mark.

Index: ChangeLog
===================================================================
RCS file: /cvs/gnome/gconf/ChangeLog,v
retrieving revision 1.527
diff -u -p -r1.527 ChangeLog
--- ChangeLog	21 Jun 2004 10:22:39 -0000	1.527
+++ ChangeLog	21 Jun 2004 16:15:42 -0000
@@ -1,0 +1,39 @@
+2004-06-21  Mark McLoughlin  <mark skynet ie>
+
+	Fix for bug #138498 - turn on "subtree-in-a-file" for the
+	subdirectories of the following directories:
+
+	    /apps/evolution",
+	    /apps/panel/profiles",
+	    /apps
+	    /desktop/gnome
+	    /system
+	    /schemas/apps
+	    /schemas/desktop/gnome
+	    /schemas/system
+	    /schemas
+	    /
+
+	You can turn this of by passing the "nomerge" flag to the
+	backend - e.g. xml:readwrite,nomerge:$(HOME)/.gconf
+	
+	* backends/markup-tree.[ch]:
+	(markup_tree_get): pass in the nomerge path.
+	(markup_dir_build_file_path),
+	(markup_dir_build_dir_path): simple wrappers for build_path().
+	(load_subtree), (load_entries), (load_subdirs),
+	(delete_useless_subdirs): upd. for above change.
+	(recursively_load_subtree): impl. recursively loading the tree
+	below a given dir.
+	(should_save_as_subtree): logic to figure out which dirs should
+	be saved as merged files.
+	(markup_dir_sync): save the dir in a merged file if neccessary.
+	(markup_dir_build_path): allow building a non-filesystem path.
+	(parse_tree), (save_tree): upd.
+	(write_dir): set the "not_in_filesystem" flag.
+	
+	* backends/markup-backend.c:
+	(resolve_address), (ms_new): parse and use the "nomerge" flag.
+	
+	* backends/gconf-merge-tree.c: (merge_tree): upd.
+
Index: backends/gconf-merge-tree.c
===================================================================
RCS file: /cvs/gnome/gconf/backends/gconf-merge-tree.c,v
retrieving revision 1.2
diff -u -p -r1.2 gconf-merge-tree.c
--- backends/gconf-merge-tree.c	28 Oct 2003 14:15:47 -0000	1.2
+++ backends/gconf-merge-tree.c	21 Jun 2004 16:15:42 -0000
@@ -39,25 +39,6 @@ _gconf_mode_t_to_mode (mode_t orig)
   return mode;
 }
 
-static void
-recursively_load_entire_tree (MarkupDir *dir)
-{
-  GSList *tmp;
-
-  load_entries (dir);
-  load_subdirs (dir);
-
-  tmp = dir->subdirs;
-  while (tmp != NULL)
-    {
-      MarkupDir *subdir = tmp->data;
-
-      recursively_load_entire_tree (subdir);
-
-      tmp = tmp->next;
-    }
-}
-
 static gboolean
 merge_tree (const char *root_dir)
 {
@@ -80,9 +61,9 @@ merge_tree (const char *root_dir)
 
     }
 
-  tree = markup_tree_get (root_dir, dir_mode, file_mode);
+  tree = markup_tree_get (root_dir, dir_mode, file_mode, FALSE);
 
-  recursively_load_entire_tree (tree->root);
+  recursively_load_subtree (tree->root);
 
   error = NULL;
   save_tree (tree->root, TRUE, file_mode, &error);
@@ -90,7 +71,7 @@ merge_tree (const char *root_dir)
     {
       char *markup_file;
 
-      markup_file = markup_dir_build_path (tree->root, TRUE, TRUE);
+      markup_file = markup_dir_build_file_path (tree->root, TRUE);
       fprintf (stderr, _("Error saving GConf tree to '%s': %s\n"),
 	       markup_file,
 	       error->message);
Index: backends/markup-backend.c
===================================================================
RCS file: /cvs/gnome/gconf/backends/markup-backend.c,v
retrieving revision 1.11
diff -u -p -r1.11 markup-backend.c
--- backends/markup-backend.c	19 Apr 2004 10:05:47 -0000	1.11
+++ backends/markup-backend.c	21 Jun 2004 16:15:42 -0000
@@ -65,11 +65,13 @@ typedef struct
   MarkupTree *tree;
   guint dir_mode;
   guint file_mode;
+  guint try_merge : 1;
 } MarkupSource;
 
 static MarkupSource* ms_new     (const char   *root_dir,
                                  guint         dir_mode,
                                  guint         file_mode,
+                                 gboolean      try_merge,
                                  GConfLock    *lock);
 static void          ms_destroy (MarkupSource *source);
 
@@ -262,6 +264,7 @@ resolve_address (const char *address,
   char** address_flags;
   char** iter;
   gboolean force_readonly;
+  gboolean try_merge;
 
   root_dir = get_dir_from_address (address, err);
   if (root_dir == NULL)
@@ -286,6 +289,7 @@ resolve_address (const char *address,
     }
 
   force_readonly = FALSE;
+  try_merge = TRUE;
   
   address_flags = gconf_address_flags (address);  
   if (address_flags)
@@ -296,7 +300,10 @@ resolve_address (const char *address,
           if (strcmp (*iter, "readonly") == 0)
             {
               force_readonly = TRUE;
-              break;
+            }
+          else if (strcmp (*iter, "nomerge") == 0)
+            {
+              try_merge = FALSE;
             }
 
           ++iter;
@@ -386,9 +393,12 @@ resolve_address (const char *address,
       return NULL;
     }
   
+  if (try_merge && !(flags & GCONF_SOURCE_ALL_WRITEABLE))
+    try_merge = FALSE;
+
   /* Create the new source */
 
-  xsource = ms_new (root_dir, dir_mode, file_mode, lock);
+  xsource = ms_new (root_dir, dir_mode, file_mode, try_merge, lock);
 
   gconf_log (GCL_DEBUG,
              _("Directory/file permissions for XML source at root %s are: %o/%o"),
@@ -891,6 +901,7 @@ static MarkupSource*
 ms_new (const char* root_dir,
         guint       dir_mode,
         guint       file_mode,
+        gboolean    try_merge,
         GConfLock  *lock)
 {
   MarkupSource* ms;
@@ -909,8 +920,12 @@ ms_new (const char* root_dir,
 
   ms->dir_mode = dir_mode;
   ms->file_mode = file_mode;
+  ms->try_merge = try_merge;
   
-  ms->tree = markup_tree_get (ms->root_dir, ms->dir_mode, ms->file_mode);
+  ms->tree = markup_tree_get (ms->root_dir,
+                              ms->dir_mode,
+                              ms->file_mode,
+                              ms->try_merge);
   
   return ms;
 }
Index: backends/markup-tree.c
===================================================================
RCS file: /cvs/gnome/gconf/backends/markup-tree.c,v
retrieving revision 1.8
diff -u -p -r1.8 markup-tree.c
--- backends/markup-tree.c	12 Jun 2004 07:39:15 -0000	1.8
+++ backends/markup-tree.c	21 Jun 2004 16:15:42 -0000
@@ -63,8 +63,9 @@ static void       markup_dir_free       
 static gboolean   markup_dir_needs_sync            (MarkupDir  *dir);
 static gboolean   markup_dir_sync                  (MarkupDir  *dir);
 static char*      markup_dir_build_path            (MarkupDir  *dir,
-						    gboolean    with_data_file,
-						    gboolean    subtree_data_file);
+                                                    gboolean    filesystem_path,
+                                                    gboolean    with_data_file,
+                                                    gboolean    subtree_data_file);
 static void       markup_dir_set_entries_need_save (MarkupDir  *dir);
 
 static MarkupEntry* markup_entry_new  (MarkupDir   *dir,
@@ -89,14 +90,34 @@ struct _MarkupTree
   MarkupDir *root;
 
   guint refcount;
+
+  guint try_merge : 1;
 };
 
 static GHashTable *trees_by_root_dir = NULL;
 
+/* List of dirs whose subdirs should be saved as a
+ * subtree-in-a-file. The order is important.
+ */
+static const char *save_as_subtree_dirs[] =
+{
+  "/apps/evolution",
+  "/apps/panel/profiles",
+  "/apps",
+  "/desktop/gnome",
+  "/system"
+  "/schemas/apps",
+  "/schemas/desktop/gnome",
+  "/schemas/system",
+  "/schemas",
+  "/"
+};
+
 MarkupTree*
 markup_tree_get (const char *root_dir,
                  guint       dir_mode,
-                 guint       file_mode)
+                 guint       file_mode,
+                 gboolean    try_merge)
 {
   MarkupTree *tree = NULL;
 
@@ -116,6 +137,7 @@ markup_tree_get (const char *root_dir,
   tree->dirname = g_strdup (root_dir);
   tree->dir_mode = dir_mode;
   tree->file_mode = file_mode;
+  tree->try_merge = try_merge != FALSE;
 
   tree->root = markup_dir_new (tree, NULL, "/");  
 
@@ -258,6 +280,20 @@ markup_dir_queue_sync (MarkupDir *dir)
     }
 }
 
+static inline char *
+markup_dir_build_file_path (MarkupDir *dir,
+                            gboolean   subtree_data_file)
+{
+  return markup_dir_build_path (dir, TRUE, TRUE, subtree_data_file);
+}
+
+static inline char *
+markup_dir_build_dir_path (MarkupDir *dir,
+                           gboolean   filesystem_path)
+{
+  return markup_dir_build_path (dir, filesystem_path, FALSE, FALSE);
+}
+
 static MarkupDir*
 markup_tree_get_dir_internal (MarkupTree *tree,
                               const char *full_key,
@@ -361,7 +397,7 @@ load_subtree (MarkupDir *dir)
   GError *tmp_err = NULL;
   char *markup_file;
 
-  markup_file = markup_dir_build_path (dir, TRUE, TRUE);
+  markup_file = markup_dir_build_file_path (dir, TRUE);
   if (!gconf_file_exists (markup_file))
     {
       g_free (markup_file);
@@ -427,7 +463,7 @@ load_entries (MarkupDir *dir)
 	  /* this message is debug-only because it usually happens
 	   * when creating a new directory
 	   */
-	  markup_file = markup_dir_build_path (dir, TRUE, FALSE);
+	  markup_file = markup_dir_build_file_path (dir, FALSE);
 	  gconf_log (GCL_DEBUG,
 		     "Failed to load file \"%s\": %s",
 		     markup_file, tmp_err->message);
@@ -467,7 +503,7 @@ load_subdirs (MarkupDir *dir)
   if (load_subtree (dir))
     return TRUE;
 
-  markup_dir = markup_dir_build_path (dir, FALSE, FALSE);
+  markup_dir = markup_dir_build_dir_path (dir, TRUE);
   
   dp = opendir (markup_dir);
   
@@ -786,8 +822,8 @@ delete_useless_subdirs (MarkupDir *dir)
 	      char *fs_dirname;
 	      char *fs_filename;
           
-	      fs_dirname = markup_dir_build_path (subdir, FALSE, FALSE);
-	      fs_filename = markup_dir_build_path (subdir, TRUE, dir->save_as_subtree);
+	      fs_dirname = markup_dir_build_dir_path (subdir, TRUE);
+	      fs_filename = markup_dir_build_file_path (subdir, dir->save_as_subtree);
 
 	      if (unlink (fs_filename) < 0)
 		{
@@ -887,6 +923,80 @@ delete_useless_entries (MarkupDir *dir)
   return some_deleted;
 }
 
+static void
+recursively_load_subtree (MarkupDir *dir)
+{
+  GSList *tmp;
+
+  load_entries (dir);
+  load_subdirs (dir);
+
+  tmp = dir->subdirs;
+  while (tmp != NULL)
+    {
+      MarkupDir *subdir = tmp->data;
+
+      recursively_load_subtree (subdir);
+
+      tmp = tmp->next;
+    }
+}
+
+static gboolean
+should_save_as_subtree (MarkupDir *dir)
+{
+  gboolean  save_as_subtree = FALSE;
+  char     *dir_path;
+  char     *parent_path;
+  int       pathlen;
+  int       i;
+
+  if (!dir->tree->try_merge)
+    return FALSE;
+
+  /* never merge root */
+  if (!dir->parent)
+    return FALSE;
+
+  dir_path = markup_dir_build_dir_path (dir, FALSE);
+  pathlen  = strlen (dir_path);
+
+  parent_path = markup_dir_build_dir_path (dir->parent, FALSE);
+
+  i = 0;
+  while (i < G_N_ELEMENTS (save_as_subtree_dirs))
+    {
+      const char *match = save_as_subtree_dirs [i];
+
+      /* 2 rules:
+       *  1) If @match is an ancestor of this dir, don't
+       *     consider merging this dir
+       *  2) If @match is this dir's parent, then merge
+       *     this dir
+       *
+       * (1) is so that we don't e.g., with "/apps" and
+       * "/apps/panel/profiles", merge /apps/panel when
+       * we really want to merge /apps/panel/profiles/default
+       */
+
+      if (strncmp (match, dir_path, pathlen) == 0)
+        break;
+
+      if (strcmp (match, parent_path) == 0)
+        {
+          save_as_subtree = TRUE;
+          break;
+        }
+
+      ++i;
+    }
+
+  g_free (dir_path);
+  g_free (parent_path);
+
+  return save_as_subtree;
+}
+
 static gboolean
 markup_dir_sync (MarkupDir *dir)
 {
@@ -918,10 +1028,16 @@ markup_dir_sync (MarkupDir *dir)
       
       tmp = tmp->next;
     }
+
+  if (!dir->save_as_subtree && should_save_as_subtree (dir))
+    {
+      dir->save_as_subtree = TRUE;
+      recursively_load_subtree (dir);
+    }
   
-  fs_dirname = markup_dir_build_path (dir, FALSE, FALSE);
-  fs_filename = markup_dir_build_path (dir, TRUE, FALSE);
-  fs_subtree = markup_dir_build_path (dir, TRUE, TRUE);
+  fs_dirname = markup_dir_build_dir_path (dir, TRUE);
+  fs_filename = markup_dir_build_file_path (dir, FALSE);
+  fs_subtree = markup_dir_build_file_path (dir, TRUE);
 
   /* For a dir to be loaded as a subdir, it must have a
    * %gconf.xml file, even if it has no entries in that
@@ -1051,6 +1167,7 @@ markup_dir_sync (MarkupDir *dir)
 
 static char*
 markup_dir_build_path (MarkupDir  *dir,
+                       gboolean    filesystem_path,
                        gboolean    with_data_file,
 		       gboolean    subtree_data_file)
 {
@@ -1059,6 +1176,8 @@ markup_dir_build_path (MarkupDir  *dir,
   GSList *tmp;
   MarkupDir *iter;
 
+  g_assert (filesystem_path || !with_data_file);
+
   components = NULL;
   iter = dir;
   while (iter->parent != NULL) /* exclude root dir */
@@ -1067,7 +1186,11 @@ markup_dir_build_path (MarkupDir  *dir,
       iter = iter->parent;
     }
 
-  name = g_string_new (dir->tree->dirname);
+  if (filesystem_path)
+    name = g_string_new (dir->tree->dirname);
+  else
+    name = g_string_new (components ? NULL : "/");
+
   tmp = components;
   while (tmp != NULL)
     {
@@ -3072,7 +3195,7 @@ parse_tree (MarkupDir  *root,
   char *text;
   gsize length;
 
-  filename = markup_dir_build_path (root, TRUE, parse_subtree);
+  filename = markup_dir_build_file_path (root, parse_subtree);
   
   parse_info_init (&info, root, parse_subtree);
 
@@ -3570,6 +3693,8 @@ write_dir (MarkupDir *dir,
   gboolean retval = FALSE;
   char *whitespace;
 
+  dir->not_in_filesystem = TRUE;
+
   /* This dir will be deleted from the 
    * MarkupTree after syncing anyway ...
    */
@@ -3639,7 +3764,7 @@ save_tree (MarkupDir  *dir,
   new_fd = -1;
   f = NULL;
 
-  filename = markup_dir_build_path (dir, TRUE, save_as_subtree);
+  filename = markup_dir_build_file_path (dir, save_as_subtree);
   
   new_filename = g_strconcat (filename, ".new", NULL);
   new_fd = open (new_filename, O_WRONLY | O_CREAT, file_mode);
Index: backends/markup-tree.h
===================================================================
RCS file: /cvs/gnome/gconf/backends/markup-tree.h,v
retrieving revision 1.4
diff -u -p -r1.4 markup-tree.h
--- backends/markup-tree.h	13 Mar 2003 20:24:57 -0000	1.4
+++ backends/markup-tree.h	21 Jun 2004 16:15:42 -0000
@@ -31,7 +31,8 @@ typedef struct _MarkupEntry MarkupEntry;
 
 MarkupTree* markup_tree_get        (const char *root_dir,
                                     guint       dir_mode,
-                                    guint       file_mode);
+                                    guint       file_mode,
+                                    gboolean    try_merge);
 void        markup_tree_unref      (MarkupTree *tree);
 void        markup_tree_rebuild    (MarkupTree *tree);
 MarkupDir*  markup_tree_lookup_dir (MarkupTree *tree,





[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]