[dovecot-cvs] dovecot/src/imap cmd-thread.c, 1.11, 1.12 imap-thread.c, 1.33, 1.34 imap-thread.h, 1.4, 1.5
tss at dovecot.org
tss at dovecot.org
Wed Dec 20 03:38:44 UTC 2006
Update of /var/lib/cvs/dovecot/src/imap
In directory talvi:/tmp/cvs-serv32714/imap
Modified Files:
cmd-thread.c imap-thread.c imap-thread.h
Log Message:
Implemented X-REFERENCES2 threading. Two differences to standard REFERENCES:
Sort root nodes by the newest mail in the thread, and don't do base subject
merging.
Index: cmd-thread.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/imap/cmd-thread.c,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -d -r1.11 -r1.12
--- cmd-thread.c 13 Jan 2006 20:25:59 -0000 1.11
+++ cmd-thread.c 20 Dec 2006 03:38:41 -0000 1.12
@@ -38,6 +38,8 @@
str = IMAP_ARG_STR(args);
if (strcasecmp(str, "REFERENCES") == 0)
threading = MAIL_THREAD_REFERENCES;
+ else if (strcasecmp(str, "X-REFERENCES2") == 0)
+ threading = MAIL_THREAD_REFERENCES2;
else if (strcasecmp(str, "ORDEREDSUBJECT") == 0) {
client_send_command_error(cmd,
"ORDEREDSUBJECT threading is currently not supported.");
Index: imap-thread.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/imap/imap-thread.c,v
retrieving revision 1.33
retrieving revision 1.34
diff -u -d -r1.33 -r1.34
--- imap-thread.c 15 Dec 2006 23:50:22 -0000 1.33
+++ imap-thread.c 20 Dec 2006 03:38:41 -0000 1.34
@@ -142,6 +142,7 @@
struct mailbox_transaction_context *t;
struct mailbox *box;
struct ostream *output;
+ enum mail_thread_type thread_type;
struct mail *tmp_mail;
struct mail_thread_rec tmp_rec;
@@ -158,6 +159,7 @@
struct hash_table *subject_hash;
ARRAY_DEFINE(roots, struct mail_thread_root_rec *);
ARRAY_DEFINE(moved_recs, struct mail_thread_moved_rec);
+ uint32_t *alt_dates;
unsigned int cmp_match_count;
uint32_t cmp_last_idx;
@@ -188,6 +190,8 @@
static void mail_thread_deinit(struct imap_thread_mailbox *tbox,
struct thread_context *ctx)
{
+ i_free(ctx->alt_dates);
+
if (ctx->msgid_hash != tbox->msgid_hash)
mail_hash_free(&ctx->msgid_hash);
else
@@ -491,8 +495,8 @@
struct mail *mail;
int ret, try;
- if (type != MAIL_THREAD_REFERENCES)
- i_fatal("Only REFERENCES threading supported");
+ i_assert(type == MAIL_THREAD_REFERENCES ||
+ type == MAIL_THREAD_REFERENCES2);
if (tbox->msgid_hash == NULL)
imap_thread_hash_init(cmd->client->mailbox, TRUE);
@@ -503,6 +507,7 @@
ctx = t_new(struct thread_context, 1);
tbox->ctx = ctx;
ctx->msgid_hash = tbox->msgid_hash;
+ ctx->thread_type = type;
for (try = 0; try < 2; try++) {
ret = 0;
@@ -1591,6 +1596,16 @@
qsort(roots, count, sizeof(*roots), mail_thread_root_rec_sort_cmp);
}
+static void update_root_dates(struct thread_context *ctx)
+{
+ struct mail_thread_root_rec **roots;
+ unsigned int i, count;
+
+ roots = array_get_modifiable(&ctx->roots, &count);
+ for (i = 0; i < count; i++)
+ roots[i]->sent_date = ctx->alt_dates[roots[i]->idx];
+}
+
static int str_add_id(struct thread_context *ctx, string_t *str, uint32_t uid)
{
if (!ctx->id_is_uid) {
@@ -1773,6 +1788,35 @@
return 0;
}
+static int update_altdates(struct thread_context *ctx, uint32_t idx,
+ const struct mail_thread_rec *rec)
+{
+ const struct mail_hash_header *hdr;
+ uint32_t timestamp = rec->sent_date;
+
+ hdr = mail_hash_get_header(ctx->msgid_hash);
+ for (;;) {
+ if (ctx->alt_dates[idx] < timestamp) {
+ /* @UNSAFE */
+ ctx->alt_dates[idx] = timestamp;
+ }
+
+ idx = rec->parent_idx;
+ if (idx == 0)
+ break;
+
+ if (idx > hdr->record_count) {
+ mail_hash_set_corrupted(ctx->msgid_hash,
+ "parent_idx too large");
+ return -1;
+ }
+
+ if (mail_thread_rec_idx(ctx, idx, &rec) < 0)
+ return -1;
+ }
+ return 0;
+}
+
static int mail_thread_finish(struct thread_context *ctx)
{
const struct mail_hash_header *hdr;
@@ -1789,10 +1833,16 @@
/* (2) save root nodes */
i_array_init(&ctx->roots, I_MIN(128, hdr->record_count));
+ if (ctx->thread_type == MAIL_THREAD_REFERENCES2)
+ ctx->alt_dates = i_new(uint32_t, hdr->record_count + 1);
for (idx = 1; idx <= hdr->record_count; idx++) {
if (mail_thread_rec_idx(ctx, idx, &rec) < 0)
return -1;
- if (rec->parent_idx == 0 && rec->rec.uid != (uint32_t)-1) {
+
+ if (MAIL_HASH_RECORD_IS_DELETED(&rec->rec))
+ continue;
+
+ if (rec->parent_idx == 0) {
/* use the first non-dummy message's uid/sent_date
so that the roots can be directly sorted */
if (mail_thread_rec_get_nondummy(ctx, rec, &rec) < 0)
@@ -1805,19 +1855,27 @@
root_rec->sent_date = rec->sent_date;
array_append(&ctx->roots, &root_rec, 1);
}
+
+ if (ctx->thread_type == MAIL_THREAD_REFERENCES2)
+ update_altdates(ctx, idx, rec);
}
- /* (4) */
- sort_root_nodes(ctx);
+ if (ctx->thread_type == MAIL_THREAD_REFERENCES2) {
+ update_root_dates(ctx);
+ i_free_and_null(ctx->alt_dates);
+ } else {
+ /* (4) */
+ sort_root_nodes(ctx);
- /* (5) Gather together messages under the root that have the same
- base subject text. */
- if (gather_base_subjects(ctx) < 0)
- return -1;
+ /* (5) Gather together messages under the root that have
+ the same base subject text. */
+ if (gather_base_subjects(ctx) < 0)
+ return -1;
- /* (5.C) Merge threads with the same thread subject. */
- if (merge_subject_threads(ctx) < 0)
- return -1;
+ /* (5.C) Merge threads with the same thread subject. */
+ if (merge_subject_threads(ctx) < 0)
+ return -1;
+ }
/* (6) Sort again and send replies */
t_push();
Index: imap-thread.h
===================================================================
RCS file: /var/lib/cvs/dovecot/src/imap/imap-thread.h,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- imap-thread.h 11 Jul 2006 16:07:57 -0000 1.4
+++ imap-thread.h 20 Dec 2006 03:38:41 -0000 1.5
@@ -4,7 +4,8 @@
enum mail_thread_type {
MAIL_THREAD_NONE,
MAIL_THREAD_ORDEREDSUBJECT,
- MAIL_THREAD_REFERENCES
+ MAIL_THREAD_REFERENCES,
+ MAIL_THREAD_REFERENCES2
};
int imap_thread(struct client_command_context *cmd, const char *charset,
More information about the dovecot-cvs
mailing list