Offline contact caching
@xclaesse
Submitted by Xavier Claessens Assigned to Telepathy bugs list
Description
Following my email[1], I think we should add helpers in telepathy-glib to handle the offline contact cache.
Goals:
- Provide last known Nickname for TpNamesMixin (bug #14540) without requesting VCard on XMPP.
- Provide last known ContactInfo without requesting VCard on XMPP.
- Provide offline roster
- Implement local roster for tp-sofiasip
Out of scope:
- incremental roster download. This is probably too protocol-specific.
Proposed solution:
- storing:
When CM is going offline, of course before freeing its data structures needed to reply to tp_contacts_mixin_get_contact_attributes(), it calls:
tp_base_contact_list_write_cache() { contacts = tp_base_contact_list_dup_contacts (self); result = tp_contacts_mixin_get_contact_attributes (conn, all_interfaces_except_presence); for attributes in result: { id = tp_asv_get_string (attributes, TP_TOKEN_CONNECTION_CONTACT_ID); variant = asv_to_gvariant(attributes); filename = g_strdup_printf ("~/.cache/telepathy/rosters/%s/%s", something_relevant_to_identify_the_account(self), id); write_file (filename, g_variant_to_blob(variant)); } }
- reading:
When CM receive the roster, or directly at startup for SIP:
GHashTable<contact-id, asv>
tp_base_contact_list_read_cache(Set<contact-id>
roster_ids)
{
return _read_roster_cache (something_relevant_to_identify_the_account(self),
roster_ids);
}
_read_roster_cache(something_relevant_to_identify_the_account, roster_ids) { dir = g_strdup_printf ("~/.cache/telepathy/rosters/%s", something_relevant_to_identify_the_account); for file in dir: { id = g_strrstr(file, "/")+1;
/* roster_ids is NULL when we just want to read them all */
if (roster_ids != NULL && id not in roster_ids)
{
rmfile(file);
continue;
}
reply[id] = g_variant_from_blob (file);
}
return reply; }
The CM populates his internal data structures from that. Or maybe we want to avoid reading everything, and we should wait for a GetContactAttributes call, and read cache only if something is missing (like ContactInfo, or Nickname) and just for that contact. Probably even better like that.
- Get an offline roster:
GPtrArray<TpOfflineContact>
tp_account_get_offline_roster()
{
map = _read_roster_cache(something_relevant_to_identify_the_account(self),
NULL);
for attributes in map:
{
reply.add(tp_offline_contact_new(attributes));
}
return reply;
}
TpOfflineContact is a trivial object that keeps a ref on attributes asv, and return the asv's value for each getter function. API is similar to TpContact but immutable.
The only thing not really clear to me, is how we define something_relevant_to_identify_the_account(). I would use tp_account_get_path_suffix() but how can I construct that from the TpBaseConnection side?
Comments more than welcome!
[1] http://lists.freedesktop.org/archives/telepathy/2013-March/006384.html