summaryrefslogtreecommitdiff
path: root/telepathy-logger/log-store-xml.c
diff options
context:
space:
mode:
authorDavid Laban <david.laban@collabora.co.uk>2011-05-17 20:18:19 -0400
committerDavid Laban <david.laban@collabora.co.uk>2011-05-17 20:18:19 -0400
commitf796a5a882dd57f56b08be817d4d929643970d25 (patch)
tree6ffd06ca25df59f920d4de331bb8a15acf2724e4 /telepathy-logger/log-store-xml.c
parentdc17262c8b8690801b76b62caa8d7cb78ad11a2f (diff)
downloadtelepathy-logger-f796a5a882dd57f56b08be817d4d929643970d25.tar.gz
log_store_xml_get_events_for_file: replace edited messages.
This should support "b supersedes a ; c supersedes a" as well as "b supersedes a ; c supersedes b" Also, the list of returned events should only contain the most recent version (for backwards compat with dumb log viewers, as suggested by sjoerd). * make a event_queue_add_text_event responsible for adding the event to the returned gqueue (replacing the event it supersedes as needed). * use a GHashTable of {token: place to put message} for already edited messages, and check that first, then walk through the queue (starting at the most recent event) trying to find it. * add a dummy event if none can be found.
Diffstat (limited to 'telepathy-logger/log-store-xml.c')
-rw-r--r--telepathy-logger/log-store-xml.c84
1 files changed, 78 insertions, 6 deletions
diff --git a/telepathy-logger/log-store-xml.c b/telepathy-logger/log-store-xml.c
index 045cdb9..89dd08c 100644
--- a/telepathy-logger/log-store-xml.c
+++ b/telepathy-logger/log-store-xml.c
@@ -1261,6 +1261,68 @@ event_queue_insert_sorted_after (GQueue *events,
}
}
+static GList *
+event_queue_add_text_event (GQueue *events,
+ GList *index,
+ GHashTable *superseded_links,
+ TplTextEvent *event)
+{
+ GList *l = NULL;
+ const gchar *supersedes_token = tpl_text_event_get_supersedes_token (event);
+ TplTextEvent *dummy_event;
+
+ if (supersedes_token == NULL)
+ return event_queue_insert_sorted_after (events, index, TPL_EVENT (event));
+
+ l = g_hash_table_lookup (superseded_links, supersedes_token);
+ if (l != NULL)
+ {
+ tpl_text_event_add_supersedes (event, l->data);
+ g_object_unref (l->data);
+ l->data = event;
+ g_hash_table_insert (superseded_links, (gpointer) supersedes_token, l);
+ return index;
+ }
+
+ /* Search backwards from "now" and insert (but don't update "now") */
+ for (l = index; l != NULL; l = l->prev)
+ {
+ if (!tp_strdiff (tpl_text_event_get_message_token (l->data),
+ supersedes_token))
+ {
+ tpl_text_event_add_supersedes (event, l->data);
+ g_object_unref (l->data);
+ l->data = event;
+ g_hash_table_insert (superseded_links, (gpointer) supersedes_token, l);
+ return index;
+ }
+ }
+
+ DEBUG ("Can't find event %s (superseded by %s). "
+ "Better <s>drink my own piss</s> fake it.",
+ supersedes_token, tpl_text_event_get_message_token (event));
+
+ dummy_event = g_object_new (TPL_TYPE_TEXT_EVENT,
+ /* TplEvent */
+ "account", tpl_event_get_account (TPL_EVENT (event)),
+ /* MISSING: "channel-path", channel_path, */
+ "receiver", tpl_event_get_receiver (TPL_EVENT (event)),
+ "sender", tpl_event_get_sender (TPL_EVENT (event)),
+ "timestamp", tpl_event_get_timestamp (TPL_EVENT (event)),
+ /* TplTextEvent */
+ "message-type", tpl_text_event_get_message_type (event),
+ "message", "",
+ "message-token", supersedes_token,
+ NULL);
+
+ tpl_text_event_add_supersedes (event, dummy_event);
+ index = event_queue_insert_sorted_after (events, index,
+ TPL_EVENT (event));
+ g_hash_table_insert (superseded_links, (gpointer) supersedes_token,
+ index);
+ return index;
+}
+
/* returns a Glist of TplEvent instances */
static void
log_store_xml_get_events_for_file (TplLogStoreXml *self,
@@ -1278,6 +1340,7 @@ log_store_xml_get_events_for_file (TplLogStoreXml *self,
gchar *tmp;
gchar *target_id;
gchar *self_id;
+ GHashTable *supersedes_links;
GError *error = NULL;
guint num_events = 0;
GList *index;
@@ -1340,6 +1403,11 @@ log_store_xml_get_events_for_file (TplLogStoreXml *self,
g_free (dirname);
g_free (tmp);
+ /* Temporary hash from borrowed supersedes-token to borrowed link in
+ * events, so that we can efficiently replace repeatedly superseded
+ * events as their replacements come in. */
+ supersedes_links = g_hash_table_new (g_str_hash, g_str_equal);
+
/* Now get the events. */
index = events->head;
for (node = log_node->children; node; node = node->next)
@@ -1348,15 +1416,18 @@ log_store_xml_get_events_for_file (TplLogStoreXml *self,
if (type == TPL_TYPE_TEXT_EVENT
&& strcmp ((const gchar *) node->name, "message") == 0)
- event = parse_text_node (self, node, is_room, target_id, self_id,
- account);
+ {
+ event = parse_text_node (self, node, is_room, target_id, self_id,
+ account);
+ index = event_queue_add_text_event (events, index,
+ supersedes_links, TPL_TEXT_EVENT (event));
+ num_events++;
+ }
else if (type == TPL_TYPE_CALL_EVENT
&& strcmp ((const char*) node->name, "call") == 0)
- event = parse_call_node (self, node, is_room, target_id, self_id,
- account);
-
- if (event != NULL)
{
+ event = parse_call_node (self, node, is_room, target_id, self_id,
+ account);
index = event_queue_insert_sorted_after (events, index, event);
num_events++;
}
@@ -1367,6 +1438,7 @@ log_store_xml_get_events_for_file (TplLogStoreXml *self,
g_free (target_id);
xmlFreeDoc (doc);
xmlFreeParserCtxt (ctxt);
+ g_hash_table_destroy (supersedes_links);
}