Ejemplo n.º 1
0
Archivo: mu-threader.c Proyecto: nd/mu
/* find a container for the given msgid; if it does not exist yet,
 * create a new one, and register it */
static MuContainer*
find_or_create (GHashTable *id_table, MuMsg *msg, guint docid)
{
	MuContainer *c;
	const char* msgid;

	g_return_val_if_fail (msg, NULL);
	g_return_val_if_fail (docid != 0, NULL);

	msgid = mu_msg_get_msgid (msg);
	if (!msgid)
		msgid = mu_msg_get_path (msg); /* fake it */

	c = g_hash_table_lookup (id_table, msgid);

	/* If id_table contains an empty MuContainer for this ID: * *
	 * Store this message in the MuContainer's message slot. */
	if (c) {
		if (!c->msg) {
			c->msg	  = mu_msg_ref (msg);
			c->docid  = docid;
			return c;
		} else {
			/* special case, not in the JWZ algorithm: the
			 * container exists already and has a message; this
			 * means that we are seeing *another message* with a
			 * message-id we already saw... create this message,
			 * and mark it as a duplicate, and a child of the one
			 * we saw before; use its path as a fake message-id
			 * */
			MuContainer *c2;
			const char* fake_msgid;

			fake_msgid = mu_msg_get_path (msg);

			c2	  = mu_container_new (msg, docid, fake_msgid);
			c2->flags = MU_CONTAINER_FLAG_DUP;
			c	  = mu_container_append_children (c, c2);

			g_hash_table_insert (id_table, (gpointer)fake_msgid, c2);

			return NULL; /* don't process this message further */
		}
	} else { /* Else: Create a new MuContainer object holding
		    this message; Index the MuContainer by
		    Message-ID in id_table. */
		c = mu_container_new (msg, docid, msgid);
		g_hash_table_insert (id_table, (gpointer)msgid, c);
		/* assert_no_duplicates (id_table); */

		return c;
	}
}
Ejemplo n.º 2
0
MuContainer*
mu_container_splice_grandchildren (MuContainer *parent, MuContainer *child)
{
	MuContainer *newchild;

	g_return_val_if_fail (parent, NULL);
	g_return_val_if_fail (child, NULL);
	g_return_val_if_fail (parent != child, NULL);

	newchild = child->child;
	child->child=NULL;

	return mu_container_append_children (parent, newchild);
}
Ejemplo n.º 3
0
Archivo: mu-threader.c Proyecto: nd/mu
static void /* 1B */
handle_references (GHashTable *id_table, MuContainer *c)
{
	const GSList *refs, *cur;
	MuContainer *parent;
	gboolean created;

	refs = mu_msg_get_references (c->msg);
	if (!refs)
		return; /* nothing to do */

	/* For each element in the message's References field:

	   Find a MuContainer object for the given Message-ID: If
	   there's one in id_table use that; Otherwise, make (and
	   index) one with a null Message. */

	/* go over over our list of refs, until 1 before the last... */
	created = FALSE;
	for (parent = NULL, cur = refs; cur; cur = g_slist_next (cur)) {

		MuContainer *child;
		child = find_or_create_referred (id_table, (gchar*)cur->data,
						 &created);

		/*Link the References field's MuContainers together in
		 * the order implied by the References header.

		 If they are already linked, don't change the existing
		 links.  Do not add a link if adding that link would
		 introduce a loop: that is, before asserting A->B,
		 search down the children of B to see if A is
		 reachable, and also search down the children of A to
		 see if B is reachable. If either is already reachable
		 as a child of the other, don't add the link. */

		if (child_elligible (parent, child, created))
			parent = mu_container_append_children (parent, child);

		parent = child;
	}

	/* 'parent' points to the last ref: our direct parent;

	   Set the parent of this message to be the last element in
	   References. Note that this message may have a parent
	   already: this can happen because we saw this ID in a
	   References field, and presumed a parent based on the other
	   entries in that field. Now that we have the actual message,
	   we can be more definitive, so throw away the old parent and
	   use this new one. Find this MuContainer in the parent's
	   children list, and unlink it.

	   Note that this could cause this message to now have no
	   parent, if it has no references field, but some message
	   referred to it as the non-first element of its
	   references. (Which would have been some kind of lie...)

	   Note that at all times, the various ``parent'' and ``child'' fields
	   must be kept inter-consistent. */

	/* optimization: if the the message was newly added, it's by
	 * definition not reachable yet */

	if (child_elligible (parent, c, created))
		parent = mu_container_append_children (parent, c);
}