[dconf] service: new 'state' object



commit c4c2473639d81fb5b09cb11a75c96b21ca471c36
Author: Ryan Lortie <desrt desrt ca>
Date:   Sat Jul 24 19:28:44 2010 -0400

    service: new 'state' object
    
    Clean up the service a bit by putting its state into a separate object
    that is accessible from the DBus code and the writer.
    
    This way we avoid a circular dependency without sticking inappropriate
    data in the writer.

 service/Makefile.am    |    2 +
 service/dconf-state.c  |  100 ++++++++++++++++++++++++++++++++++++++++++++++++
 service/dconf-state.h  |   22 ++++++++++
 service/dconf-writer.c |   82 ++++++---------------------------------
 service/dconf-writer.h |    8 ++--
 service/service.c      |   48 ++++++++++++++++-------
 6 files changed, 174 insertions(+), 88 deletions(-)
---
diff --git a/service/Makefile.am b/service/Makefile.am
index c8ebb06..d844e2a 100644
--- a/service/Makefile.am
+++ b/service/Makefile.am
@@ -16,6 +16,8 @@ dconf_service_SOURCES = \
 	dconf-rebuilder.c		\
 	dconf-writer.h			\
 	dconf-writer.c			\
+	dconf-state.h			\
+	dconf-state.c			\
 	service.c
 
 DISTCLEANFILES = ca.desrt.dconf.service
diff --git a/service/dconf-state.c b/service/dconf-state.c
new file mode 100644
index 0000000..9c7569b
--- /dev/null
+++ b/service/dconf-state.c
@@ -0,0 +1,100 @@
+#include "dconf-state.h"
+
+#include "dconf-shmdir.h"
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+
+static void
+dconf_state_init_session (DConfState *state)
+{
+  const gchar *config_dir = g_get_user_config_dir ();
+
+  state->db_dir = g_build_filename (config_dir, "dconf", NULL);
+
+  if (g_mkdir_with_parents (state->db_dir, 0700))
+    {
+      /* XXX remove this after a while... */
+      if (errno == ENOTDIR)
+        {
+          gchar *tmp, *final;
+
+          g_message ("Attempting to migrate ~/.config/dconf "
+                     "to ~/.config/dconf/user");
+
+          tmp = g_build_filename (config_dir, "dconf-user.db", NULL);
+
+          if (rename (state->db_dir, tmp))
+            g_error ("Can not rename '%s' to '%s': %s",
+                     state->db_dir, tmp, g_strerror (errno));
+
+          if (g_mkdir_with_parents (state->db_dir, 0700))
+            g_error ("Can not create directory '%s': %s",
+                     state->db_dir, g_strerror (errno));
+
+          final = g_build_filename (state->db_dir, "user", NULL);
+
+          if (rename (tmp, final))
+            g_error ("Can not rename '%s' to '%s': %s",
+                     tmp, final, g_strerror (errno));
+
+          g_message ("Successful.");
+
+          g_free (final);
+          g_free (tmp);
+        }
+      else
+        g_error ("Can not create directory '%s': %s",
+                 state->db_dir, g_strerror (errno));
+    }
+
+  state->shm_dir = dconf_shmdir_from_environment ();
+
+  if (state->shm_dir == NULL)
+    {
+      const gchar *tmpdir = g_get_tmp_dir ();
+      gchar *shmdir;
+
+      shmdir = g_build_filename (tmpdir, "dconf.XXXXXX", NULL);
+
+      if ((state->shm_dir = mkdtemp (shmdir)) == NULL)
+        g_error ("Can not create reasonable shm directory");
+    }
+}
+
+void
+dconf_state_init (DConfState *state)
+{
+  state->is_session = strcmp (g_get_user_name (), "dconf") != 0;
+  state->main_loop = g_main_loop_new (NULL, FALSE);
+  state->serial = 0;
+  state->id = NULL;
+
+  if (state->is_session)
+    dconf_state_init_session (state);
+
+  g_print ("db is %s\n", state->db_dir);
+}
+
+void
+dconf_state_destroy (DConfState *state)
+{
+  g_main_loop_unref (state->main_loop);
+}
+
+void
+dconf_state_set_id (DConfState  *state,
+                    const gchar *id)
+{
+  g_assert (state->id == NULL);
+  state->id = g_strdup (id);
+}
+
+gchar *
+dconf_state_get_tag (DConfState *state)
+{
+  return g_strdup_printf ("%"G_GUINT64_FORMAT"%s",
+                          state->serial++, state->id);
+}
diff --git a/service/dconf-state.h b/service/dconf-state.h
new file mode 100644
index 0000000..8bbe612
--- /dev/null
+++ b/service/dconf-state.h
@@ -0,0 +1,22 @@
+#ifndef __dconf_state_h__
+#define __dconf_state_h__
+
+#include <glib.h>
+
+typedef struct
+{
+  gboolean is_session;
+  GMainLoop *main_loop;
+  guint64 serial;
+  gchar *db_dir;
+  gchar *shm_dir;
+  gchar *id;
+} DConfState;
+
+void                    dconf_state_init                                (DConfState  *state);
+void                    dconf_state_set_id                              (DConfState  *state,
+                                                                         const gchar *id);
+void                    dconf_state_destroy                             (DConfState  *state);
+gchar *                 dconf_state_get_tag                             (DConfState  *state);
+
+#endif /* __dconf_state_h__ */
diff --git a/service/dconf-writer.c b/service/dconf-writer.c
index c4d21a7..15a618c 100644
--- a/service/dconf-writer.c
+++ b/service/dconf-writer.c
@@ -21,8 +21,8 @@
 
 #include "dconf-writer.h"
 
-#include "dconf-shmdir.h"
 #include "dconf-rebuilder.h"
+#include "dconf-state.h"
 
 #include <stdlib.h>
 #include <unistd.h>
@@ -30,22 +30,14 @@
 #include <errno.h>
 #include <stdio.h>
 
-static const gchar *dconf_writer_shm_dir;
-static const gchar *dconf_writer_db_dir;
-
 struct OPAQUE_TYPE__DConfWriter
 {
+  DConfState *state;
   gchar *name;
   gchar *path;
   gchar *shm;
 };
 
-const gchar *
-dconf_writer_get_shm_dir (void)
-{
-  return dconf_writer_shm_dir;
-}
-
 /* Each element must only contain the ASCII characters "[A-Z][a-z][0-9]_"
  */
 static gboolean
@@ -141,72 +133,22 @@ dconf_writer_get_name (DConfWriter *writer)
   return writer->name;
 }
 
+DConfState *
+dconf_writer_get_state (DConfWriter *writer)
+{
+  return writer->state;
+}
+
 DConfWriter *
-dconf_writer_new (const gchar *name)
+dconf_writer_new (DConfState  *state,
+                  const gchar *name)
 {
   DConfWriter *writer;
 
   writer = g_slice_new (DConfWriter);
-  writer->path = g_build_filename (dconf_writer_db_dir, name, NULL);
-  writer->shm = g_build_filename (dconf_writer_shm_dir, name, NULL);
+  writer->path = g_build_filename (state->db_dir, name, NULL);
+  writer->shm = g_build_filename (state->shm_dir, name, NULL);
   writer->name = g_strdup (name);
 
   return writer;
 }
-
-void
-dconf_writer_init (void)
-{
-  const gchar *config_dir = g_get_user_config_dir ();
-
-  dconf_writer_db_dir = g_build_filename (config_dir, "dconf", NULL);
-
-  if (g_mkdir_with_parents (dconf_writer_db_dir, 0700))
-    {
-      /* XXX remove this after a while... */
-      if (errno == ENOTDIR)
-        {
-          gchar *tmp, *final;
-
-          g_message ("Attempting to migrate ~/.config/dconf "
-                     "to ~/.config/dconf/user");
-
-          tmp = g_build_filename (config_dir, "dconf-user.db", NULL);
-
-          if (rename (dconf_writer_db_dir, tmp))
-            g_error ("Can not rename '%s' to '%s': %s",
-                     dconf_writer_db_dir, tmp, g_strerror (errno));
-
-          if (g_mkdir_with_parents (dconf_writer_db_dir, 0700))
-            g_error ("Can not create directory '%s': %s",
-                     dconf_writer_db_dir, g_strerror (errno));
-
-          final = g_build_filename (dconf_writer_db_dir, "user", NULL);
-
-          if (rename (tmp, final))
-            g_error ("Can not rename '%s' to '%s': %s",
-                     tmp, final, g_strerror (errno));
-
-          g_message ("Successful.");
-
-          g_free (final);
-          g_free (tmp);
-        }
-      else
-        g_error ("Can not create directory '%s': %s",
-                 dconf_writer_db_dir, g_strerror (errno));
-    }
-
-  dconf_writer_shm_dir = dconf_shmdir_from_environment ();
-
-  if (dconf_writer_shm_dir == NULL)
-    {
-      const gchar *tmpdir = g_get_tmp_dir ();
-      gchar *shmdir;
-
-      shmdir = g_build_filename (tmpdir, "dconf.XXXXXX", NULL);
-
-      if ((dconf_writer_shm_dir = mkdtemp (shmdir)) == NULL)
-        g_error ("Can not create reasonable shm directory");
-    }
-}
diff --git a/service/dconf-writer.h b/service/dconf-writer.h
index 8c21f3b..4c2e6b3 100644
--- a/service/dconf-writer.h
+++ b/service/dconf-writer.h
@@ -22,14 +22,14 @@
 #ifndef __dconf_writer_h__
 #define __dconf_writer_h__
 
-#include <glib.h>
+#include "dconf-state.h"
 
 typedef struct OPAQUE_TYPE__DConfWriter DConfWriter;
 
-const gchar *           dconf_writer_get_shm_dir                        (void);
 gchar **                dconf_writer_list_existing                      (void);
-void                    dconf_writer_init                               (void);
-DConfWriter *           dconf_writer_new                                (const gchar          *name);
+DConfWriter *           dconf_writer_new                                (DConfState           *state,
+                                                                         const gchar          *name);
+DConfState *            dconf_writer_get_state                          (DConfWriter          *writer);
 const gchar *           dconf_writer_get_name                           (DConfWriter          *writer);
 gboolean                dconf_writer_write                              (DConfWriter          *writer,
                                                                          const gchar          *name,
diff --git a/service/service.c b/service/service.c
index 4a91e43..30512bd 100644
--- a/service/service.c
+++ b/service/service.c
@@ -25,8 +25,7 @@
 
 #include "dconf-interfaces.h"
 #include "dconf-writer.h"
-
-static guint64 dconf_service_serial;
+#include "dconf-state.h"
 
 static void
 emit_notify_signal (GDBusConnection  *connection,
@@ -120,6 +119,9 @@ method_call (GDBusConnection       *connection,
              gpointer               user_data)
 {
   DConfWriter *writer = user_data;
+  DConfState *state;
+
+  state = dconf_writer_get_state (writer);
 
   if (strcmp (method_name, "Write") == 0)
     {
@@ -129,8 +131,8 @@ method_call (GDBusConnection       *connection,
       gsize key_length;
       GVariant *value;
       GVariant *none;
-      gchar tag[20];
       gchar *path;
+      gchar *tag;
 
       g_variant_get (parameters, "(@s av)", &keyvalue, &value);
       key = g_variant_get_string (keyvalue, &key_length);
@@ -164,7 +166,7 @@ method_call (GDBusConnection       *connection,
           return;
         }
 
-      snprintf (tag, sizeof tag, "%"G_GUINT64_FORMAT, dconf_service_serial++);
+      tag = dconf_state_get_tag (state);
       g_dbus_method_invocation_return_value (invocation,
                                              g_variant_new ("(s)", tag));
       none = g_variant_new_array (G_VARIANT_TYPE_STRING, NULL, 0);
@@ -176,6 +178,7 @@ method_call (GDBusConnection       *connection,
                                                     key, none, tag),
                                      NULL);
       g_free (path);
+      g_free (tag);
     }
 
   else if (strcmp (method_name, "WriteMany") == 0)
@@ -185,8 +188,8 @@ method_call (GDBusConnection       *connection,
       GVariantIter *iter;
       const gchar **keys;
       GVariant **values;
-      gchar tag[20];
       gsize length;
+      gchar *tag;
       gint i = 0;
       gint j;
 
@@ -228,7 +231,7 @@ method_call (GDBusConnection       *connection,
           return;
         }
 
-      snprintf (tag, sizeof tag, "%"G_GUINT64_FORMAT, dconf_service_serial++);
+      tag = dconf_state_get_tag (state);
       g_dbus_method_invocation_return_value (invocation,
                                              g_variant_new ("(s)", tag));
       emit_notify_signal (connection, writer, tag, prefix, keys, i);
@@ -239,6 +242,7 @@ method_call (GDBusConnection       *connection,
 
       g_free (values);
       g_free (keys);
+      g_free (tag);
     }
 
   else if (strcmp (method_name, "SetLock") == 0)
@@ -272,7 +276,9 @@ writer_info_get_property (GDBusConnection  *connection,
                           GError          **error,
                           gpointer          user_data)
 {
-  return g_variant_new_string (dconf_writer_get_shm_dir ());
+  DConfState *state = user_data;
+
+  return g_variant_new_string (state->shm_dir);
 }
 
 static const GDBusInterfaceVTable *
@@ -284,6 +290,8 @@ subtree_dispatch (GDBusConnection *connection,
                   gpointer        *out_user_data,
                   gpointer         user_data)
 {
+  DConfState *state = user_data;
+
   if (strcmp (interface_name, "ca.desrt.dconf.Writer") == 0)
     {
       static const GDBusInterfaceVTable vtable = {
@@ -302,7 +310,7 @@ subtree_dispatch (GDBusConnection *connection,
 
       if G_UNLIKELY (writer == NULL)
         {
-          writer = dconf_writer_new (node);
+          writer = dconf_writer_new (state, node);
           g_hash_table_insert (writer_table, g_strdup (node), writer);
         }
 
@@ -317,7 +325,7 @@ subtree_dispatch (GDBusConnection *connection,
         NULL, writer_info_get_property, NULL
       };
 
-      *out_user_data = NULL;
+      *out_user_data = state;
       return &vtable;
     }
 
@@ -368,11 +376,14 @@ bus_acquired (GDBusConnection *connection,
   static GDBusSubtreeVTable vtable = {
     subtree_enumerate, subtree_introspect, subtree_dispatch
   };
+  DConfState *state = user_data;
   GDBusSubtreeFlags flags;
 
+  dconf_state_set_id (state, g_dbus_connection_get_unique_name (connection));
+
   flags = G_DBUS_SUBTREE_FLAGS_DISPATCH_TO_UNENUMERATED_NODES;
   g_dbus_connection_register_subtree (connection, "/ca/desrt/dconf/Writer",
-                                      &vtable, flags, NULL, NULL, NULL);
+                                      &vtable, flags, state, NULL, NULL);
 }
 
 static void
@@ -393,14 +404,23 @@ name_lost (GDBusConnection *connection,
 int
 main (void)
 {
+  DConfState state;
+  GBusType type;
+
   g_type_init ();
+  dconf_state_init (&state);
+
+  if (state.is_session)
+    type = G_BUS_TYPE_SESSION;
+  else
+    type = G_BUS_TYPE_SYSTEM;
 
-  dconf_writer_init ();
+  g_bus_own_name (type, "ca.desrt.dconf", G_BUS_NAME_OWNER_FLAGS_NONE,
+                  bus_acquired, name_acquired, name_lost, &state, NULL);
 
-  g_bus_own_name (G_BUS_TYPE_SESSION, "ca.desrt.dconf", 0,
-                  bus_acquired, name_acquired, name_lost, NULL, NULL);
+  g_main_loop_run (state.main_loop);
 
-  g_main_loop_run (g_main_loop_new (NULL, FALSE));
+  dconf_state_destroy (&state);
 
   return 0;
 }



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