]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
Fixes for syncing mails that are kept in new/ dir.
authorTimo Sirainen <tss@iki.fi>
Thu, 29 May 2003 22:48:02 +0000 (01:48 +0300)
committerTimo Sirainen <tss@iki.fi>
Thu, 29 May 2003 22:48:02 +0000 (01:48 +0300)
--HG--
branch : HEAD

src/lib-index/mail-index-open.c
src/lib-index/mail-index.h
src/lib-index/maildir/maildir-sync.c

index 3fc62f4296c1169c22c35c40f47962de03c02f9f..9709e6b667f0a885d9e9b8f03b712be3428cfa48 100644 (file)
@@ -27,6 +27,9 @@ static int mail_index_open_init(struct mail_index *index,
 
        hdr = index->header;
 
+       index->maildir_have_new =
+               (hdr->flags & MAIL_INDEX_FLAG_MAILDIR_NEW) != 0;
+
        /* update \Recent message counters */
        if ((flags & MAIL_INDEX_OPEN_FLAG_UPDATE_RECENT) != 0 &&
            hdr->last_nonrecent_uid != hdr->next_uid-1) {
index 48371de52c91a4ad7107127e2eb40fa61befa63a..0915c228f69aacea0f7c2d82d6f8351e2870f542 100644 (file)
@@ -29,14 +29,15 @@ enum mail_index_header_flag {
        /* Rebuild flag is set while index is being rebuilt or when
           some error is noticed in the index file. If this flag is set,
           the index shouldn't be used before rebuilding it. */
-       MAIL_INDEX_FLAG_REBUILD                 = 0x01,
-       MAIL_INDEX_FLAG_FSCK                    = 0x02,
-       MAIL_INDEX_FLAG_CACHE_FIELDS            = 0x04,
-       MAIL_INDEX_FLAG_COMPRESS                = 0x08,
-       MAIL_INDEX_FLAG_COMPRESS_DATA           = 0x10,
-       MAIL_INDEX_FLAG_REBUILD_TREE            = 0x20,
-       MAIL_INDEX_FLAG_DIRTY_MESSAGES          = 0x40,
-       MAIL_INDEX_FLAG_DIRTY_CUSTOMFLAGS       = 0x80
+       MAIL_INDEX_FLAG_REBUILD                 = 0x0001,
+       MAIL_INDEX_FLAG_FSCK                    = 0x0002,
+       MAIL_INDEX_FLAG_CACHE_FIELDS            = 0x0004,
+       MAIL_INDEX_FLAG_COMPRESS                = 0x0008,
+       MAIL_INDEX_FLAG_COMPRESS_DATA           = 0x0010,
+       MAIL_INDEX_FLAG_REBUILD_TREE            = 0x0020,
+       MAIL_INDEX_FLAG_DIRTY_MESSAGES          = 0x0040,
+       MAIL_INDEX_FLAG_DIRTY_CUSTOMFLAGS       = 0x0080,
+       MAIL_INDEX_FLAG_MAILDIR_NEW             = 0x0100
 };
 
 enum mail_data_field {
index 7df3ed3d5e13cd34d25e618cfa0a7f6b8889de9a..f460aef298570f38962a837ee493bb737bdcfb82 100644 (file)
@@ -436,7 +436,7 @@ static void uidlist_hash_get_filenames(void *key, void *value, void *context)
        struct maildir_hash_rec *hash_rec = value;
 
        if (ACTION(hash_rec) == MAILDIR_FILE_ACTION_NEW)
-               buffer_append(buf, (const void *) &key, sizeof(key));
+               buffer_append(buf, (const void *) &key, sizeof(const char *));
 }
 
 static int maildir_full_sync_finish(struct maildir_sync_context *ctx)
@@ -637,8 +637,8 @@ static int maildir_full_sync_finish(struct maildir_sync_context *ctx)
        buf = buffer_create_static_hard(ctx->pool,
                                        ctx->new_count * sizeof(const char *));
        hash_foreach(ctx->files, uidlist_hash_get_filenames, buf);
-       i_assert(buffer_get_used_size(buf) / sizeof(const char *) <=
-                ctx->new_count);
+       i_assert(buffer_get_used_size(buf) ==
+                ctx->new_count * sizeof(const char *));
 
        new_files = buffer_get_modifyable_data(buf, NULL);
        qsort(new_files, ctx->new_count, sizeof(const char *),
@@ -669,7 +669,8 @@ static int maildir_full_sync_finish(struct maildir_sync_context *ctx)
        return TRUE;
 }
 
-static int maildir_full_sync_init(struct maildir_sync_context *ctx)
+static int maildir_full_sync_init(struct maildir_sync_context *ctx,
+                                 int only_new)
 {
        struct mail_index *index = ctx->index;
        struct mail_index_record *rec;
@@ -697,6 +698,7 @@ static int maildir_full_sync_init(struct maildir_sync_context *ctx)
        ctx->files = hash_create(default_pool, ctx->pool,
                                 index->header->messages_count * 2,
                                 maildir_hash, maildir_cmp);
+       ctx->new_count = 0;
 
        have_new = FALSE;
 
@@ -709,20 +711,23 @@ static int maildir_full_sync_init(struct maildir_sync_context *ctx)
                if ((rec->index_flags & INDEX_MAIL_FLAG_MAILDIR_NEW) != 0)
                        have_new = TRUE;
 
-               hash_rec = p_new(ctx->pool, struct maildir_hash_rec, 1);
-               hash_rec->rec = rec;
-               hash_rec->action = MAILDIR_FILE_ACTION_EXPUNGE;
+               if (!only_new ||
+                   (rec->index_flags & INDEX_MAIL_FLAG_MAILDIR_NEW) != 0) {
+                       hash_rec = p_new(ctx->pool, struct maildir_hash_rec, 1);
+                       hash_rec->rec = rec;
+                       hash_rec->action = MAILDIR_FILE_ACTION_EXPUNGE;
 
-               if (hash_lookup(ctx->files, fname) != NULL) {
-                       index_set_corrupted(index, "Duplicated message %s",
-                                           fname);
-                       return FALSE;
-               }
+                       if (hash_lookup(ctx->files, fname) != NULL) {
+                               index_set_corrupted(index,
+                                       "Duplicated message %s", fname);
+                               return FALSE;
+                       }
 
-               /* WARNING: index must not be modified as long as these
-                  hash keys exist. Modifying might change the mmap base
-                  address. */
-               hash_insert(ctx->files, (void *) fname, hash_rec);
+                       /* WARNING: index must not be modified as long as
+                          these hash keys exist. Modifying might change the
+                          mmap base address. */
+                       hash_insert(ctx->files, (void *) fname, hash_rec);
+               }
 
                rec = index->next(index, rec);
        }
@@ -892,6 +897,7 @@ static int maildir_full_sync_dirs(struct maildir_sync_context *ctx)
                if (!maildir_full_sync_dir(ctx, ctx->new_dir, TRUE,
                                           ctx->new_dirp, ctx->new_dent))
                        return FALSE;
+                ctx->new_dent = NULL;
        }
 
        dirp = opendir(ctx->cur_dir);
@@ -911,6 +917,25 @@ static int maildir_full_sync_dirs(struct maildir_sync_context *ctx)
        return !failed;
 }
 
+static int maildir_sync_new_dir_full(struct maildir_sync_context *ctx)
+{
+       if (!ctx->index->set_lock(ctx->index, MAIL_LOCK_EXCLUSIVE))
+               return FALSE;
+
+       if (!maildir_full_sync_init(ctx, TRUE))
+               return FALSE;
+
+       if (!maildir_full_sync_dir(ctx, ctx->new_dir, TRUE,
+                                  ctx->new_dirp, ctx->new_dent))
+               return FALSE;
+       ctx->new_dent = NULL;
+
+       if (!maildir_full_sync_finish(ctx))
+               return FALSE;
+
+       return TRUE;
+}
+
 static int maildir_sync_new_dir(struct maildir_sync_context *ctx,
                                int move_to_cur, int append_index)
 {
@@ -919,6 +944,14 @@ static int maildir_sync_new_dir(struct maildir_sync_context *ctx,
        const char *final_dir;
 
        if (append_index) {
+               if (ctx->index->maildir_have_new) {
+                       /* some of the mails in new/ are already indexed.
+                          we'll have to do a full sync.
+                          FIXME: or not really, just full sync for mails
+                          in new/ */
+                       return maildir_sync_new_dir_full(ctx);
+               }
+
                if (!ctx->index->set_lock(ctx->index, MAIL_LOCK_EXCLUSIVE))
                        return FALSE;
 
@@ -988,8 +1021,6 @@ static int maildir_sync_new_dir(struct maildir_sync_context *ctx,
                }
 
                if (append_index) {
-                       /* FIXME: it may be already indexed if it couldn't
-                          be moved to cur! */
                        if (!move_to_cur)
                                ctx->index->maildir_have_new = TRUE;
 
@@ -1026,7 +1057,7 @@ static int maildir_sync_cur_dir(struct maildir_sync_context *ctx)
        if (!index->set_lock(index, MAIL_LOCK_EXCLUSIVE))
                return FALSE;
 
-       if (!maildir_full_sync_init(ctx) ||
+       if (!maildir_full_sync_init(ctx, FALSE) ||
            !maildir_full_sync_dirs(ctx) ||
            !maildir_full_sync_finish(ctx))
                return FALSE;
@@ -1099,6 +1130,13 @@ static int maildir_index_sync_context(struct maildir_sync_context *ctx,
                        return FALSE;
        }
 
+       if (index->lock_type == MAIL_LOCK_EXCLUSIVE) {
+               if (index->maildir_have_new)
+                       index->header->flags |= MAIL_INDEX_FLAG_MAILDIR_NEW;
+               else
+                       index->header->flags &= ~MAIL_INDEX_FLAG_MAILDIR_NEW;
+       }
+
        if (cur_mtime < ioloop_time - MAILDIR_SYNC_SECS)
                index->maildir_cur_dirty = 0;
        else
@@ -1190,7 +1228,7 @@ static int maildir_index_sync_context_readonly(struct maildir_sync_context *ctx)
           directly. but don't rely on it. */
        (void)index->try_lock(index, MAIL_LOCK_EXCLUSIVE);
 
-       if (!maildir_full_sync_init(ctx) ||
+       if (!maildir_full_sync_init(ctx, FALSE) ||
            !maildir_full_sync_dirs(ctx) ||
            !maildir_full_sync_finish_readonly(ctx))
                return FALSE;