mdbox-sync.c revision 8f4d8c489a992a5f0dca8a263968544c1c669779
/* 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.
3. Expunge messages from mailbox index.
4. Finish map sync, which updates head=tail and unlocks map index.
If something crashes after 2 but before 4 is finished, head != tail 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>
#include <dirent.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 */
}
break;
}
if (ret == 0) {
/* write refcount changes to map index */
}
if (ret == 0) {
/* write changes to mailbox index */
}
/* this finally finishes the map sync and marks the map transaction
to be successfully finished. */
if (ret < 0)
return ret == 0 ? 1 :
}
{
struct mail_index_view *view;
struct mdbox_index_header hdr;
int ret;
if (ret == 0) {
} else if (retry) {
}
return ret;
}
struct mdbox_sync_context **ctx_r)
{
struct mdbox_sync_context *ctx;
unsigned int i;
int ret;
(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 */
for (i = 0;; i++) {
if (ret <= 0) {
if (ret < 0)
return ret;
}
/* now that we're locked, check again if we want to rebuild */
ret = 0;
else {
break;
}
/* failure. keep the index locked while we're doing a
rebuild. */
if (ret == 0) {
if (!storage_rebuilt) {
/* we'll need to rebuild storage too.
try again from the beginning. */
}
"dbox %s: Storage keeps breaking",
ret = -1;
}
if (ret < 0) {
return -1;
}
}
return 0;
}
{
if (success) {
ret = -1;
}
} else {
}
return ret;
}
{
struct mdbox_sync_context *sync_ctx;
return -1;
return 0;
}
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)
}
}
{
struct dirent *d;
int ret = 0;
return 0;
/* we want to quickly find the latest alt file, but we also want to
avoid accessing the alt storage as much as possible. so we'll do
this by finding the lowest numbered file (n) from primary storage.
hopefully one of n-[1..m] is appendable in alt storage. */
/* no storage directory at all yet */
return 0;
}
return -1;
}
strlen(MDBOX_MAIL_FILE_PREFIX)) != 0)
continue;
&file_id) < 0)
continue;
}
}
if (errno != 0) {
ret = -1;
}
ret = -1;
}
return ret;
}
{
struct seq_range_iter iter;
unsigned int i = 0;
bool deleted;
int ret = 0;
ret = -1;
/* add also files that can be altmoved */
ret = -1;
if (mdbox_file_purge(file) < 0)
ret = -1;
} else {
}
} T_END;
/* purging found corrupted files */
(void)mdbox_storage_rebuild(storage);
ret = -1;
}
return ret;
}