On Wed, 2007-03-21 at 16:38 +0100, Steffen Kaiser wrote: > I noticed with EXPUNGE that the client feedback is sent after all messages > are deleted, when this is the same with COPY, could one sent some feedback > to the client in order to keep the connection open?
Does the attached patch help?
? src/imap/log
? src/imap/ns.sh
? src/imap/ref.sh
? src/lib-storage/maildir-sync-stayalive.diff
? src/lib-storage/index/maildir/diff
? src/lib-storage/index/mbox/debug
? src/lib-storage/index/mbox/diff
Index: src/imap/client.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/imap/client.c,v
retrieving revision 1.67.2.9
diff -u -r1.67.2.9 client.c
--- src/imap/client.c 14 Mar 2007 12:46:10 -0000 1.67.2.9
+++ src/imap/client.c 21 Mar 2007 17:57:13 -0000
@@ -148,6 +148,7 @@
if (o_stream_sendv(client->output, iov, 2) < 0)
return -1;
+ client->last_output = ioloop_time;
if (o_stream_get_buffer_used_size(client->output) >=
CLIENT_OUTPUT_OPTIMAL_SIZE) {
@@ -172,6 +173,8 @@
(void)o_stream_send(client->output, " ", 1);
(void)o_stream_send_str(client->output, data);
(void)o_stream_send(client->output, "\r\n", 2);
+
+ client->last_output = ioloop_time;
}
void client_send_command_error(struct client_command_context *cmd,
Index: src/imap/cmd-copy.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/imap/cmd-copy.c,v
retrieving revision 1.35
diff -u -r1.35 cmd-copy.c
--- src/imap/cmd-copy.c 6 Mar 2006 18:13:54 -0000 1.35
+++ src/imap/cmd-copy.c 21 Mar 2007 17:57:14 -0000
@@ -1,12 +1,29 @@
-/* Copyright (C) 2002 Timo Sirainen */
+/* Copyright (C) 2002-2007 Timo Sirainen */
#include "common.h"
#include "str.h"
+#include "ostream.h"
#include "commands.h"
#include "imap-search.h"
-static int fetch_and_copy(struct mailbox_transaction_context *t,
- struct mailbox *srcbox,
+#include <time.h>
+
+#define COPY_CHECK_INTERVAL 100
+
+static void client_send_sendalive_if_needed(struct client *client)
+{
+ time_t now;
+
+ now = time(NULL);
+ if (now - client->last_output > MAIL_STORAGE_STAYALIVE_SECS) {
+ o_stream_send_str(client->output, "* OK Hang in there..\r\n");
+ o_stream_flush(client->output);
+ client->last_output = now;
+ }
+}
+
+static int fetch_and_copy(struct client *client,
+ struct mailbox_transaction_context *t,
struct mail_search_arg *search_args)
{
struct mail_search_context *search_ctx;
@@ -14,9 +31,10 @@
struct mail_keywords *keywords;
const char *const *keywords_list;
struct mail *mail;
+ unsigned int copy_count = 0;
int ret;
- src_trans = mailbox_transaction_begin(srcbox, 0);
+ src_trans = mailbox_transaction_begin(client->mailbox, 0);
search_ctx = mailbox_search_init(src_trans, NULL, search_args, NULL);
mail = mail_alloc(src_trans, MAIL_FETCH_STREAM_HEADER |
@@ -28,6 +46,9 @@
break;
}
+ if ((++copy_count % COPY_CHECK_INTERVAL) != 0)
+ client_send_sendalive_if_needed(client);
+
keywords_list = mail_get_keywords(mail);
keywords = strarray_length(keywords_list) == 0 ? NULL :
mailbox_keywords_create(t, keywords_list);
@@ -92,7 +113,7 @@
t = mailbox_transaction_begin(destbox,
MAILBOX_TRANSACTION_FLAG_EXTERNAL);
- ret = fetch_and_copy(t, client->mailbox, search_arg);
+ ret = fetch_and_copy(client, t, search_arg);
if (ret <= 0)
mailbox_transaction_rollback(&t);
Index: src/lib-storage/mail-storage.h
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-storage/mail-storage.h,v
retrieving revision 1.107.2.5
diff -u -r1.107.2.5 mail-storage.h
--- src/lib-storage/mail-storage.h 28 Dec 2006 16:27:42 -0000 1.107.2.5
+++ src/lib-storage/mail-storage.h 21 Mar 2007 17:57:14 -0000
@@ -5,6 +5,9 @@
#include "mail-types.h"
+/* If some operation is taking long, call notify_ok every n seconds. */
+#define MAIL_STORAGE_STAYALIVE_SECS 15
+
enum mail_storage_flags {
/* Print debugging information while initializing the storage */
MAIL_STORAGE_FLAG_DEBUG = 0x01,
Index: src/lib-storage/index/maildir/maildir-sync.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-storage/index/maildir/maildir-sync.c,v
retrieving revision 1.77.2.7
diff -u -r1.77.2.7 maildir-sync.c
--- src/lib-storage/index/maildir/maildir-sync.c 14 Mar 2007 16:17:47 -0000 1.77.2.7
+++ src/lib-storage/index/maildir/maildir-sync.c 21 Mar 2007 17:57:14 -0000
@@ -210,12 +210,17 @@
const char *new_dir, *cur_dir;
bool partial;
+ unsigned int move_count, check_count;
+ time_t last_touch, last_notify;
+
struct maildir_uidlist_sync_ctx *uidlist_sync_ctx;
struct maildir_index_sync_context *index_sync_ctx;
};
struct maildir_index_sync_context {
struct maildir_mailbox *mbox;
+ struct maildir_sync_context *maildir_sync_ctx;
+
struct mail_index_view *view;
struct mail_index_sync_ctx *sync_ctx;
struct maildir_keywords_sync_ctx *keywords_sync_ctx;
@@ -471,6 +476,39 @@
return -1;
}
+static void
+maildir_sync_check_timeouts(struct maildir_sync_context *ctx, bool move)
+{
+ time_t now;
+
+ if (move) {
+ ctx->move_count++;
+ if ((ctx->move_count % MAILDIR_SLOW_MOVE_COUNT) != 0)
+ return;
+ } else {
+ ctx->check_count++;
+ if ((ctx->check_count % MAILDIR_SLOW_CHECK_COUNT) != 0)
+ return;
+ }
+
+ now = time(NULL);
+ if (now - ctx->last_touch > MAILDIR_LOCK_TOUCH_SECS) {
+ (void)maildir_uidlist_lock_touch(ctx->mbox->uidlist);
+ ctx->last_touch = now;
+ }
+ if (now - ctx->last_notify > MAIL_STORAGE_STAYALIVE_SECS) {
+ struct mailbox *box = &ctx->mbox->ibox.box;
+ struct index_storage *istorage = &ctx->mbox->storage->storage;
+
+ if (istorage->callbacks->notify_ok != NULL) {
+ istorage->callbacks->
+ notify_ok(box, "Hang in there..",
+ istorage->callback_context);
+ }
+ ctx->last_notify = now;
+ }
+}
+
static int
maildir_sync_record_commit_until(struct maildir_index_sync_context *ctx,
uint32_t last_seq)
@@ -511,10 +549,14 @@
ctx->seq = seq;
if (expunged) {
+ maildir_sync_check_timeouts(ctx->maildir_sync_ctx,
+ TRUE);
if (maildir_file_do(ctx->mbox, uid,
maildir_expunge, ctx) < 0)
return -1;
} else if (flag_changed) {
+ maildir_sync_check_timeouts(ctx->maildir_sync_ctx,
+ TRUE);
if (maildir_file_do(ctx->mbox, uid,
maildir_sync_flags, ctx) < 0)
return -1;
@@ -624,6 +666,8 @@
ctx->mbox = mbox;
ctx->new_dir = t_strconcat(mbox->path, "/new", NULL);
ctx->cur_dir = t_strconcat(mbox->path, "/cur", NULL);
+ ctx->last_touch = ioloop_time;
+ ctx->last_notify = ioloop_time;
return ctx;
}
@@ -696,13 +740,9 @@
string_t *src, *dest;
struct dirent *dp;
enum maildir_uidlist_rec_flag flags;
- time_t last_touch;
- unsigned int moves = 0, count = 0;
int ret = 1;
bool move_new, check_touch;
- last_touch = ioloop_time;
-
dir = new_dir ? ctx->new_dir : ctx->cur_dir;
dirp = opendir(dir);
if (dirp == NULL) {
@@ -715,6 +755,7 @@
src = t_str_new(1024);
dest = t_str_new(1024);
+ ctx->move_count = 0;
move_new = new_dir && !mailbox_is_readonly(&ctx->mbox->ibox.box) &&
!ctx->mbox->ibox.keep_recent;
while ((dp = readdir(dirp)) != NULL) {
@@ -747,13 +788,13 @@
}
if (rename(str_c(src), str_c(dest)) == 0) {
/* we moved it - it's \Recent for us */
- moves++;
+ maildir_sync_check_timeouts(ctx, TRUE);
ctx->mbox->dirty_cur_time = ioloop_time;
flags |= MAILDIR_UIDLIST_REC_FLAG_MOVED |
MAILDIR_UIDLIST_REC_FLAG_RECENT;
} else if (ENOTFOUND(errno)) {
/* someone else moved it already */
- moves++;
+ maildir_sync_check_timeouts(ctx, TRUE);
flags |= MAILDIR_UIDLIST_REC_FLAG_MOVED;
} else if (ENOSPACE(errno) || errno == EACCES) {
/* not enough disk space / read-only maildir,
@@ -768,23 +809,12 @@
"rename(%s, %s) failed: %m",
str_c(src), str_c(dest));
}
- if ((moves % MAILDIR_SLOW_MOVE_COUNT) == 0)
- check_touch = TRUE;
} else if (new_dir) {
flags |= MAILDIR_UIDLIST_REC_FLAG_NEW_DIR |
MAILDIR_UIDLIST_REC_FLAG_RECENT;
}
- count++;
- if (check_touch || (count % MAILDIR_SLOW_CHECK_COUNT) == 0) {
- time_t now = time(NULL);
-
- if (now - last_touch > MAILDIR_LOCK_TOUCH_SECS) {
- (void)maildir_uidlist_lock_touch(
- ctx->mbox->uidlist);
- last_touch = now;
- }
- }
+ maildir_sync_check_timeouts(ctx, FALSE);
ret = maildir_uidlist_sync_next(ctx->uidlist_sync_ctx,
dp->d_name, flags);
@@ -806,7 +836,8 @@
}
t_pop();
- return ret < 0 ? -1 : (moves <= MAILDIR_RENAME_RESCAN_COUNT ? 0 : 1);
+ return ret < 0 ? -1 :
+ (ctx->move_count <= MAILDIR_RENAME_RESCAN_COUNT ? 0 : 1);
}
static void
@@ -1344,6 +1375,7 @@
if (maildir_sync_index_begin(ctx->mbox,
&ctx->index_sync_ctx) < 0)
return -1;
+ ctx->index_sync_ctx->maildir_sync_ctx = ctx;
}
if (new_changed || cur_changed) {
signature.asc
Description: This is a digitally signed message part
