dovecot-2.0: maildir: Support saving messages with specified UIDs.
dovecot at dovecot.org
dovecot at dovecot.org
Tue Jul 28 02:04:46 EEST 2009
details: http://hg.dovecot.org/dovecot-2.0/rev/be433e394f69
changeset: 9685:be433e394f69
user: Timo Sirainen <tss at iki.fi>
date: Mon Jul 27 19:02:12 2009 -0400
description:
maildir: Support saving messages with specified UIDs.
diffstat:
4 files changed, 74 insertions(+), 30 deletions(-)
src/lib-storage/index/maildir/maildir-save.c | 33 ++++++++---
src/lib-storage/index/maildir/maildir-storage.h | 4 -
src/lib-storage/index/maildir/maildir-uidlist.c | 64 ++++++++++++++++-------
src/lib-storage/index/maildir/maildir-uidlist.h | 3 +
diffs (truncated from 302 to 300 lines):
diff -r fb8bc26d7194 -r be433e394f69 src/lib-storage/index/maildir/maildir-save.c
--- a/src/lib-storage/index/maildir/maildir-save.c Mon Jul 27 19:00:56 2009 -0400
+++ b/src/lib-storage/index/maildir/maildir-save.c Mon Jul 27 19:02:12 2009 -0400
@@ -32,6 +32,7 @@ struct maildir_filename {
uoff_t size, vsize;
enum mail_flags flags;
+ unsigned int preserve_filename:1;
unsigned int keywords_count;
/* unsigned int keywords[]; */
};
@@ -131,8 +132,8 @@ maildir_save_transaction_init(struct mai
return ctx;
}
-uint32_t maildir_save_add(struct mail_save_context *_ctx,
- const char *base_fname)
+struct maildir_filename *
+maildir_save_add(struct mail_save_context *_ctx, const char *base_fname)
{
struct maildir_save_context *ctx = (struct maildir_save_context *)_ctx;
struct maildir_filename *mf;
@@ -171,7 +172,7 @@ uint32_t maildir_save_add(struct mail_sa
}
/* insert into index */
- mail_index_append(ctx->trans, 0, &ctx->seq);
+ mail_index_append(ctx->trans, _ctx->uid, &ctx->seq);
mail_index_update_flags(ctx->trans, ctx->seq,
MODIFY_REPLACE, _ctx->flags);
if (_ctx->keywords != NULL) {
@@ -202,7 +203,7 @@ uint32_t maildir_save_add(struct mail_sa
ctx->input = input;
ctx->cur_dest_mail = _ctx->dest_mail;
}
- return ctx->seq;
+ return mf;
}
static bool
@@ -213,12 +214,12 @@ maildir_get_updated_filename(struct mail
const char *basename = mf->basename;
if (ctx->mbox->storage->save_size_in_filename &&
- mf->size != (uoff_t)-1) {
+ mf->size != (uoff_t)-1 && !mf->preserve_filename) {
basename = t_strdup_printf("%s,%c=%"PRIuUOFF_T, basename,
MAILDIR_EXTRA_FILE_SIZE, mf->size);
}
- if (mf->vsize != (uoff_t)-1) {
+ if (mf->vsize != (uoff_t)-1 && !mf->preserve_filename) {
basename = t_strdup_printf("%s,%c=%"PRIuUOFF_T, basename,
MAILDIR_EXTRA_VIRTUAL_SIZE,
mf->vsize);
@@ -370,6 +371,7 @@ int maildir_save_begin(struct mail_save_
int maildir_save_begin(struct mail_save_context *_ctx, struct istream *input)
{
struct maildir_save_context *ctx = (struct maildir_save_context *)_ctx;
+ struct maildir_filename *mf;
T_BEGIN {
/* create a new file in tmp/ directory */
@@ -383,7 +385,9 @@ int maildir_save_begin(struct mail_save_
ctx->input = i_stream_create_crlf(input);
else
ctx->input = i_stream_create_lf(input);
- maildir_save_add(_ctx, fname);
+ mf = maildir_save_add(_ctx, fname);
+ if (fname == _ctx->guid)
+ mf->preserve_filename = TRUE;
}
} T_END;
@@ -728,22 +732,31 @@ maildir_save_move_files_to_newcur(struct
static void maildir_save_sync_uidlist(struct maildir_save_context *ctx)
{
+ struct mailbox_transaction_context *t = ctx->ctx.transaction;
struct maildir_filename *mf;
+ struct seq_range_iter iter;
enum maildir_uidlist_rec_flag flags;
- bool newdir;
+ unsigned int n = 0;
+ uint32_t uid;
+ bool newdir, bret;
int ret;
+ seq_range_array_iter_init(&iter, &t->changes->saved_uids);
for (mf = ctx->files; mf != NULL; mf = mf->next) T_BEGIN {
const char *dest;
+
+ bret = seq_range_array_iter_nth(&iter, n++, &uid);
+ i_assert(bret);
newdir = maildir_get_updated_filename(ctx, mf, &dest);
flags = MAILDIR_UIDLIST_REC_FLAG_RECENT;
if (newdir)
flags |= MAILDIR_UIDLIST_REC_FLAG_NEW_DIR;
- ret = maildir_uidlist_sync_next(ctx->uidlist_sync_ctx,
- dest, flags);
+ ret = maildir_uidlist_sync_next_uid(ctx->uidlist_sync_ctx,
+ dest, uid, flags);
i_assert(ret > 0);
} T_END;
+ i_assert(!seq_range_array_iter_nth(&iter, n, &uid));
}
int maildir_transaction_save_commit_pre(struct maildir_save_context *ctx)
diff -r fb8bc26d7194 -r be433e394f69 src/lib-storage/index/maildir/maildir-storage.h
--- a/src/lib-storage/index/maildir/maildir-storage.h Mon Jul 27 19:00:56 2009 -0400
+++ b/src/lib-storage/index/maildir/maildir-storage.h Mon Jul 27 19:02:12 2009 -0400
@@ -133,8 +133,8 @@ void maildir_save_cancel(struct mail_sav
struct maildir_save_context *
maildir_save_transaction_init(struct maildir_transaction_context *t);
-uint32_t maildir_save_add(struct mail_save_context *ctx,
- const char *base_fname);
+struct maildir_filename *
+maildir_save_add(struct mail_save_context *_ctx, const char *base_fname);
const char *maildir_save_file_get_path(struct mailbox_transaction_context *t,
uint32_t seq);
diff -r fb8bc26d7194 -r be433e394f69 src/lib-storage/index/maildir/maildir-uidlist.c
--- a/src/lib-storage/index/maildir/maildir-uidlist.c Mon Jul 27 19:00:56 2009 -0400
+++ b/src/lib-storage/index/maildir/maildir-uidlist.c Mon Jul 27 19:02:12 2009 -0400
@@ -110,7 +110,7 @@ struct maildir_uidlist_sync_ctx {
ARRAY_TYPE(maildir_uidlist_rec_p) records;
struct hash_table *files;
- unsigned int first_unwritten_pos, first_nouid_pos;
+ unsigned int first_unwritten_pos, first_new_pos;
unsigned int new_files_count;
unsigned int finish_change_counter;
@@ -1551,7 +1551,7 @@ int maildir_uidlist_sync_init(struct mai
(sync_flags & MAILDIR_UIDLIST_SYNC_PARTIAL) != 0;
ctx->locked = locked;
ctx->first_unwritten_pos = (unsigned int)-1;
- ctx->first_nouid_pos = (unsigned int)-1;
+ ctx->first_new_pos = (unsigned int)-1;
if (ctx->partial) {
if ((sync_flags & MAILDIR_UIDLIST_SYNC_KEEP_STATE) == 0) {
@@ -1574,7 +1574,7 @@ int maildir_uidlist_sync_init(struct mai
static void
maildir_uidlist_sync_next_partial(struct maildir_uidlist_sync_ctx *ctx,
- const char *filename,
+ const char *filename, uint32_t uid,
enum maildir_uidlist_rec_flag flags)
{
struct maildir_uidlist *uidlist = ctx->uidlist;
@@ -1588,8 +1588,8 @@ maildir_uidlist_sync_next_partial(struct
/* we can't add it, so just ignore it */
return;
}
- if (ctx->first_nouid_pos == (unsigned int)-1)
- ctx->first_nouid_pos = array_count(&uidlist->records);
+ if (ctx->first_new_pos == (unsigned int)-1)
+ ctx->first_new_pos = array_count(&uidlist->records);
ctx->new_files_count++;
ctx->changed = TRUE;
@@ -1606,6 +1606,11 @@ maildir_uidlist_sync_next_partial(struct
array_append(&uidlist->records, &rec, 1);
uidlist->change_counter++;
}
+ if (uid != 0) {
+ rec->uid = uid;
+ if (uidlist->next_uid <= uid)
+ uidlist->next_uid = uid + 1;
+ }
rec->flags = (rec->flags | flags) & ~MAILDIR_UIDLIST_REC_FLAG_NONSYNCED;
rec->filename = p_strdup(uidlist->record_pool, filename);
@@ -1636,6 +1641,13 @@ int maildir_uidlist_sync_next(struct mai
int maildir_uidlist_sync_next(struct maildir_uidlist_sync_ctx *ctx,
const char *filename,
enum maildir_uidlist_rec_flag flags)
+{
+ return maildir_uidlist_sync_next_uid(ctx, filename, 0, flags);
+}
+
+int maildir_uidlist_sync_next_uid(struct maildir_uidlist_sync_ctx *ctx,
+ const char *filename, uint32_t uid,
+ enum maildir_uidlist_rec_flag flags)
{
struct maildir_uidlist *uidlist = ctx->uidlist;
struct maildir_uidlist_rec *rec, *old_rec;
@@ -1656,7 +1668,7 @@ int maildir_uidlist_sync_next(struct mai
}
if (ctx->partial) {
- maildir_uidlist_sync_next_partial(ctx, filename, flags);
+ maildir_uidlist_sync_next_partial(ctx, filename, uid, flags);
return 1;
}
@@ -1693,6 +1705,11 @@ int maildir_uidlist_sync_next(struct mai
array_append(&ctx->records, &rec, 1);
}
+ if (uid != 0) {
+ rec->uid = uid;
+ if (uidlist->next_uid <= uid)
+ uidlist->next_uid = uid + 1;
+ }
rec->flags = (rec->flags | flags) & ~MAILDIR_UIDLIST_REC_FLAG_NONSYNCED;
rec->filename = p_strdup(ctx->record_pool, filename);
@@ -1720,9 +1737,9 @@ void maildir_uidlist_sync_remove(struct
i_assert(ctx->first_unwritten_pos > idx);
ctx->first_unwritten_pos--;
}
- if (ctx->first_nouid_pos != (unsigned int)-1) {
- i_assert(ctx->first_nouid_pos > idx);
- ctx->first_nouid_pos--;
+ if (ctx->first_new_pos != (unsigned int)-1) {
+ i_assert(ctx->first_new_pos > idx);
+ ctx->first_new_pos--;
}
ctx->changed = TRUE;
@@ -1762,10 +1779,16 @@ maildir_uidlist_get_full_filename(struct
return rec == NULL ? NULL : rec->filename;
}
-static int maildir_time_cmp(const void *p1, const void *p2)
+static int maildir_assign_uid_cmp(const void *p1, const void *p2)
{
const struct maildir_uidlist_rec *const *rec1 = p1, *const *rec2 = p2;
+ if ((*rec1)->uid != (*rec2)->uid) {
+ if ((*rec1)->uid < (*rec2)->uid)
+ return -1;
+ else
+ return 1;
+ }
return maildir_filename_sort_cmp((*rec1)->filename, (*rec2)->filename);
}
@@ -1775,17 +1798,22 @@ static void maildir_uidlist_assign_uids(
unsigned int dest, count;
i_assert(UIDLIST_ALLOW_WRITING(ctx->uidlist));
- i_assert(ctx->first_nouid_pos != (unsigned int)-1);
+ i_assert(ctx->first_new_pos != (unsigned int)-1);
if (ctx->first_unwritten_pos == (unsigned int)-1)
- ctx->first_unwritten_pos = ctx->first_nouid_pos;
+ ctx->first_unwritten_pos = ctx->first_new_pos;
/* sort new files and assign UIDs for them */
recs = array_get_modifiable(&ctx->uidlist->records, &count);
- qsort(recs + ctx->first_nouid_pos, count - ctx->first_nouid_pos,
- sizeof(*recs), maildir_time_cmp);
-
- for (dest = ctx->first_nouid_pos; dest < count; dest++) {
+ qsort(recs + ctx->first_new_pos, count - ctx->first_new_pos,
+ sizeof(*recs), maildir_assign_uid_cmp);
+
+ for (dest = ctx->first_new_pos; dest < count; dest++) {
+ if (recs[dest]->uid == (uint32_t)-1)
+ break;
+ }
+
+ for (; dest < count; dest++) {
i_assert(recs[dest]->uid == (uint32_t)-1);
i_assert(ctx->uidlist->next_uid < (uint32_t)-1);
recs[dest]->uid = ctx->uidlist->next_uid++;
@@ -1796,7 +1824,7 @@ static void maildir_uidlist_assign_uids(
ctx->uidlist->last_seen_uid = ctx->uidlist->next_uid-1;
ctx->new_files_count = 0;
- ctx->first_nouid_pos = (unsigned int)-1;
+ ctx->first_new_pos = (unsigned int)-1;
ctx->uidlist->change_counter++;
ctx->finish_change_counter = ctx->uidlist->change_counter;
}
@@ -1822,7 +1850,7 @@ static void maildir_uidlist_swap(struct
ctx->record_pool = NULL;
if (ctx->new_files_count != 0) {
- ctx->first_nouid_pos = array_count(&uidlist->records) -
+ ctx->first_new_pos = array_count(&uidlist->records) -
ctx->new_files_count;
maildir_uidlist_assign_uids(ctx);
} else {
diff -r fb8bc26d7194 -r be433e394f69 src/lib-storage/index/maildir/maildir-uidlist.h
--- a/src/lib-storage/index/maildir/maildir-uidlist.h Mon Jul 27 19:00:56 2009 -0400
+++ b/src/lib-storage/index/maildir/maildir-uidlist.h Mon Jul 27 19:02:12 2009 -0400
@@ -110,6 +110,9 @@ int maildir_uidlist_sync_next(struct mai
int maildir_uidlist_sync_next(struct maildir_uidlist_sync_ctx *ctx,
const char *filename,
enum maildir_uidlist_rec_flag flags);
+int maildir_uidlist_sync_next_uid(struct maildir_uidlist_sync_ctx *ctx,
+ const char *filename, uint32_t uid,
+ enum maildir_uidlist_rec_flag flags);
void maildir_uidlist_sync_remove(struct maildir_uidlist_sync_ctx *ctx,
More information about the dovecot-cvs
mailing list