This documentation is for Dovecot v2.x, see wiki1 for v1.x documentation.

Mailbox Synchronization

The idea behind synchronization is to find out what changes other sessions have done to the mailbox and to finalize our own changes to the mailbox.

For example if you expunge a message in a transaction and commit it, the commit will only write a "please expunge UID n" record to Dovecot's transaction log file. The message still exists on the disk. The next time Dovecot syncs the mailbox (either the session that wrote the record or another one), it goes through all the non-synchronized records in transaction log and applies the requested changes to the backend mailbox. Syncing can be a bit heavyweight operation, so it's possible to commit multiple transactions and perform a single sync for all of them. Dovecot attempts to do this with IMAP protocol when pipelining commands.

The other important job of syncing is to refresh mailbox's state:

When a mailbox is opened, its state starts with what index files contain at the time. Since the backend mailbox may have already changed, and syncing an up-to-date mailbox is usually really cheap, there isn't much point in not syncing mailbox immediately after opening. The mailbox state stays the same until you synchronize the mailbox again, before that no new messages show up and no messages get expunged.

Typically you would sync the mailbox

Initializing

mailbox_sync_init() initializes syncing.

There are some flags that control how much effort is spent on syncing:

Then there are also other syncing flags:

Reading changes

While mailbox_sync_next() returns TRUE, it fills out sync record:

Expunge records don't immediately change the view's sequence numbers. After seeing an expunge record you can still fetch the expunged messages' flags and possibly other information. Only after syncing is deinitialized, the sequences change.

Message flag change records don't actually show what the changes were. You can find the new flags just by fetching them (mail_get_flags(), etc.), they're available immediately. You'll need to create a transaction and a mail for that. For example:

sync_ctx = mailbox_sync_init(box, flags);
trans = mailbox_transaction_begin(box, 0);
mail = mail_alloc(trans, MAIL_FETCH_FLAGS, 0);

If you don't actually care about sync records, you don't necessarily have to even call mailbox_sync_next(). In that case it's actually easiest to perform the whole sync using a one-step mailbox_sync() function. This function also sets MAILBOX_SYNC_FLAG_FIX_INCONSISTENT flag automatically.

Deinitializing

mailbox_sync_deinit() finalizes the syncing. If any errors occurred during sync, it'll return -1.

If MAILBOX_SYNC_FLAG_NO_EXPUNGES was used and some expunges were actually delayed, status_r->sync_delayed_expunges is set to TRUE.

Implementing sync for a storage backend

FIXME: talk about mail_index_sync_*() and how to change stuff and how to update internal state.

None: Design/Storage/Mailbox/Sync (last edited 2009-12-17 00:26:52 by TimoSirainen)