index-sync.c revision 18c5ae52ca659071a35279dda22ba9556985805e
e59faf65ce864fe95dc00f5d52b8323cdbd0608aTimo Sirainen/* Copyright (C) 2002 Timo Sirainen */
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen#include "lib.h"
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen#include "index-storage.h"
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen#include "mail-index-util.h"
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen#include "mail-modifylog.h"
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen#include "mail-custom-flags.h"
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainenstatic void index_storage_sync_size(IndexMailbox *ibox)
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen{
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen unsigned int messages, recent;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen messages = ibox->index->get_header(ibox->index)->messages_count;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen messages += mail_modifylog_get_expunge_count(ibox->index->modifylog);
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen if (messages != ibox->synced_messages_count) {
f7539a17ea306191b53b8f5e752e228937df9ec3Timo Sirainen i_assert(messages > ibox->synced_messages_count);
f7539a17ea306191b53b8f5e752e228937df9ec3Timo Sirainen
f7539a17ea306191b53b8f5e752e228937df9ec3Timo Sirainen /* new messages in mailbox */
f7539a17ea306191b53b8f5e752e228937df9ec3Timo Sirainen recent = index_storage_get_recent_count(ibox->index);
f7539a17ea306191b53b8f5e752e228937df9ec3Timo Sirainen ibox->sync_callbacks.new_messages(&ibox->box, messages, recent,
f7539a17ea306191b53b8f5e752e228937df9ec3Timo Sirainen ibox->sync_context);
f7539a17ea306191b53b8f5e752e228937df9ec3Timo Sirainen ibox->synced_messages_count = messages;
f7539a17ea306191b53b8f5e752e228937df9ec3Timo Sirainen }
f7539a17ea306191b53b8f5e752e228937df9ec3Timo Sirainen}
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen/* may leave the index locked */
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainenint index_storage_sync_index_if_possible(IndexMailbox *ibox, int sync_size)
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen{
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen MailIndex *index = ibox->index;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen if (index->sync(index)) {
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen /* reset every time it has worked */
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen ibox->sent_diskspace_warning = FALSE;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen } else {
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen if (!index->is_diskspace_error(index)) {
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen (void)index->set_lock(index, MAIL_LOCK_UNLOCK);
e5fd6dfd0a492e4708d4dbb7971d7fc5d7b8fd85Timo Sirainen return mail_storage_set_index_error(ibox);
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen }
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
d22301419109ed4a38351715e6760011421dadecTimo Sirainen /* notify client once about it */
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen if (!ibox->sent_diskspace_warning) {
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen ibox->sent_diskspace_warning = TRUE;
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen ibox->sync_callbacks.alert_no_diskspace(
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen &ibox->box, ibox->sync_context);
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen }
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen index_reset_error(index);
d22301419109ed4a38351715e6760011421dadecTimo Sirainen }
d22301419109ed4a38351715e6760011421dadecTimo Sirainen
d22301419109ed4a38351715e6760011421dadecTimo Sirainen /* notify about changes in mailbox size. */
d22301419109ed4a38351715e6760011421dadecTimo Sirainen if (index->lock_type == MAIL_LOCK_UNLOCK)
d22301419109ed4a38351715e6760011421dadecTimo Sirainen return TRUE; /* no changes - must be no new mail either */
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
e5fd6dfd0a492e4708d4dbb7971d7fc5d7b8fd85Timo Sirainen if (sync_size)
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen index_storage_sync_size(ibox);
d22301419109ed4a38351715e6760011421dadecTimo Sirainen
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen /* notify changes in custom flags */
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen if (mail_custom_flags_has_changes(index->custom_flags)) {
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen ibox->sync_callbacks.new_custom_flags(&ibox->box,
d22301419109ed4a38351715e6760011421dadecTimo Sirainen mail_custom_flags_list_get(index->custom_flags),
d22301419109ed4a38351715e6760011421dadecTimo Sirainen MAIL_CUSTOM_FLAGS_COUNT, ibox->sync_context);
d22301419109ed4a38351715e6760011421dadecTimo Sirainen }
d22301419109ed4a38351715e6760011421dadecTimo Sirainen
d22301419109ed4a38351715e6760011421dadecTimo Sirainen return TRUE;
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen}
d22301419109ed4a38351715e6760011421dadecTimo Sirainen
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainenint index_storage_sync_modifylog(IndexMailbox *ibox, int hide_deleted)
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen{
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen const ModifyLogRecord *log1, *log2, *log, *first_flag_log;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen MailIndexRecord *rec;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen MailFlags flags;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen MailboxSyncCallbacks *sc;
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen void *sc_context;
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen const char **custom_flags;
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen unsigned int count1, count2, total_count, seq, seq_count, i, messages;
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen unsigned int first_flag_change, first_flag_messages_count;
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen /* show the log */
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen if (!mail_modifylog_get_nonsynced(ibox->index->modifylog,
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen &log1, &count1, &log2, &count2))
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen return mail_storage_set_index_error(ibox);
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen sc = &ibox->sync_callbacks;
b42697a5749b85659a24316d97f1c208d469e4e8Timo Sirainen sc_context = ibox->sync_context;
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen /* first show expunges. this makes it easier to deal with sequence
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen numbers. */
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen total_count = count1 + count2;
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen messages = ibox->synced_messages_count;
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen first_flag_change = total_count;
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen first_flag_log = NULL;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen first_flag_messages_count = 0;
d22301419109ed4a38351715e6760011421dadecTimo Sirainen
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen for (i = 0, log = log1; i < total_count; i++, log++) {
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen if (i == count1)
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen log = log2;
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen if (log->seq1 > messages) {
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen /* client doesn't know about this message yet */
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen continue;
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen }
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen switch (log->type) {
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen case RECORD_TYPE_EXPUNGE:
9ffdc9d18870acef2e4dde99715d8528ff4b080dTimo Sirainen seq_count = (log->seq2 - log->seq1) + 1;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen messages -= seq_count;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
f81f4bc282cd1944cec187bae89c0701a416ed2aTimo Sirainen for (; seq_count > 0; seq_count--) {
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen sc->expunge(&ibox->box, log->seq1,
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen sc_context);
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen }
f81f4bc282cd1944cec187bae89c0701a416ed2aTimo Sirainen break;
d22301419109ed4a38351715e6760011421dadecTimo Sirainen case RECORD_TYPE_FLAGS_CHANGED:
f81f4bc282cd1944cec187bae89c0701a416ed2aTimo Sirainen if (first_flag_change == total_count) {
d22301419109ed4a38351715e6760011421dadecTimo Sirainen first_flag_change = i;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen first_flag_log = log;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen first_flag_messages_count = messages;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen }
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen break;
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen }
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen }
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen /* set synced messages count before flag changes break it */
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen ibox->synced_messages_count = messages;
563273bdac80393af63b9520cbf4d24cc0efd028Timo Sirainen
ac26a4607cb12b156f6a42f1ead2881bedd43d94Timo Sirainen /* now show the flags */
dca6d617a23e3f93af3b8df59acb46478179fe55Timo Sirainen messages = first_flag_messages_count;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen custom_flags = mail_custom_flags_list_get(ibox->index->custom_flags);
1108376e39a19912e8394e64e19b1bc6f6691cf6Timo Sirainen
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen log = first_flag_log;
3e564425db51f3921ce4de11859777135fdedd15Timo Sirainen for (i = first_flag_change; i < total_count; i++, log++) {
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen if (i == count1)
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen log = log2;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen if (log->seq1 > messages) {
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen /* client doesn't know about this message yet */
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen continue;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen }
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen switch (log->type) {
09c08fad8e7cc694a6c8d1711e67839acd3a2f04Timo Sirainen case RECORD_TYPE_EXPUNGE:
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen messages -= (log->seq2 - log->seq1) + 1;
9ffdc9d18870acef2e4dde99715d8528ff4b080dTimo Sirainen break;
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen case RECORD_TYPE_FLAGS_CHANGED:
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen rec = ibox->index->lookup_uid_range(ibox->index,
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen log->uid1,
d3442384ca53d4b18a493db7dd0b000f470419cfTimo Sirainen log->uid2, &seq);
d3442384ca53d4b18a493db7dd0b000f470419cfTimo Sirainen while (rec != NULL && rec->uid <= log->uid2) {
fbd918f47f591f8084fd52b207ef29515ddd11b9Timo Sirainen flags = rec->msg_flags;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen if (rec->uid >= ibox->index->first_recent_uid)
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen flags |= MAIL_RECENT;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
5137d2d80255938a0f5fb8f3c1a21b34cf11ada3Timo Sirainen /* \Deleted-hiding is useful when syncing just
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen before doing EXPUNGE. */
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen if ((flags & MAIL_DELETED) == 0 ||
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen !hide_deleted) {
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen sc->update_flags(
48270badadd82279bfe50ae3d187aea8b0b2b30eTimo Sirainen &ibox->box, seq, rec->uid,
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen flags, custom_flags,
14ab4610b6038da6c5d0814fecabc6b74bc81a6bTimo Sirainen MAIL_CUSTOM_FLAGS_COUNT,
84ed9f8f3d0e5ed47607ef417618e49e4f865557Timo Sirainen sc_context);
84ed9f8f3d0e5ed47607ef417618e49e4f865557Timo Sirainen }
e3796bfd2bc0fd5ba664893d346df9334a5b3af0Timo Sirainen
5afa8e2edf4f313cd56e5909f92f39c3b5b7b4d3Timo Sirainen seq++;
408e5be344c9131fdebe771718a5bf49f88cc51cTimo Sirainen rec = ibox->index->next(ibox->index, rec);
370b60cfccff7c50586fc30f4f591499a55301a8Timo Sirainen }
ecdce39e5ef4b62eefa9f5818f17d153fd5d710aTimo Sirainen break;
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen }
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen }
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen /* mark synced */
de58be41126e5d68008d2ea706d62ccdc1f29337Timo Sirainen if (!mail_modifylog_mark_synced(ibox->index->modifylog))
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen return mail_storage_set_index_error(ibox);
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen return TRUE;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen}
e3aeeb634245e80d4f643f8d2eea11d6b72336d8Timo Sirainen
e3aeeb634245e80d4f643f8d2eea11d6b72336d8Timo Sirainenint index_storage_sync(Mailbox *box, int sync_expunges)
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen{
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen IndexMailbox *ibox = (IndexMailbox *) box;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen int failed;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen if (!index_storage_sync_index_if_possible(ibox, FALSE))
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen return FALSE;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
if (!sync_expunges) {
/* FIXME: we could still send flag changes */
failed = FALSE;
} else {
if (!ibox->index->set_lock(ibox->index, MAIL_LOCK_SHARED))
return mail_storage_set_index_error(ibox);
failed = !index_storage_sync_modifylog(ibox, FALSE);
}
/* check size only if we're locked (== at least something changed) */
if (ibox->index->lock_type != MAIL_LOCK_UNLOCK)
index_storage_sync_size(ibox);
if (!ibox->index->set_lock(ibox->index, MAIL_LOCK_UNLOCK))
return mail_storage_set_index_error(ibox);
return !failed;
}