[Pkg-telepathy-commits] [telepathy-mission-control-6] 91/280: McdAccountManagerDefault: segregate attributes and parameters

Simon McVittie smcv at debian.org
Thu Mar 27 20:07:09 UTC 2014


This is an automated email from the git hooks/post-receive script.

smcv pushed a commit to branch debian
in repository telepathy-mission-control-6.

commit 477d1f2d6041df4b3af2c6b678afe40238eb3b0c
Author: Simon McVittie <simon.mcvittie at collabora.co.uk>
Date:   Tue Oct 29 12:05:46 2013 +0000

    McdAccountManagerDefault: segregate attributes and parameters
    
    Instead of lumping everything into a GKeyFile, store attributes and
    parameters separately.
    
    Bug: https://bugs.freedesktop.org/show_bug.cgi?id=54875
    Reviewed-by: Guillaume Desmottes <guillaume.desmottes at collabora.co.uk>
---
 src/mcd-account-manager-default.c | 326 ++++++++++++++++++++++++++++++++------
 src/mcd-account-manager-default.h |   4 +-
 2 files changed, 277 insertions(+), 53 deletions(-)

diff --git a/src/mcd-account-manager-default.c b/src/mcd-account-manager-default.c
index 66ce891..6bbea0e 100644
--- a/src/mcd-account-manager-default.c
+++ b/src/mcd-account-manager-default.c
@@ -37,6 +37,54 @@
 #define PLUGIN_DESCRIPTION "GKeyFile (default) account storage backend"
 #define INITIAL_CONFIG "# Telepathy accounts\n"
 
+typedef struct {
+    /* owned string, attribute => owned string, value
+     * attributes to be stored in the keyfile */
+    GHashTable *attributes;
+    /* owned string, parameter (without "param-") => owned string, value
+     * parameters to be stored in the keyfile */
+    GHashTable *untyped_parameters;
+    /* TRUE if the entire account is pending deletion */
+    gboolean pending_deletion;
+} McdDefaultStoredAccount;
+
+static McdDefaultStoredAccount *
+lookup_stored_account (McdAccountManagerDefault *self,
+    const gchar *account)
+{
+  return g_hash_table_lookup (self->accounts, account);
+}
+
+static McdDefaultStoredAccount *
+ensure_stored_account (McdAccountManagerDefault *self,
+    const gchar *account)
+{
+  McdDefaultStoredAccount *sa = lookup_stored_account (self, account);
+
+  if (sa == NULL)
+    {
+      sa = g_slice_new0 (McdDefaultStoredAccount);
+      sa->attributes = g_hash_table_new_full (g_str_hash, g_str_equal,
+          g_free, g_free);
+      sa->untyped_parameters = g_hash_table_new_full (g_str_hash, g_str_equal,
+          g_free, g_free);
+      g_hash_table_insert (self->accounts, g_strdup (account), sa);
+    }
+
+  sa->pending_deletion = FALSE;
+  return sa;
+}
+
+static void
+stored_account_free (gpointer p)
+{
+  McdDefaultStoredAccount *sa = p;
+
+  g_hash_table_unref (sa->attributes);
+  g_hash_table_unref (sa->untyped_parameters);
+  g_slice_free (McdDefaultStoredAccount, sa);
+}
+
 static void account_storage_iface_init (McpAccountStorageIface *,
     gpointer);
 
@@ -76,10 +124,8 @@ mcd_account_manager_default_init (McdAccountManagerDefault *self)
 {
   DEBUG ("mcd_account_manager_default_init");
   self->filename = account_filename_in (g_get_user_data_dir ());
-  self->keyfile = g_key_file_new ();
-  self->removed = g_key_file_new ();
-  self->removed_accounts =
-    g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+  self->accounts = g_hash_table_new_full (g_str_hash, g_str_equal, g_free,
+      stored_account_free);
   self->save = FALSE;
   self->loaded = FALSE;
 }
@@ -93,20 +139,95 @@ mcd_account_manager_default_class_init (McdAccountManagerDefaultClass *cls)
 /* We happen to know that the string MC gave us is "sufficiently escaped" to
  * put it in the keyfile as-is. */
 static gboolean
-_set (const McpAccountStorage *self,
+set_parameter (const McpAccountStorage *self,
     const McpAccountManager *am,
     const gchar *account,
-    const gchar *key,
+    const gchar *prefixed,
+    const gchar *parameter,
     const gchar *val)
 {
   McdAccountManagerDefault *amd = MCD_ACCOUNT_MANAGER_DEFAULT (self);
+  McdDefaultStoredAccount *sa;
 
+  sa = ensure_stored_account (amd, account);
   amd->save = TRUE;
 
   if (val != NULL)
-    g_key_file_set_value (amd->keyfile, account, key, val);
+    g_hash_table_insert (sa->untyped_parameters, g_strdup (parameter),
+        g_strdup (val));
+  else
+    g_hash_table_remove (sa->untyped_parameters, parameter);
+
+  return TRUE;
+}
+
+/* As above, the string is escaped for a keyfile. */
+static gboolean
+set_attribute (const McpAccountStorage *self,
+    const McpAccountManager *am,
+    const gchar *account,
+    const gchar *attribute,
+    const gchar *val)
+{
+  McdAccountManagerDefault *amd = MCD_ACCOUNT_MANAGER_DEFAULT (self);
+  McdDefaultStoredAccount *sa = ensure_stored_account (amd, account);
+
+  amd->save = TRUE;
+
+  if (val != NULL)
+    g_hash_table_insert (sa->attributes, g_strdup (attribute), g_strdup (val));
+  else
+    g_hash_table_remove (sa->attributes, attribute);
+
+  return TRUE;
+}
+
+static gboolean
+_set (const McpAccountStorage *self,
+    const McpAccountManager *am,
+    const gchar *account,
+    const gchar *key,
+    const gchar *val)
+{
+  if (g_str_has_prefix (key, "param-"))
+    {
+      return set_parameter (self, am, account, key, key + 6, val);
+    }
+  else
+    {
+      return set_attribute (self, am, account, key, val);
+    }
+}
+
+static gboolean
+get_parameter (const McpAccountStorage *self,
+    const McpAccountManager *am,
+    const gchar *account,
+    const gchar *prefixed,
+    const gchar *parameter)
+{
+  McdAccountManagerDefault *amd = MCD_ACCOUNT_MANAGER_DEFAULT (self);
+  McdDefaultStoredAccount *sa = lookup_stored_account (amd, account);
+
+  if (parameter != NULL)
+    {
+      gchar *v = NULL;
+
+      if (sa == NULL)
+        return FALSE;
+
+      v = g_hash_table_lookup (sa->untyped_parameters, parameter);
+
+      if (v == NULL)
+        return FALSE;
+
+      mcp_account_manager_set_value (am, account, prefixed, v);
+      g_free (v);
+    }
   else
-    g_key_file_remove_key (amd->keyfile, account, key, NULL);
+    {
+      g_assert_not_reached ();
+    }
 
   return TRUE;
 }
@@ -118,12 +239,21 @@ _get (const McpAccountStorage *self,
     const gchar *key)
 {
   McdAccountManagerDefault *amd = MCD_ACCOUNT_MANAGER_DEFAULT (self);
+  McdDefaultStoredAccount *sa = lookup_stored_account (amd, account);
+
+  if (sa == NULL)
+    return FALSE;
 
   if (key != NULL)
     {
       gchar *v = NULL;
 
-      v = g_key_file_get_value (amd->keyfile, account, key, NULL);
+      if (g_str_has_prefix (key, "param-"))
+        {
+          return get_parameter (self, am, account, key, key + 6);
+        }
+
+      v = g_hash_table_lookup (sa->attributes, key);
 
       if (v == NULL)
         return FALSE;
@@ -133,24 +263,30 @@ _get (const McpAccountStorage *self,
     }
   else
     {
-      gsize i;
-      gsize n;
-      GStrv keys = g_key_file_get_keys (amd->keyfile, account, &n, NULL);
+      GHashTableIter iter;
+      gpointer k, v;
 
-      if (keys == NULL)
-        n = 0;
+      g_hash_table_iter_init (&iter, sa->attributes);
 
-      for (i = 0; i < n; i++)
+      while (g_hash_table_iter_next (&iter, &k, &v))
         {
-          gchar *v = g_key_file_get_value (amd->keyfile, account, keys[i], NULL);
+          if (v != NULL)
+            mcp_account_manager_set_value (am, account, k, v);
+        }
 
+      g_hash_table_iter_init (&iter, sa->untyped_parameters);
+
+      while (g_hash_table_iter_next (&iter, &k, &v))
+        {
           if (v != NULL)
-            mcp_account_manager_set_value (am, account, keys[i], v);
+            {
+              gchar *prefixed = g_strdup_printf ("param-%s",
+                  (const gchar *) k);
 
-          g_free (v);
+              mcp_account_manager_set_value (am, account, prefixed, v);
+              g_free (prefixed);
+            }
         }
-
-      g_strfreev (keys);
     }
 
   return TRUE;
@@ -183,32 +319,44 @@ _delete (const McpAccountStorage *self,
       const gchar *key)
 {
   McdAccountManagerDefault *amd = MCD_ACCOUNT_MANAGER_DEFAULT (self);
+  McdDefaultStoredAccount *sa = lookup_stored_account (amd, account);
+
+  if (sa == NULL)
+    {
+      /* Apparently we never had this account anyway. The plugin API
+       * considers this to be "success". */
+      return TRUE;
+    }
 
   if (key == NULL)
     {
-      if (g_key_file_remove_group (amd->keyfile, account, NULL))
-        amd->save = TRUE;
+      amd->save = TRUE;
+
+      /* flag the whole account as purged */
+      sa->pending_deletion = TRUE;
+      g_hash_table_remove_all (sa->attributes);
+      g_hash_table_remove_all (sa->untyped_parameters);
     }
   else
     {
-      gsize n;
-      GStrv keys;
-      gboolean save = FALSE;
-
-      save = g_key_file_remove_key (amd->keyfile, account, key, NULL);
-
-      if (save)
-        amd->save = TRUE;
-
-      keys = g_key_file_get_keys (amd->keyfile, account, &n, NULL);
-
-      /* if that was the last parameter, the account is gone too */
-      if (keys == NULL || n == 0)
+      if (g_str_has_prefix (key, "param-"))
+        {
+          if (g_hash_table_remove (sa->untyped_parameters, key + 6))
+            amd->save = TRUE;
+        }
+      else
         {
-          g_key_file_remove_group (amd->keyfile, account, NULL);
+          if (g_hash_table_remove (sa->attributes, key))
+            amd->save = TRUE;
         }
 
-      g_strfreev (keys);
+      /* if that was the last attribute or parameter, the account is gone
+       * too */
+      if (g_hash_table_size (sa->attributes) == 0 &&
+          g_hash_table_size (sa->untyped_parameters) == 0)
+        {
+          sa->pending_deletion = TRUE;
+        }
     }
 
   return TRUE;
@@ -226,6 +374,9 @@ _commit (const McpAccountStorage *self,
   gboolean rval = FALSE;
   gchar *dir;
   GError *error = NULL;
+  GHashTableIter outer;
+  gpointer account_p, sa_p;
+  GKeyFile *keyfile;
 
   if (!amd->save)
     return TRUE;
@@ -244,7 +395,37 @@ _commit (const McpAccountStorage *self,
 
   g_free (dir);
 
-  data = g_key_file_to_data (amd->keyfile, &n, NULL);
+  keyfile = g_key_file_new ();
+
+  g_hash_table_iter_init (&outer, amd->accounts);
+
+  while (g_hash_table_iter_next (&outer, &account_p, &sa_p))
+    {
+      McdDefaultStoredAccount *sa = sa_p;
+      GHashTableIter inner;
+      gpointer k, v;
+
+      /* don't save accounts that are being deleted */
+      if (sa->pending_deletion)
+        continue;
+
+      g_hash_table_iter_init (&inner, sa->attributes);
+
+      while (g_hash_table_iter_next (&inner, &k, &v))
+        g_key_file_set_value (keyfile, account_p, k, v);
+
+      g_hash_table_iter_init (&inner, sa->untyped_parameters);
+
+      while (g_hash_table_iter_next (&inner, &k, &v))
+        {
+          gchar *prefixed = g_strdup_printf ("param-%s", (const gchar *) k);
+
+          g_key_file_set_value (keyfile, account_p, prefixed, v);
+          g_free (prefixed);
+        }
+    }
+
+  data = g_key_file_to_data (keyfile, &n, NULL);
   rval = g_file_set_contents (amd->filename, data, n, &error);
 
   if (rval)
@@ -258,6 +439,18 @@ _commit (const McpAccountStorage *self,
     }
 
   g_free (data);
+  g_key_file_unref (keyfile);
+
+  g_hash_table_iter_init (&outer, amd->accounts);
+
+  /* forget about any entirely removed accounts */
+  while (g_hash_table_iter_next (&outer, NULL, &sa_p))
+    {
+      McdDefaultStoredAccount *sa = sa_p;
+
+      if (sa->pending_deletion)
+        g_hash_table_iter_remove (&outer);
+    }
 
   return rval;
 }
@@ -267,8 +460,12 @@ am_default_load_keyfile (McdAccountManagerDefault *self,
     const gchar *filename)
 {
   GError *error = NULL;
+  GKeyFile *keyfile = g_key_file_new ();
+  gsize i;
+  gsize n = 0;
+  GStrv account_tails;
 
-  if (g_key_file_load_from_file (self->keyfile, filename,
+  if (g_key_file_load_from_file (keyfile, filename,
         G_KEY_FILE_KEEP_COMMENTS, &error))
     {
       DEBUG ("Loaded accounts from %s", filename);
@@ -282,20 +479,53 @@ am_default_load_keyfile (McdAccountManagerDefault *self,
        * we don't want to overwrite a corrupt-but-maybe-recoverable
        * configuration file with an empty one until given a reason to
        * do so. */
-      g_key_file_load_from_data (self->keyfile, INITIAL_CONFIG, -1,
+      g_key_file_load_from_data (keyfile, INITIAL_CONFIG, -1,
           G_KEY_FILE_KEEP_COMMENTS, NULL);
     }
+
+  account_tails = g_key_file_get_groups (keyfile, &n);
+
+  for (i = 0; i < n; i++)
+    {
+      const gchar *account = account_tails[i];
+      McdDefaultStoredAccount *sa = ensure_stored_account (self, account);
+      gsize j;
+      gsize m = 0;
+      GStrv keys = g_key_file_get_keys (keyfile, account, &m, NULL);
+
+      for (j = 0; j < m; j++)
+        {
+          gchar *key = keys[j];
+          gchar *raw = g_key_file_get_value (keyfile, account, key, NULL);
+
+          if (g_str_has_prefix (key, "param-"))
+            {
+              /* steals ownership of raw */
+              g_hash_table_insert (sa->untyped_parameters, g_strdup (key + 6),
+                  raw);
+            }
+          else
+            {
+              /* steals ownership of raw */
+              g_hash_table_insert (sa->attributes, g_strdup (key), raw);
+            }
+        }
+
+      g_strfreev (keys);
+    }
+
+  g_strfreev (account_tails);
+  g_key_file_unref (keyfile);
 }
 
 static GList *
 _list (const McpAccountStorage *self,
     const McpAccountManager *am)
 {
-  gsize i;
-  gsize n;
-  GStrv accounts;
   GList *rval = NULL;
   McdAccountManagerDefault *amd = MCD_ACCOUNT_MANAGER_DEFAULT (self);
+  GHashTableIter hash_iter;
+  gpointer k, v;
 
   if (!amd->loaded && g_file_test (amd->filename, G_FILE_TEST_EXISTS))
     {
@@ -358,22 +588,18 @@ _list (const McpAccountStorage *self,
   if (!amd->loaded)
     {
       DEBUG ("Creating initial account data");
-      g_key_file_load_from_data (amd->keyfile, INITIAL_CONFIG, -1,
-          G_KEY_FILE_KEEP_COMMENTS, NULL);
       amd->loaded = TRUE;
       amd->save = TRUE;
       _commit (self, am, NULL);
     }
 
-  accounts = g_key_file_get_groups (amd->keyfile, &n);
+  g_hash_table_iter_init (&hash_iter, amd->accounts);
 
-  for (i = 0; i < n; i++)
+  while (g_hash_table_iter_next (&hash_iter, &k, &v))
     {
-      rval = g_list_prepend (rval, g_strdup (accounts[i]));
+      rval = g_list_prepend (rval, g_strdup (k));
     }
 
-  g_strfreev (accounts);
-
   return rval;
 }
 
diff --git a/src/mcd-account-manager-default.h b/src/mcd-account-manager-default.h
index b16bc4f..e48a767 100644
--- a/src/mcd-account-manager-default.h
+++ b/src/mcd-account-manager-default.h
@@ -49,9 +49,7 @@ G_BEGIN_DECLS
 
 typedef struct {
   GObject parent;
-  GKeyFile *keyfile;
-  GKeyFile *removed;
-  GHashTable *removed_accounts;
+  GHashTable *accounts;
   gchar *filename;
   gboolean save;
   gboolean loaded;

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-telepathy/telepathy-mission-control-6.git



More information about the Pkg-telepathy-commits mailing list