Mercurial > dovecot > core-2.2
changeset 9685:be433e394f69 HEAD
maildir: Support saving messages with specified UIDs.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Mon, 27 Jul 2009 19:02:12 -0400 |
parents | fb8bc26d7194 |
children | 4d5cc6ce68aa |
files | src/lib-storage/index/maildir/maildir-save.c src/lib-storage/index/maildir/maildir-storage.h src/lib-storage/index/maildir/maildir-uidlist.c src/lib-storage/index/maildir/maildir-uidlist.h |
diffstat | 4 files changed, 73 insertions(+), 29 deletions(-) [+] |
line wrap: on
line diff
--- 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 @@ uoff_t size, vsize; enum mail_flags flags; + unsigned int preserve_filename:1; unsigned int keywords_count; /* unsigned int keywords[]; */ }; @@ -131,8 +132,8 @@ 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 @@ } /* 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 @@ ctx->input = input; ctx->cur_dest_mail = _ctx->dest_mail; } - return ctx->seq; + return mf; } static bool @@ -213,12 +214,12 @@ 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_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 @@ 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 @@ 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)
--- 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 @@ 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);
--- 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 @@ 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 @@ (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 @@ 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 @@ /* 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 @@ 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); @@ -1637,6 +1642,13 @@ 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; const char *p, *dir; @@ -1656,7 +1668,7 @@ } 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 @@ 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 @@ 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 @@ 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 @@ 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); + qsort(recs + ctx->first_new_pos, count - ctx->first_new_pos, + sizeof(*recs), maildir_assign_uid_cmp); - for (dest = ctx->first_nouid_pos; dest < count; dest++) { + 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 @@ 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 @@ 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 {
--- 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 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, const char *filename); const char *