mdbox-purge.c revision 1ef2ea0e6a763f9f9d466cba41a774119351cb81
a8c5a86d183db25a57bf193c06b41e092ec2e151Timo Sirainen/* Copyright (c) 2007-2011 Dovecot authors, see the included COPYING file */
4082d5b171d1c3a00ba705093d62b8afc9cf17aeTimo Sirainen Altmoving works like:
4082d5b171d1c3a00ba705093d62b8afc9cf17aeTimo Sirainen 1. Message's DBOX_INDEX_FLAG_ALT flag is changed. This is caught by mdbox
4082d5b171d1c3a00ba705093d62b8afc9cf17aeTimo Sirainen code and map UID's alt-refcount is updated. It won't be written to disk.
4082d5b171d1c3a00ba705093d62b8afc9cf17aeTimo Sirainen 2. mdbox_purge() is called, which checks if map UID's refcount equals
4082d5b171d1c3a00ba705093d62b8afc9cf17aeTimo Sirainen to its alt-refcount. If it does, it's moved to alt storage. Moving to
4082d5b171d1c3a00ba705093d62b8afc9cf17aeTimo Sirainen primary storage is done if _ALT flag was removed from any message.
4082d5b171d1c3a00ba705093d62b8afc9cf17aeTimo Sirainen /* list of file_ids that exist in primary storage. this list is looked
4082d5b171d1c3a00ba705093d62b8afc9cf17aeTimo Sirainen up while there is no locking, so it may not be accurate anymore by
4082d5b171d1c3a00ba705093d62b8afc9cf17aeTimo Sirainen the time it's used. */
4082d5b171d1c3a00ba705093d62b8afc9cf17aeTimo Sirainen /* list of file_ids that we need to purge */
d06d6667bac64aabe1efb216af56ca45108d63b0Timo Sirainen /* map_uid => mdbox_msg_action */
d06d6667bac64aabe1efb216af56ca45108d63b0Timo Sirainenstatic int mdbox_map_file_msg_offset_cmp(const void *p1, const void *p2)
d06d6667bac64aabe1efb216af56ca45108d63b0Timo Sirainen const struct mdbox_map_file_msg *m1 = p1, *m2 = p2;
199566f5a171b2c43b9a5254634f6bf47b8baca8Timo Sirainenmdbox_file_read_metadata_hdr(struct dbox_file *file,
199566f5a171b2c43b9a5254634f6bf47b8baca8Timo Sirainen const unsigned char *data;
199566f5a171b2c43b9a5254634f6bf47b8baca8Timo Sirainen ret = i_stream_read_data(file->input, &data, &size,
199566f5a171b2c43b9a5254634f6bf47b8baca8Timo Sirainen dbox_file_set_corrupted(file, "missing metadata");
199566f5a171b2c43b9a5254634f6bf47b8baca8Timo Sirainen mail_storage_set_critical(&file->storage->storage,
48acc31adebfdd4e4945ee76e1f5259e4b1b6fffTimo Sirainen memcpy(meta_hdr_r, data, sizeof(*meta_hdr_r));
48acc31adebfdd4e4945ee76e1f5259e4b1b6fffTimo Sirainen if (memcmp(meta_hdr_r->magic_post, DBOX_MAGIC_POST,
48acc31adebfdd4e4945ee76e1f5259e4b1b6fffTimo Sirainen dbox_file_set_corrupted(file, "invalid metadata magic");
48acc31adebfdd4e4945ee76e1f5259e4b1b6fffTimo Sirainen i_stream_skip(file->input, sizeof(*meta_hdr_r));
48acc31adebfdd4e4945ee76e1f5259e4b1b6fffTimo Sirainenmdbox_file_metadata_copy(struct dbox_file *file, struct ostream *output)
48acc31adebfdd4e4945ee76e1f5259e4b1b6fffTimo Sirainen if ((ret = mdbox_file_read_metadata_hdr(file, &meta_hdr)) <= 0)
48acc31adebfdd4e4945ee76e1f5259e4b1b6fffTimo Sirainen o_stream_send(output, &meta_hdr, sizeof(meta_hdr));
48acc31adebfdd4e4945ee76e1f5259e4b1b6fffTimo Sirainen buf_size = i_stream_get_max_buffer_size(file->input);
461ffead9720d1e516b959d5e41f049c73d38c7cTimo Sirainen while ((line = i_stream_read_next_line(file->input)) != NULL) {
48acc31adebfdd4e4945ee76e1f5259e4b1b6fffTimo Sirainen /* end of metadata */
48acc31adebfdd4e4945ee76e1f5259e4b1b6fffTimo Sirainen i_stream_set_max_buffer_size(file->input, buf_size);
48acc31adebfdd4e4945ee76e1f5259e4b1b6fffTimo Sirainen dbox_file_set_corrupted(file, "missing end-of-metadata line");
d06d6667bac64aabe1efb216af56ca45108d63b0Timo Sirainenmdbox_metadata_get_extrefs(struct dbox_file *file, pool_t ext_refs_pool,
48acc31adebfdd4e4945ee76e1f5259e4b1b6fffTimo Sirainen /* skip and ignore the header */
48acc31adebfdd4e4945ee76e1f5259e4b1b6fffTimo Sirainen if ((ret = mdbox_file_read_metadata_hdr(file, &meta_hdr)) <= 0)
48acc31adebfdd4e4945ee76e1f5259e4b1b6fffTimo Sirainen buf_size = i_stream_get_max_buffer_size(file->input);
48acc31adebfdd4e4945ee76e1f5259e4b1b6fffTimo Sirainen while ((line = i_stream_read_next_line(file->input)) != NULL) {
48acc31adebfdd4e4945ee76e1f5259e4b1b6fffTimo Sirainen /* end of metadata */
48acc31adebfdd4e4945ee76e1f5259e4b1b6fffTimo Sirainen if (!dbox_attachment_parse_extref(line+1, ext_refs_pool,
48acc31adebfdd4e4945ee76e1f5259e4b1b6fffTimo Sirainen i_warning("%s: Ignoring corrupted extref: %s",
48acc31adebfdd4e4945ee76e1f5259e4b1b6fffTimo Sirainen i_stream_set_max_buffer_size(file->input, buf_size);
48acc31adebfdd4e4945ee76e1f5259e4b1b6fffTimo Sirainen dbox_file_set_corrupted(file, "missing end-of-metadata line");
8ae72ad7d0c69e972cfa65d1e2ce4e3e9a8b765cTimo Sirainenmdbox_purge_want_altpath(struct mdbox_purge_context *ctx, uint32_t map_uid)
48acc31adebfdd4e4945ee76e1f5259e4b1b6fffTimo Sirainen value = hash_table_lookup(ctx->altmoves, POINTER_CAST(map_uid));
48acc31adebfdd4e4945ee76e1f5259e4b1b6fffTimo Sirainen action = POINTER_CAST_TO(value, enum mdbox_msg_action);
48acc31adebfdd4e4945ee76e1f5259e4b1b6fffTimo Sirainen return action == MDBOX_MSG_ACTION_MOVE_TO_ALT;
48acc31adebfdd4e4945ee76e1f5259e4b1b6fffTimo Sirainenmdbox_purge_save_msg(struct mdbox_purge_context *ctx, struct dbox_file *file,
48acc31adebfdd4e4945ee76e1f5259e4b1b6fffTimo Sirainen struct dbox_file_append_context *out_file_append;
48acc31adebfdd4e4945ee76e1f5259e4b1b6fffTimo Sirainen ctx->append_ctx = mdbox_map_append_begin(ctx->atomic);
48acc31adebfdd4e4945ee76e1f5259e4b1b6fffTimo Sirainen append_flags = !mdbox_purge_want_altpath(ctx, msg->map_uid) ? 0 :
48acc31adebfdd4e4945ee76e1f5259e4b1b6fffTimo Sirainen msg_size = file->msg_header_size + file->cur_physical_size;
48acc31adebfdd4e4945ee76e1f5259e4b1b6fffTimo Sirainen if (mdbox_map_append_next(ctx->append_ctx, file->cur_physical_size,
86bde2c1838d1ce967fa2b394bb952004a4adcb7Timo Sirainen input = i_stream_create_limit(file->input, msg_size);
48acc31adebfdd4e4945ee76e1f5259e4b1b6fffTimo Sirainen mail_storage_set_critical(&file->storage->storage,
48acc31adebfdd4e4945ee76e1f5259e4b1b6fffTimo Sirainen mail_storage_set_critical(&file->storage->storage,
48acc31adebfdd4e4945ee76e1f5259e4b1b6fffTimo Sirainen "write(%s) failed: %m",
48acc31adebfdd4e4945ee76e1f5259e4b1b6fffTimo Sirainen dbox_file_set_corrupted(file, "truncated message at EOF");
48acc31adebfdd4e4945ee76e1f5259e4b1b6fffTimo Sirainen /* copy metadata */
4082d5b171d1c3a00ba705093d62b8afc9cf17aeTimo Sirainen if ((ret = mdbox_file_metadata_copy(file, output)) <= 0)
unsigned int i, count;
int ret;
for (i = 0; i < count; i++) {
&refcount);
if (ret <= 0) {
if (ret < 0)
if (refcount > 0)
int ret = 0;
return ret;
unsigned int i, count;
int ret;
return ret;
&msgs_arr) < 0) {
for (i = 0; i < count; i++) {
ret = 0;
&ext_refs);
if (ret <= 0)
if (ret <= 0)
ret = 0;
if (ret <= 0)
if (ret <= 0) {
&expunged_map_uids) < 0 ||
if (ret > 0) {
return ret;
static struct mdbox_purge_context *
return ctx;
struct dirent *d;
int ret = 0;
&file_id) < 0)
if (errno != 0) {
return ret;
int ret = 0;
count = 0;
cur_map_uid = 0;
for (i = 0; i < count; i++) {
alt_refcount++;
count = 0;
cur_map_uid = 0;
for (i = 0; i < count; i++) {
return ret;
bool deleted;
int ret;
while (ret == 0 &&
} T_END;
return ret;