index-thread-links.c revision a68752dd4de71537a8f7d120aa299044727f125a
/* Copyright (c) 2002-2008 Dovecot authors, see the included COPYING file */
#include "lib.h"
#include "array.h"
#include "message-id.h"
#include "mail-storage.h"
#include "index-thread-private.h"
{
struct mail_thread_node *node;
else {
/* duplicate message-id, keep the original.
if the original ever gets expunged, rebuild. */
}
return msgid_idx;
}
const struct mail_thread_node *node,
const struct mail_thread_node *ancestor)
{
if (node->parent_idx == 0)
return FALSE;
}
return TRUE;
}
{
/* either child_idx or parent_idx may cause thread_nodes array to
grow. in such situation the other pointer may become invalid if
we don't get the pointers in correct order. */
if (child_idx < parent_idx) {
} else {
}
/* loops to itself - ignore */
return;
}
/* child is an ancestor of parent. Adding child -> parent_node
would introduce a loop. If any messages referencing the path
between parent_node's parent and child_node get expunged, we
have to rebuild the tree because the loop might break.
For example:
#1: a -> b (a.ref=1, b.ref=1)
#2: b -> a (a.ref=2, b.ref=2)
#3: c -> a -> b (a.ref=3, b.ref=3, c.ref=1)
Expunging #3 wouldn't break the loop, but expunging #1
would. */
do {
return;
/* The same link already exists */
return;
}
/* Set parent_node as child_node's parent */
if (child->parent_idx == 0) {
} else {
/* Conflicting parent already exists, keep the original */
if (MAIL_THREAD_NODE_EXISTS(child)) {
/* If this message gets expunged,
the parent is changed. */
} else {
/* Message doesn't exist, so it was one of the node's
children that created the original reference. If
that reference gets dropped, the parent is changed.
We could catch this in one of several ways:
a) Link to parent node gets unreferenced
b) Link to this node gets unreferenced
c) Any of the child nodes gets expunged
b) is probably the least likely to happen,
so use it */
}
}
}
static uint32_t
const struct mail_index_strmap_rec *msgid_map,
unsigned int *msgid_map_idx)
{
return 0;
msgid_map++;
*msgid_map_idx += 1;
*msgid_map_idx += 1;
}
return parent_idx;
}
const struct mail_index_strmap_rec *msgid_map,
unsigned int *msgid_map_idx)
{
struct mail_thread_node *node;
/* conflicting parent, remove it. */
node->parent_idx = 0;
/* If this message gets expunged, we have to revert back to
the original parent. */
}
if (parent_idx != 0)
*msgid_map_idx += 1;
}
static bool
{
if (parent->child_unref_rebuilds)
return FALSE;
if (child->parent_link_refcount == 0) {
/* we don't have a root anymore */
child->parent_idx = 0;
}
return TRUE;
}
const struct mail_index_strmap_rec *msgid_map,
unsigned int *msgid_map_idx)
{
struct mail_thread_node *node;
unsigned int count = 1;
/* this message was never added to the cache, skip */
return TRUE;
}
if (node->expunge_rebuilds) {
/* this catches the duplicate message-id case */
return FALSE;
}
/* update link refcounts */
count++;
return FALSE;
count++;
}
return FALSE;
}
/* mark this message as expunged */
/* we don't know (and don't want to waste time figuring out) if other
messages point to this removed message, so don't delete the node */
*msgid_map_idx += count;
return TRUE;
}