box->close(box);
if (!failed) {
- client_sync_full(client);
+ client_sync_full_fast(client);
client_send_tagline(client, "OK Append completed.");
}
return TRUE;
{
client_send_line(client, "* CAPABILITY " CAPABILITY_STRING);
- client_sync_full(client);
+ client_sync_full_fast(client);
client_send_tagline(client, "OK Capability completed.");
return TRUE;
}
ret = client->mailbox->copy(client->mailbox, destbox,
messageset, client->cmd_uid);
- /* sync always - if COPY fails because of expunges they'll get
- synced here */
- client_sync_full(client);
-
- if (ret)
+ if (ret) {
+ client_sync_full_fast(client);
client_send_tagline(client, "OK Copy completed.");
- else
+ } else {
+ /* if COPY fails because of expunges they'll get synced here */
+ client_sync_full(client);
client_send_storage_error(client);
+ }
destbox->close(destbox);
return TRUE;
if ((client_workarounds &
WORKAROUND_OE6_FETCH_NO_NEWMAIL) == 0) {
if (client->cmd_uid)
- client_sync_full(client);
+ client_sync_full_fast(client);
else
client_sync_without_expunges(client);
}
client_send_tagline(client, t_strconcat("NO ", error, NULL));
} else if (imap_search(client, charset, sargs)) {
if (client->cmd_uid)
- client_sync_full(client);
+ client_sync_full_fast(client);
else
client_sync_without_expunges(client);
client_send_tagline(client, "OK Search completed.");
} else if (imap_sort(client, charset, sargs, sorting)) {
/* NOTE: syncing is allowed when returning UIDs */
if (client->cmd_uid)
- client_sync_full(client);
+ client_sync_full_fast(client);
else
client_sync_without_expunges(client);
client_send_tagline(client, "OK Sort completed.");
client->cmd_uid, &flags,
modify_type, !silent, &all_found)) {
if (client->cmd_uid)
- client_sync_full(client);
+ client_sync_full_fast(client);
else
client_sync_without_expunges(client);
client_send_tagline(client, all_found ? "OK Store completed." :
} else if (imap_thread(client, charset, sargs, threading)) {
/* NOTE: syncing is allowed when returning UIDs */
if (client->cmd_uid)
- client_sync_full(client);
+ client_sync_full_fast(client);
else
client_sync_without_expunges(client);
client_send_tagline(client, "OK Search completed.");
void client_sync_full(struct client *client)
{
if (client->mailbox != NULL) {
- if (!client->mailbox->sync(client->mailbox, TRUE))
+ if (!client->mailbox->sync(client->mailbox, 0))
+ client_send_untagged_storage_error(client);
+ }
+}
+
+void client_sync_full_fast(struct client *client)
+{
+ if (client->mailbox != NULL) {
+ if (!client->mailbox->sync(client->mailbox,
+ MAIL_SYNC_FLAG_FAST))
client_send_untagged_storage_error(client);
}
}
void client_sync_without_expunges(struct client *client)
{
if (client->mailbox != NULL) {
- if (!client->mailbox->sync(client->mailbox, FALSE))
+ if (!client->mailbox->sync(client->mailbox,
+ MAIL_SYNC_FLAG_NO_EXPUNGES |
+ MAIL_SYNC_FLAG_FAST))
client_send_untagged_storage_error(client);
}
}
FETCH FLAGS, EXISTS and RECENT responses. */
void client_sync_full(struct client *client);
+/* Synchronize fast. */
+void client_sync_full_fast(struct client *client);
+
/* Synchronize all but expunges with client. */
void client_sync_without_expunges(struct client *client);
if (!rebuilt) {
/* sync ourself. do it before updating cache and compression
which may happen because of this. */
- if (!index->sync_and_lock(index, MAIL_LOCK_SHARED, NULL) &&
+ if (!index->sync_and_lock(index, FALSE,
+ MAIL_LOCK_SHARED, NULL) &&
!index->nodiskspace)
return FALSE;
lock when calling this function. The data_lock_type specifies what
lock should be set to data file (mbox file). This function may
leave the index in ANY locking state. If changes is non-NULL, it's
- set to TRUE if any changes were noticed. */
- int (*sync_and_lock)(struct mail_index *index,
+ set to TRUE if any changes were noticed. If minimal_sync is TRUE,
+ we do as little as possible to get data file locked (ie. noop with
+ maildir). */
+ int (*sync_and_lock)(struct mail_index *index, int minimal_sync,
enum mail_lock_type data_lock_type, int *changes);
/* Returns the index header (never fails). The index needs to be
int maildir_index_rebuild(struct mail_index *index);
int maildir_index_sync_readonly(struct mail_index *index,
const char *fname, int *found);
-int maildir_index_sync(struct mail_index *index,
+int maildir_index_sync(struct mail_index *index, int minimal_sync,
enum mail_lock_type lock_type, int *changes);
int maildir_index_append_file(struct mail_index *index, const char *dir,
}
/* read the mails by syncing */
- if (!index->sync_and_lock(index, MAIL_LOCK_UNLOCK, NULL))
+ if (!index->sync_and_lock(index, FALSE, MAIL_LOCK_UNLOCK, NULL))
return FALSE;
/* rebuild is complete - remove the flag */
return ret;
}
-int maildir_index_sync(struct mail_index *index,
+int maildir_index_sync(struct mail_index *index, int minimal_sync,
enum mail_lock_type data_lock_type __attr_unused__,
int *changes)
{
if (changes != NULL)
*changes = FALSE;
+ if (minimal_sync)
+ return TRUE;
+
ctx = maildir_sync_context_new(index);
ret = maildir_index_sync_context(ctx, changes);
maildir_index_sync_deinit(ctx);
mbox_index_alloc(const char *mbox_path, const char *index_dir,
const char *control_dir);
int mbox_index_rebuild(struct mail_index *index);
-int mbox_index_sync(struct mail_index *index,
+int mbox_index_sync(struct mail_index *index, int minimal_sync,
enum mail_lock_type lock_type, int *changes);
int mbox_sync_full(struct mail_index *index);
struct istream *mbox_open_mail(struct mail_index *index,
if (!index->set_lock(index, MAIL_LOCK_EXCLUSIVE))
break;
- if (!index->sync_and_lock(index, MAIL_LOCK_EXCLUSIVE,
- NULL))
+ if (!index->sync_and_lock(index, FALSE,
+ MAIL_LOCK_EXCLUSIVE, NULL))
break;
}
return mbox_sync_full(index);
}
-int mbox_index_sync(struct mail_index *index,
+int mbox_index_sync(struct mail_index *index, int minimal_sync __attr_unused__,
enum mail_lock_type data_lock_type, int *changes)
{
struct stat st;
if (!index_storage_lock(ibox, MAIL_LOCK_EXCLUSIVE))
return FALSE;
} else {
- if (!index_storage_sync_and_lock(ibox, TRUE, MAIL_LOCK_SHARED))
+ if (!index_storage_sync_and_lock(ibox, TRUE, TRUE,
+ MAIL_LOCK_SHARED))
return FALSE;
}
if (!index_storage_lock(ibox, MAIL_LOCK_EXCLUSIVE))
return FALSE;
- if (!index_storage_sync_and_lock(ibox, FALSE, MAIL_LOCK_EXCLUSIVE))
+ if (!index_storage_sync_and_lock(ibox, FALSE, TRUE,
+ MAIL_LOCK_EXCLUSIVE))
return FALSE;
/* modifylog must be marked synced before expunging
check_mail = (client_workarounds &
WORKAROUND_OE6_FETCH_NO_NEWMAIL) == 0;
- if (!index_storage_sync_and_lock(ibox, check_mail, MAIL_LOCK_SHARED))
+ if (!index_storage_sync_and_lock(ibox, check_mail, TRUE,
+ MAIL_LOCK_SHARED))
return NULL;
if (update_seen != NULL && *update_seen &&
return NULL;
}
- if (!index_storage_sync_and_lock(ibox, TRUE, MAIL_LOCK_SHARED))
+ if (!index_storage_sync_and_lock(ibox, TRUE, TRUE, MAIL_LOCK_SHARED))
return NULL;
ctx = i_new(struct mail_search_context, 1);
if ((items & STATUS_MESSAGE_COUNTS) != 0) {
/* if we're doing STATUS for selected mailbox, we have to sync
it first or STATUS reply may give different data */
- if (!index_storage_sync_and_lock(ibox, TRUE, MAIL_LOCK_UNLOCK))
+ if (!index_storage_sync_and_lock(ibox, TRUE, FALSE,
+ MAIL_LOCK_UNLOCK))
return FALSE;
if (!index_storage_sync_modifylog(ibox, FALSE)) {
int readonly, int fast);
int index_storage_close(struct mailbox *box);
-int index_storage_sync_and_lock(struct index_mailbox *ibox, int sync_size,
+int index_storage_sync_and_lock(struct index_mailbox *ibox,
+ int sync_size, int minimal_sync,
enum mail_lock_type data_lock_type);
int index_storage_sync_modifylog(struct index_mailbox *ibox, int hide_deleted);
int index_storage_get_status(struct mailbox *box,
enum mailbox_status_items items,
struct mailbox_status *status);
-int index_storage_sync(struct mailbox *box, int sync_expunges);
+int index_storage_sync(struct mailbox *box, enum mail_sync_flags flags);
int index_storage_update_flags(struct mailbox *box, const char *messageset,
int uidset, const struct mail_full_flags *flags,
enum modify_type modify_type, int notify,
#include "mail-modifylog.h"
#include "mail-custom-flags.h"
+/* How often to do full sync when fast sync flag is set. */
+#define MAILBOX_FULL_SYNC_INTERVAL 5
+
static void index_storage_sync_size(struct index_mailbox *ibox)
{
struct mail_storage *storage = ibox->box.storage;
}
}
-int index_storage_sync_and_lock(struct index_mailbox *ibox, int sync_size,
+int index_storage_sync_and_lock(struct index_mailbox *ibox,
+ int sync_size, int minimal_sync,
enum mail_lock_type data_lock_type)
{
struct mail_storage *storage = ibox->box.storage;
set_shared_lock = ibox->index->lock_type != MAIL_LOCK_EXCLUSIVE;
index_storage_init_lock_notify(ibox);
- failed = !index->sync_and_lock(index, data_lock_type, &changes);
+ failed = !index->sync_and_lock(index, minimal_sync,
+ data_lock_type, &changes);
ibox->index->set_lock_notify_callback(ibox->index, NULL, NULL);
if (!failed) {
return TRUE;
}
-int index_storage_sync(struct mailbox *box, int sync_expunges)
+int index_storage_sync(struct mailbox *box, enum mail_sync_flags flags)
{
struct index_mailbox *ibox = (struct index_mailbox *) box;
int ret;
- ibox->sync_last_check = ioloop_time;
+ if ((flags & MAIL_SYNC_FLAG_FAST) == 0 ||
+ ibox->sync_last_check + MAILBOX_FULL_SYNC_INTERVAL <= ioloop_time) {
+ ibox->sync_last_check = ioloop_time;
- if (!index_storage_sync_and_lock(ibox, FALSE, MAIL_LOCK_UNLOCK))
- return FALSE;
+ if (!index_storage_sync_and_lock(ibox, FALSE, FALSE,
+ MAIL_LOCK_UNLOCK))
+ return FALSE;
+ } else {
+ /* check only modify log */
+ if (!index_storage_lock(ibox, MAIL_LOCK_SHARED)) {
+ (void)index_storage_lock(ibox, MAIL_LOCK_UNLOCK);
+ return FALSE;
+ }
+ }
/* FIXME: we could sync flags always, but expunges in the middle
could make it a bit more difficult and slower */
- if (sync_expunges ||
+ if ((flags & MAIL_SYNC_FLAG_NO_EXPUNGES) == 0 ||
mail_modifylog_get_expunge_count(ibox->index->modifylog) == 0)
ret = index_storage_sync_modifylog(ibox, FALSE);
else
if (!index_storage_lock(ibox, MAIL_LOCK_EXCLUSIVE))
return FALSE;
- if (!index_storage_sync_and_lock(ibox, TRUE, MAIL_LOCK_UNLOCK))
+ if (!index_storage_sync_and_lock(ibox, TRUE, TRUE, MAIL_LOCK_UNLOCK))
return FALSE;
mail_flags &= ~MAIL_RECENT; /* \Recent can't be changed */
struct messageset_context *ctx;
int exdev, ret, ret2;
- if (!index_storage_sync_and_lock(src, TRUE, MAIL_LOCK_SHARED))
+ if (!src->index->set_lock(src->index, MAIL_LOCK_SHARED))
return -1;
ctx = index_messageset_init(src, messageset, uidset, FALSE);
return NULL;
}
- if (!index_storage_sync_and_lock(ibox, FALSE, MAIL_LOCK_EXCLUSIVE))
+ if (!index_storage_sync_and_lock(ibox, FALSE, TRUE,
+ MAIL_LOCK_EXCLUSIVE))
return NULL;
ctx = i_new(struct mail_save_context, 1);
MAIL_FETCH_IMAP_ENVELOPE = 0x4000
};
+enum mail_sync_flags {
+ MAIL_SYNC_FLAG_NO_EXPUNGES = 0x01,
+ MAIL_SYNC_FLAG_FAST = 0x02
+};
+
enum client_workarounds {
WORKAROUND_OE6_FETCH_NO_NEWMAIL = 0x01,
WORKAROUND_OUTLOOK_IDLE = 0x02
int (*get_status)(struct mailbox *box, enum mailbox_status_items items,
struct mailbox_status *status);
- /* Synchronize the mailbox. If sync_expunges is FALSE, everything
- but expunges are synced. */
- int (*sync)(struct mailbox *box, int sync_expunges);
+ /* Synchronize the mailbox. */
+ int (*sync)(struct mailbox *box, enum mail_sync_flags flags);
/* Synchronize mailbox in background. It's done until this function is
called with sync_type = MAILBOX_SYNC_NONE */