maildir-sync.c revision 31ddc75584c5cde53d2e78a737587f2e7fdcb0d2
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen 1. read files in maildir
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen 2. see if they're all found in uidlist read in memory
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen 3. if not, check if uidlist's mtime has changed and read it if so
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen 4. if still not, lock uidlist, sync it once more and generate UIDs for new
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen 5. apply changes in transaction log
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen 6. apply changes in maildir to index
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen/* Copyright (C) 2004 Timo Sirainen */
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen struct maildir_uidlist_sync_ctx *uidlist_sync_ctx;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenstatic int maildir_expunge(struct index_mailbox *ibox, const char *path,
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenstatic int maildir_sync_flags(struct index_mailbox *ibox, const char *path,
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen struct mail_index_sync_rec *syncrec = context;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen (void)maildir_filename_get_flags(path, &flags, custom_flags);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen mail_index_sync_flags_apply(syncrec, &flags8, custom_flags);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen newpath = maildir_filename_set_flags(path, flags8, custom_flags);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenstatic int maildir_sync_record(struct index_mailbox *ibox,
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen for (seq = syncrec->seq1; seq <= syncrec->seq2; seq++) {
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen if (mail_index_lookup_uid(view, seq, &uid) < 0)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen if (maildir_file_do(ibox, uid, maildir_expunge,
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen for (seq = syncrec->seq1; seq <= syncrec->seq2; seq++) {
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen if (mail_index_lookup_uid(view, seq, &uid) < 0)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen if (maildir_file_do(ibox, uid, maildir_sync_flags,
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenint maildir_sync_last_commit(struct index_mailbox *ibox)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen ret = mail_index_sync_begin(ibox->index, &sync_ctx, &view,
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen while ((ret = mail_index_sync_next(sync_ctx, &sync_rec)) > 0) {
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen if (maildir_sync_record(ibox, view, &sync_rec) < 0) {
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen // FIXME: this is bad - we have to fix this in some way
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenmaildir_sync_context_new(struct index_mailbox *ibox)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen ctx->new_dir = t_strconcat(ibox->path, "/new", NULL);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen ctx->cur_dir = t_strconcat(ibox->path, "/cur", NULL);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenstatic void maildir_sync_deinit(struct maildir_sync_context *ctx)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen (void)maildir_uidlist_sync_deinit(ctx->uidlist_sync_ctx);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenstatic int maildir_fix_duplicate(struct index_mailbox *ibox, const char *dir,
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen old_path = t_strconcat(dir, "/", old_fname, NULL);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen new_fname = maildir_generate_tmp_filename(&ioloop_timeval);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen new_path = t_strconcat(ibox->path, "/new/", new_fname, NULL);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen "rename(%s, %s) failed: %m", old_path, new_path);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic int maildir_scan_dir(struct maildir_sync_context *ctx, int new_dir)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct mail_storage *storage = ctx->ibox->box.storage;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const char *dir;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen str_printfa(src, "%s/%s", ctx->new_dir, dp->d_name);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen str_printfa(dest, "%s/%s", ctx->cur_dir, dp->d_name);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* moved - we'll look at it later in cur/ dir */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* not enough disk space, leave here */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen "rename(%s, %s) failed: %m",
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ret = maildir_uidlist_sync_next(ctx->uidlist_sync_ctx,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* possibly duplicate - try fixing it */
b35f7104715edee0cfac6d46ab0b342033867eb7Timo Sirainenstatic int maildir_sync_quick_check(struct maildir_sync_context *ctx,
659fe5d24825b160cae512538088020d97a60239Timo Sirainen new_mtime >= ibox->last_sync - MAILDIR_SYNC_SECS) {
659fe5d24825b160cae512538088020d97a60239Timo Sirainen (cur_mtime >= ibox->last_sync - MAILDIR_SYNC_SECS &&
659fe5d24825b160cae512538088020d97a60239Timo Sirainen ioloop_time - ibox->last_sync > MAILDIR_SYNC_SECS)) {
659fe5d24825b160cae512538088020d97a60239Timo Sirainen /* cur/ changed, or delayed cur/ check */
659fe5d24825b160cae512538088020d97a60239Timo Sirainenstatic int maildir_sync_index(struct maildir_sync_context *ctx)
b35f7104715edee0cfac6d46ab0b342033867eb7Timo Sirainen if (mail_index_sync_begin(ibox->index, &sync_ctx, &view,
b35f7104715edee0cfac6d46ab0b342033867eb7Timo Sirainen i_assert(ret == 0); /* view is locked, can't happen */
b35f7104715edee0cfac6d46ab0b342033867eb7Timo Sirainen trans = mail_index_transaction_begin(view, FALSE);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen iter = maildir_uidlist_iter_init(ibox->uidlist);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen while (maildir_uidlist_iter_next(iter, &uid, &uflags, &filename)) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen maildir_filename_get_flags(filename, &flags, custom_flags);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mail_index_update_flags(trans, seq, MODIFY_REPLACE,
fd3d711f219fd6813492acbe051e04327f0ca0f0Timo Sirainen /* expunged */
b35f7104715edee0cfac6d46ab0b342033867eb7Timo Sirainen /* new UID in the middle of the mailbox -
b35f7104715edee0cfac6d46ab0b342033867eb7Timo Sirainen shouldn't happen */
b35f7104715edee0cfac6d46ab0b342033867eb7Timo Sirainen "Maildir sync: UID inserted in the middle "
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen maildir_filename_get_flags(filename, &flags, custom_flags);
b35f7104715edee0cfac6d46ab0b342033867eb7Timo Sirainen if ((uint8_t)flags != (rec->flags & MAIL_FLAGS_MASK) ||
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mail_index_update_flags(trans, seq, MODIFY_REPLACE,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (mail_index_transaction_commit(trans, &seq, &offset) < 0)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* now, sync the index */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen while ((ret = mail_index_sync_next(sync_ctx, &sync_rec)) > 0) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (maildir_sync_record(ibox, view, &sync_rec) < 0) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen // FIXME: this is bad - we have to fix this in some way
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic int maildir_sync_context(struct maildir_sync_context *ctx,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (maildir_sync_quick_check(ctx, &new_changed, &cur_changed) < 0)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ctx->uidlist_sync_ctx = maildir_uidlist_sync_init(ctx->ibox->uidlist);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ret = maildir_uidlist_sync_deinit(ctx->uidlist_sync_ctx);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic int maildir_sync_context_readonly(struct maildir_sync_context *ctx)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ctx->uidlist_sync_ctx = maildir_uidlist_sync_init(ctx->ibox->uidlist);
c282435b57b6f9696fc12d99ea70468b7bdfe24cTimo Sirainen ret = maildir_uidlist_sync_deinit(ctx->uidlist_sync_ctx);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainenint maildir_storage_sync_readonly(struct index_mailbox *ibox)
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainenint maildir_storage_sync(struct mailbox *box, enum mailbox_sync_flags flags)
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen struct index_mailbox *ibox = (struct index_mailbox *)box;