mdbox-sync.c revision 4fded1eec06aba9ce37887ac30619768760cd0d0
/* Copyright (c) 2007-2010 Dovecot authors, see the included COPYING file */
/*
Expunging works like:
1. Lock map index by beginning a map sync.
2. Write map UID refcount changes to map index (=> tail != head).
3. Expunge messages from mailbox index.
4. Finish map sync, which updates tail=head and unlocks map index.
If something crashes after 2 but before 4 is finished, tail != head and
reader can do a full resync to figure out what got broken.
*/
#include "lib.h"
#include "array.h"
#include "ioloop.h"
#include "hex-binary.h"
#include "str.h"
#include "mdbox-storage.h"
#include "mdbox-storage-rebuild.h"
#include "mdbox-map.h"
#include "mdbox-file.h"
#include "mdbox-sync.h"
#include <stdlib.h>
static int
{
const void *data;
if (mail_guid_128_is_empty(guid_128) ||
return 0;
"Mailbox %s: Expunged GUID mismatch for UID %u: %s vs %s",
return -1;
}
{
/* already marked as expunged in this sync */
return 0;
}
return -1;
return -1;
return -1;
return 0;
}
const struct mail_index_sync_rec *sync_rec)
{
/* not interested */
return 0;
}
/* already expunged everything. nothing to do. */
return 0;
}
return -1;
}
return 0;
}
{
struct mail_index_transaction *trans;
struct seq_range_iter iter;
unsigned int n;
const void *data;
/* use a separate transaction here so that we can commit the changes
during map transaction */
}
if (mail_index_transaction_commit(&trans) < 0)
return -1;
/* do notifications after commit finished successfully */
}
}
return 0;
}
{
const struct mail_index_header *hdr;
struct mail_index_sync_rec sync_rec;
int ret = 0;
if (hdr->uid_validity == 0) {
/* newly created index file */
return 0;
}
/* mark the newly seen messages as recent */
}
/* handle syncing records without map being locked. */
}
break;
}
/* write refcount changes to map index. transaction commit updates the
log head, while tail is left behind. */
if (ret == 0)
/* write changes to mailbox index */
if (ret == 0)
/* finish the map changes and unlock the map. this also updates
map's tail -> head. */
if (ret < 0)
}
return ret == 0 ? 1 :
}
{
int ret;
if (ret < 0) {
return -1;
}
if (ret == 0) {
/* nothing to do */
return 0;
}
/* we have expunges, so we need to write to map.
it needs to be locked before mailbox index. */
return -1;
}
return 1;
}
struct mdbox_map_atomic_context *atomic,
struct mdbox_sync_context **ctx_r)
{
struct mdbox_sync_context *ctx;
int ret;
/* avoid race conditions with mailbox creation, don't check for dbox
headers until syncing has locked the mailbox */
(flags & MDBOX_SYNC_FLAG_FORCE_REBUILD) != 0;
if (rebuild) {
return -1;
}
if ((flags & MDBOX_SYNC_FLAG_FSYNC) != 0)
/* don't write unnecessary dirty flag updates */
if (ret <= 0) {
/* failed / nothing to do */
return ret;
}
if (ret < 0)
return -1;
/* corrupted */
if (storage_rebuilt) {
"mdbox %s: Storage keeps breaking",
return -1;
}
/* we'll need to rebuild storage.
try again from the beginning. */
}
return 0;
}
{
if (success) {
ret = -1;
}
} else {
}
return ret;
}
{
struct mdbox_sync_context *sync_ctx;
struct mdbox_map_atomic_context *atomic;
int ret;
if (ret == 0)
if (mdbox_map_atomic_finish(&atomic) < 0)
ret = -1;
return ret;
}
struct mailbox_sync_context *
{
enum mdbox_sync_flags mdbox_sync_flags = 0;
int ret = 0;
if (mailbox_open(box) < 0)
ret = -1;
}
if ((flags & MAILBOX_SYNC_FLAG_FORCE_RESYNC) != 0)
}
}