[folks] Add PersonaStore.is_prepared and make prepare() idempotent.
- From: Travis Reitter <treitter src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [folks] Add PersonaStore.is_prepared and make prepare() idempotent.
- Date: Wed, 22 Sep 2010 16:12:24 +0000 (UTC)
commit 329c41f971e0aad006b880c2640a30d38b459675
Author: Travis Reitter <travis reitter collabora co uk>
Date: Thu Sep 9 09:07:11 2010 -0700
Add PersonaStore.is_prepared and make prepare() idempotent.
Helps bgo#629331.
backends/key-file/kf-persona-store.vala | 186 ++++++++++++++-----------
backends/telepathy/lib/tpf-persona-store.vala | 131 ++++++++++-------
folks/persona-store.vala | 10 ++
3 files changed, 194 insertions(+), 133 deletions(-)
---
diff --git a/backends/key-file/kf-persona-store.vala b/backends/key-file/kf-persona-store.vala
index 6077d4b..6407eee 100644
--- a/backends/key-file/kf-persona-store.vala
+++ b/backends/key-file/kf-persona-store.vala
@@ -36,6 +36,7 @@ public class Folks.Backends.Kf.PersonaStore : Folks.PersonaStore
private GLib.KeyFile key_file;
private uint first_unused_id = 0;
private unowned Cancellable save_key_file_cancellable = null;
+ private bool _is_prepared = false;
/**
* { inheritDoc}
@@ -53,6 +54,18 @@ public class Folks.Backends.Kf.PersonaStore : Folks.PersonaStore
public override string id { get; private set; }
/**
+ * Whether this PersonaStore has been prepared.
+ *
+ * See { link Folks.PersonaStore.is_prepared}.
+ *
+ * @since 0.3.0
+ */
+ public override bool is_prepared
+ {
+ get { return this._is_prepared; }
+ }
+
+ /**
* { inheritDoc}
*/
public override HashTable<string, Persona> personas
@@ -81,98 +94,111 @@ public class Folks.Backends.Kf.PersonaStore : Folks.PersonaStore
*/
public override async void prepare ()
{
- string filename = this.file.get_path ();
- this.key_file = new GLib.KeyFile ();
-
- /* Load or create the file */
- while (true)
+ lock (this._is_prepared)
{
- /* Load the file; if this fails due to the file not existing or having
- * been deleted in the meantime, we can continue below and try to
- * create it instead. */
- try
+ if (!this._is_prepared)
{
- string contents = null;
- size_t length = 0;
+ string filename = this.file.get_path ();
+ this.key_file = new GLib.KeyFile ();
- yield this.file.load_contents_async (null, out contents,
- out length);
- if (length > 0)
+ /* Load or create the file */
+ while (true)
{
- this.key_file.load_from_data (contents, length,
- KeyFileFlags.KEEP_COMMENTS);
+ /* Load the file; if this fails due to the file not existing
+ * or having been deleted in the meantime, we can continue
+ * below and try to create it instead. */
+ try
+ {
+ string contents = null;
+ size_t length = 0;
+
+ yield this.file.load_contents_async (null, out contents,
+ out length);
+ if (length > 0)
+ {
+ this.key_file.load_from_data (contents, length,
+ KeyFileFlags.KEEP_COMMENTS);
+ }
+ break;
+ }
+ catch (Error e1)
+ {
+ if (!(e1 is IOError.NOT_FOUND))
+ {
+ warning ("The relationship key file '%s' could " +
+ "not be loaded: %s", filename, e1.message);
+ this.removed ();
+ return;
+ }
+ }
+
+ /* Ensure the parent directory tree exists for the new file */
+ File parent_dir = this.file.get_parent ();
+
+ try
+ {
+ /* Recursively create the directory */
+ parent_dir.make_directory_with_parents ();
+ }
+ catch (Error e3)
+ {
+ if (!(e3 is IOError.EXISTS))
+ {
+ warning ("The relationship key file directory " +
+ "'%s' could not be created: %s",
+ parent_dir.get_path (), e3.message);
+ this.removed ();
+ return;
+ }
+ }
+
+ /* Create a new file; if this fails due to the file having
+ * been created in the meantime, we can loop back round and
+ * try and load it. */
+ try
+ {
+ /* Create the file */
+ FileOutputStream stream = yield this.file.create_async (
+ FileCreateFlags.PRIVATE, Priority.DEFAULT);
+ yield stream.close_async (Priority.DEFAULT);
+ }
+ catch (Error e2)
+ {
+ if (!(e2 is IOError.EXISTS))
+ {
+ warning ("The relationship key file '%s' could " +
+ "not be created: %s", filename, e2.message);
+ this.removed ();
+ return;
+ }
+ }
}
- break;
- }
- catch (Error e1)
- {
- if (!(e1 is IOError.NOT_FOUND))
- {
- warning ("The relationship key file '%s' could not be " +
- "loaded: %s", filename, e1.message);
- this.removed ();
- return;
- }
- }
-
- /* Ensure the parent directory tree exists for the new file */
- File parent_dir = this.file.get_parent ();
- try
- {
- /* Recursively create the directory */
- parent_dir.make_directory_with_parents ();
- }
- catch (Error e3)
- {
- if (!(e3 is IOError.EXISTS))
+ /* We've loaded or created a key file by now, so cycle through the
+ * groups: each group is a persona which we have to create and
+ * emit */
+ string[] groups = this.key_file.get_groups ();
+ foreach (string persona_id in groups)
{
- warning ("The relationship key file directory '%s' could " +
- "not be created: %s", parent_dir.get_path (), e3.message);
- this.removed ();
- return;
+ if (persona_id.to_int () == this.first_unused_id)
+ this.first_unused_id++;
+
+ Persona persona = new Kf.Persona (this.key_file, persona_id,
+ this);
+ this._personas.insert (persona.iid, persona);
}
- }
- /* Create a new file; if this fails due to the file having been
- * created in the meantime, we can loop back round and try and load
- * it. */
- try
- {
- /* Create the file */
- FileOutputStream stream = yield this.file.create_async (
- FileCreateFlags.PRIVATE, Priority.DEFAULT);
- yield stream.close_async (Priority.DEFAULT);
- }
- catch (Error e2)
- {
- if (!(e2 is IOError.EXISTS))
+ if (this._personas.size () > 0)
{
- warning ("The relationship key file '%s' could not be " +
- "created: %s", filename, e2.message);
- this.removed ();
- return;
+ /* FIXME: Groupable.ChangeReason is not the right enum to use
+ * here */
+ this.personas_changed (this._personas.get_values (), null,
+ null, null, Groupable.ChangeReason.NONE);
}
- }
- }
-
- /* We've loaded or created a key file by now, so cycle through the groups:
- * each group is a persona which we have to create and emit */
- string[] groups = this.key_file.get_groups ();
- foreach (string persona_id in groups)
- {
- if (persona_id.to_int () == this.first_unused_id)
- this.first_unused_id++;
- Persona persona = new Kf.Persona (this.key_file, persona_id, this);
- this._personas.insert (persona.iid, persona);
- }
-
- if (this._personas.size () > 0)
- {
- /* FIXME: Groupable.ChangeReason is not the right enum to use here */
- this.personas_changed (this._personas.get_values (), null, null, null,
- Groupable.ChangeReason.NONE);
+ this._is_prepared = true;
+ this.notify_property ("is-prepared");
+ }
}
}
diff --git a/backends/telepathy/lib/tpf-persona-store.vala b/backends/telepathy/lib/tpf-persona-store.vala
index 0dedb92..c03f1d1 100644
--- a/backends/telepathy/lib/tpf-persona-store.vala
+++ b/backends/telepathy/lib/tpf-persona-store.vala
@@ -56,6 +56,7 @@ public class Tpf.PersonaStore : Folks.PersonaStore
private AccountManager account_manager;
private Logger logger;
private Contact self_contact;
+ private bool _is_prepared = false;
internal signal void group_members_changed (string group,
GLib.List<Persona>? added, GLib.List<Persona>? removed);
@@ -92,6 +93,18 @@ public class Tpf.PersonaStore : Folks.PersonaStore
public override string id { get; private set; }
/**
+ * Whether this PersonaStore has been prepared.
+ *
+ * See { link Folks.PersonaStore.is_prepared}.
+ *
+ * @since 0.3.0
+ */
+ public override bool is_prepared
+ {
+ get { return this._is_prepared; }
+ }
+
+ /**
* The { link Persona}s exposed by this PersonaStore.
*
* See { link Folks.PersonaStore.personas}.
@@ -155,64 +168,76 @@ public class Tpf.PersonaStore : Folks.PersonaStore
*/
public override async void prepare ()
{
- this.account_manager = AccountManager.dup ();
-
- this.account_manager.account_disabled.connect ((a) =>
- {
- if (this.account == a)
- {
- this.personas_changed (null, this._personas.get_values (), null,
- null, 0);
- this.removed ();
- }
- });
- this.account_manager.account_removed.connect ((a) =>
- {
- if (this.account == a)
- {
- this.personas_changed (null, this._personas.get_values (), null,
- null, 0);
- this.removed ();
- }
- });
- this.account_manager.account_validity_changed.connect ((a, valid) =>
+ lock (this._is_prepared)
{
- if (!valid && this.account == a)
+ if (!this._is_prepared)
{
- this.personas_changed (null, this._personas.get_values (), null,
- null, 0);
- this.removed ();
- }
- });
+ this.account_manager = AccountManager.dup ();
- this.account.status_changed.connect (this.account_status_changed_cb);
+ this.account_manager.account_disabled.connect ((a) =>
+ {
+ if (this.account == a)
+ {
+ this.personas_changed (null, this._personas.get_values (),
+ null, null, 0);
+ this.removed ();
+ }
+ });
+ this.account_manager.account_removed.connect ((a) =>
+ {
+ if (this.account == a)
+ {
+ this.personas_changed (null, this._personas.get_values (),
+ null, null, 0);
+ this.removed ();
+ }
+ });
+ this.account_manager.account_validity_changed.connect (
+ (a, valid) =>
+ {
+ if (!valid && this.account == a)
+ {
+ this.personas_changed (null, this._personas.get_values
+ (), null, null, 0);
+ this.removed ();
+ }
+ });
+
+ this.account.status_changed.connect (
+ this.account_status_changed_cb);
+
+ TelepathyGLib.ConnectionStatusReason reason;
+ var status = this.account.get_connection_status (out reason);
+ /* immediately handle accounts which are not currently being
+ * disconnected */
+ if (status != TelepathyGLib.ConnectionStatus.DISCONNECTED)
+ {
+ this.account_status_changed_cb (
+ TelepathyGLib.ConnectionStatus.DISCONNECTED, status,
+ reason, null, null);
+ }
- TelepathyGLib.ConnectionStatusReason reason;
- var status = this.account.get_connection_status (out reason);
- /* immediately handle accounts which are not currently being disconnected
- */
- if (status != TelepathyGLib.ConnectionStatus.DISCONNECTED)
- {
- this.account_status_changed_cb (
- TelepathyGLib.ConnectionStatus.DISCONNECTED, status, reason, null,
- null);
- }
+ try
+ {
+ this.logger = new Logger (this.id);
+ this.logger.invalidated.connect (() =>
+ {
+ warning ("lost connection to the telepathy-logger " +
+ "service");
+ this.logger = null;
+ });
+ this.logger.favourite_contacts_changed.connect (
+ this.favourite_contacts_changed_cb);
+ }
+ catch (DBus.Error e)
+ {
+ warning ("couldn't connect to the telepathy-logger service");
+ this.logger = null;
+ }
- try
- {
- this.logger = new Logger (this.id);
- this.logger.invalidated.connect (() =>
- {
- warning ("lost connection to the telepathy-logger service");
- this.logger = null;
- });
- this.logger.favourite_contacts_changed.connect (
- this.favourite_contacts_changed_cb);
- }
- catch (DBus.Error e)
- {
- warning ("couldn't connect to the telepathy-logger service");
- this.logger = null;
+ this._is_prepared = true;
+ this.notify_property ("is-prepared");
+ }
}
}
diff --git a/folks/persona-store.vala b/folks/persona-store.vala
index 2d865ef..a04c60c 100644
--- a/folks/persona-store.vala
+++ b/folks/persona-store.vala
@@ -175,6 +175,14 @@ public abstract class Folks.PersonaStore : Object
*/
public abstract HashTable<string, Persona> personas { get; }
+ /**
+ * Whether { link PersonaStore.prepare} has successfully completed for this
+ * store.
+ *
+ * @since 0.3.0
+ */
+ public abstract bool is_prepared { get; default = false; }
+
/**
* Whether the PersonaStore is writeable.
*
@@ -216,6 +224,8 @@ public abstract class Folks.PersonaStore : Object
*
* If this function throws an error, the PersonaStore will not be functional.
*
+ * This function is guaranteed to be idempotent (since version 0.3.0).
+ *
* @since 0.1.11
*/
public abstract async void prepare () throws GLib.Error;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]