telepathy-mission-control: McdStorage: store parameters in-memory as GVariants, with a fallback
Simon McVittie
smcv at kemper.freedesktop.org
Wed Feb 13 06:18:21 PST 2013
Module: telepathy-mission-control
Branch: master
Commit: ee9b43cb446218b3fca3a0a753a4a3a94413c81c
URL: http://cgit.freedesktop.org/telepathy/telepathy-mission-control/commit/?id=ee9b43cb446218b3fca3a0a753a4a3a94413c81c
Author: Simon McVittie <simon.mcvittie at collabora.co.uk>
Date: Mon Sep 10 18:27:28 2012 +0100
McdStorage: store parameters in-memory as GVariants, with a fallback
We don't necessarily know a parameter's type until we come to use it,
so we can't necessarily decode it from a plugin straight away. However,
if a new value comes in from UpdateParameters, we do know the type for
that one.
Signed-off-by: Simon McVittie <simon.mcvittie at collabora.co.uk>
---
src/mcd-storage.c | 112 ++++++++++++++++++++++++++++++++++++----------------
1 files changed, 77 insertions(+), 35 deletions(-)
diff --git a/src/mcd-storage.c b/src/mcd-storage.c
index 6cf6352..c63a791 100644
--- a/src/mcd-storage.c
+++ b/src/mcd-storage.c
@@ -69,9 +69,13 @@ typedef struct {
/* owned string => GVariant
* e.g. { 'DisplayName': <'Frederick Bloggs'> } */
GHashTable *attributes;
- /* owned string => owned string escaped as if for a keyfile
- * e.g. { 'account': 'fred at example.com', 'password': 'foo' } */
+ /* owned string => owned GVariant
+ * e.g. { 'account': <'fred at example.com'>, 'password': <'foo'> } */
GHashTable *parameters;
+ /* owned string => owned string escaped as if for a keyfile
+ * e.g. { 'account': 'fred at example.com', 'password': 'foo' }
+ * keys of @parameters and @escaped_parameters are disjoint */
+ GHashTable *escaped_parameters;
/* set of owned strings
* e.g. { 'password': 'password' } */
GHashTable *secrets;
@@ -84,6 +88,7 @@ mcd_storage_account_free (gpointer p)
g_hash_table_unref (sa->attributes);
g_hash_table_unref (sa->parameters);
+ g_hash_table_unref (sa->escaped_parameters);
g_hash_table_unref (sa->secrets);
g_slice_free (McdStorageAccount, sa);
}
@@ -228,6 +233,8 @@ ensure_account (McdStorage *self,
sa->attributes = g_hash_table_new_full (g_str_hash, g_str_equal,
g_free, (GDestroyNotify) g_variant_unref);
sa->parameters = g_hash_table_new_full (g_str_hash, g_str_equal,
+ g_free, (GDestroyNotify) g_variant_unref);
+ sa->escaped_parameters = g_hash_table_new_full (g_str_hash, g_str_equal,
g_free, g_free);
sa->secrets = g_hash_table_new_full (g_str_hash, g_str_equal,
g_free, NULL);
@@ -237,19 +244,6 @@ ensure_account (McdStorage *self,
return sa;
}
-static const gchar *
-mcd_storage_get_escaped_parameter (McdStorage *self,
- const gchar *account,
- const gchar *parameter)
-{
- McdStorageAccount *sa = lookup_account (self, account);
-
- if (sa == NULL)
- return NULL;
-
- return g_hash_table_lookup (sa->parameters, parameter);
-}
-
static gchar *
get_value (const McpAccountManager *ma,
const gchar *account,
@@ -265,8 +259,21 @@ get_value (const McpAccountManager *ma,
if (g_str_has_prefix (key, "param-"))
{
- return g_strdup (mcd_storage_get_escaped_parameter (self, account,
- key + 6));
+ variant = g_hash_table_lookup (sa->parameters, key + 6);
+
+ if (variant != NULL)
+ {
+ ret = mcd_keyfile_escape_variant (variant);
+ g_variant_unref (variant);
+ return ret;
+ }
+ else
+ {
+ /* OK, we don't have it as a variant. How about the keyfile-escaped
+ * version? */
+ return g_strdup (g_hash_table_lookup (sa->escaped_parameters,
+ key + 6));
+ }
}
else
{
@@ -395,11 +402,12 @@ set_value (const McpAccountManager *ma,
if (g_str_has_prefix (key, "param-"))
{
+ g_hash_table_remove (sa->parameters, key + 6);
+ g_hash_table_remove (sa->escaped_parameters, key + 6);
+
if (value != NULL)
- g_hash_table_insert (sa->parameters, g_strdup (key + 6),
+ g_hash_table_insert (sa->escaped_parameters, g_strdup (key + 6),
g_strdup (value));
- else
- g_hash_table_remove (sa->parameters, key + 6);
}
else
{
@@ -897,13 +905,31 @@ mcd_storage_get_parameter (McdStorage *self,
GValue *value,
GError **error)
{
+ McdStorageAccount *sa;
const gchar *escaped;
+ GVariant *variant;
g_return_val_if_fail (MCD_IS_STORAGE (self), FALSE);
g_return_val_if_fail (account != NULL, FALSE);
g_return_val_if_fail (parameter != NULL, FALSE);
- escaped = mcd_storage_get_escaped_parameter (self, account, parameter);
+ sa = lookup_account (self, account);
+
+ if (sa == NULL)
+ {
+ g_set_error (error, TP_ERROR, TP_ERROR_NOT_AVAILABLE,
+ "Account %s does not exist", account);
+ return FALSE;
+ }
+
+ variant = g_hash_table_lookup (sa->parameters, parameter);
+
+ if (variant != NULL)
+ return mcd_storage_coerce_variant_to_value (variant, value, error);
+
+ /* OK, we don't have it as a variant. How about the keyfile-escaped
+ * version? */
+ escaped = g_hash_table_lookup (sa->escaped_parameters, parameter);
if (escaped == NULL)
{
@@ -1453,8 +1479,12 @@ mcd_storage_set_parameter (McdStorage *self,
const GValue *value,
gboolean secret)
{
- gchar *escaped = NULL;
+ GVariant *old_v;
+ GVariant *new_v = NULL;
+ const gchar *old_escaped;
+ gchar *new_escaped = NULL;
McdStorageAccount *sa;
+ gboolean updated = FALSE;
g_return_val_if_fail (MCD_IS_STORAGE (self), FALSE);
g_return_val_if_fail (account != NULL, FALSE);
@@ -1463,28 +1493,40 @@ mcd_storage_set_parameter (McdStorage *self,
sa = ensure_account (self, account);
if (value != NULL)
- escaped = mcd_keyfile_escape_value (value);
+ {
+ new_escaped = mcd_keyfile_escape_value (value);
+ new_v = g_variant_ref_sink (dbus_g_value_build_g_variant (value));
+ }
+
+ old_v = g_hash_table_lookup (sa->parameters, parameter);
+ old_escaped = g_hash_table_lookup (sa->escaped_parameters, parameter);
- if (tp_strdiff (escaped, g_hash_table_lookup (sa->parameters, parameter)))
+ if (old_v != NULL)
+ updated = !mcd_nullable_variant_equal (old_v, new_v);
+ else if (old_escaped != NULL)
+ updated = tp_strdiff (old_escaped, new_escaped);
+ else
+ updated = (value != NULL);
+
+ if (updated)
{
gchar key[MAX_KEY_LENGTH];
- if (escaped == NULL)
- g_hash_table_remove (sa->parameters, parameter);
- else
+ g_hash_table_remove (sa->parameters, parameter);
+ g_hash_table_remove (sa->escaped_parameters, parameter);
+
+ if (new_v != NULL)
g_hash_table_insert (sa->parameters, g_strdup (parameter),
- g_strdup (escaped));
+ g_variant_ref (new_v));
g_snprintf (key, sizeof (key), "param-%s", parameter);
- update_storage (self, account, key, escaped, secret);
- g_free (escaped);
+ update_storage (self, account, key, new_escaped, secret);
return TRUE;
}
- else
- {
- g_free (escaped);
- return FALSE;
- }
+
+ g_free (new_escaped);
+ tp_clear_pointer (&new_v, g_variant_unref);
+ return updated;
}
static gchar *
More information about the telepathy-commits
mailing list