# HG changeset patch # User Timo Sirainen # Date 1087190571 -10800 # Node ID 0840edf34f37d543ba7f008ebfa2feea8fc836a1 # Parent f434ecc6ef8361cae57be9a2b43bc603b62b74be Locking fixes. use less memory diff -r f434ecc6ef83 -r 0840edf34f37 src/lib-storage/index/maildir/maildir-sync.c --- a/src/lib-storage/index/maildir/maildir-sync.c Mon Jun 14 08:16:10 2004 +0300 +++ b/src/lib-storage/index/maildir/maildir-sync.c Mon Jun 14 08:22:51 2004 +0300 @@ -424,9 +424,6 @@ enum maildir_uidlist_rec_flag flags; int move_new, ret = 1; - src = t_str_new(1024); - dest = t_str_new(1024); - dir = new_dir ? ctx->new_dir : ctx->cur_dir; dirp = opendir(dir); if (dirp == NULL) { @@ -435,6 +432,10 @@ return -1; } + t_push(); + src = t_str_new(1024); + dest = t_str_new(1024); + move_new = new_dir && !mailbox_is_readonly(&ctx->ibox->box) && !ctx->ibox->keep_recent; while ((dp = readdir(dirp)) != NULL) { @@ -507,6 +508,8 @@ mail_storage_set_critical(storage, "closedir(%s) failed: %m", dir); } + + t_pop(); return ret < 0 ? -1 : 0; } @@ -835,6 +838,15 @@ ctx->uidlist_sync_ctx = maildir_uidlist_sync_init(ctx->ibox->uidlist, ctx->partial); + /* we have to lock uidlist immediately, otherwise there's race + conditions with other processes who might write older maildir + file list into uidlist. + + alternative would be to lock it when new files are found, but + the directory scans _must_ be restarted then */ + if (maildir_uidlist_try_lock(ctx->ibox->uidlist) < 0) + return -1; + if (maildir_scan_dir(ctx, TRUE) < 0) return -1; if (cur_changed) { diff -r f434ecc6ef83 -r 0840edf34f37 src/lib-storage/index/maildir/maildir-uidlist.c --- a/src/lib-storage/index/maildir/maildir-uidlist.c Mon Jun 14 08:16:10 2004 +0300 +++ b/src/lib-storage/index/maildir/maildir-uidlist.c Mon Jun 14 08:22:51 2004 +0300 @@ -91,8 +91,12 @@ "file_dotlock_open(%s) failed: %m", path); return -1; } + uidlist->lock_fd = fd; - uidlist->lock_fd = fd; + /* our view of uidlist must be up-to-date if we plan on changing it */ + if (maildir_uidlist_update(uidlist) < 0) + return -1; + return 1; } @@ -463,8 +467,10 @@ iter = maildir_uidlist_iter_init(uidlist->ibox->uidlist); while (maildir_uidlist_iter_next(iter, &uid, &flags, &filename)) { + /* avoid overflowing str buffer so we don't eat more memory + than we need. */ if (str_len(str) + MAX_INT_STRLEN + - strlen(filename) + 2 >= 4096) { + strlen(filename) + 5 + 10 >= 4096) { /* flush buffer */ if (write_full(uidlist->lock_fd, str_data(str), str_len(str)) < 0) { @@ -592,6 +598,11 @@ i_assert(!ctx->synced); + if (UIDLIST_IS_LOCKED(ctx->uidlist)) { + ctx->synced = TRUE; + return 1; + } + if (!ctx->uidlist->initial_read) { /* first time reading the uidlist, no locking yet */ @@ -612,10 +623,6 @@ ctx->failed = TRUE; return -1; } - if (maildir_uidlist_update(ctx->uidlist) < 0) { - ctx->failed = TRUE; - return -1; - } ctx->synced = TRUE; return 1; @@ -842,8 +849,11 @@ if (!ctx->finished) maildir_uidlist_sync_finish(ctx); - if (ctx->new_files_count != 0 && !ctx->failed && !ctx->locked) + if (ctx->new_files_count != 0 && !ctx->failed && !ctx->locked) { + t_push(); ret = maildir_uidlist_rewrite(ctx->uidlist); + t_pop(); + } if (ctx->partial) maildir_uidlist_mark_all(ctx->uidlist, FALSE);