mdbox-purge.c revision 50854b51d6408653be4dd90bd0427978df25c2b7
2454dfa32c93c20a8522c6ed42fe057baaac9f9aStephan Bosch/* Copyright (c) 2007-2011 Dovecot authors, see the included COPYING file */
4c9294fcb17fb12326ff5db29e2f882cf4bd7fedTimo Sirainen Altmoving works like:
4c9294fcb17fb12326ff5db29e2f882cf4bd7fedTimo Sirainen 1. Message's DBOX_INDEX_FLAG_ALT flag is changed. This is caught by mdbox
4c9294fcb17fb12326ff5db29e2f882cf4bd7fedTimo Sirainen code and map UID's alt-refcount is updated. It won't be written to disk.
4c9294fcb17fb12326ff5db29e2f882cf4bd7fedTimo Sirainen 2. mdbox_purge() is called, which checks if map UID's refcount equals
4c9294fcb17fb12326ff5db29e2f882cf4bd7fedTimo Sirainen to its alt-refcount. If it does, it's moved to alt storage. Moving to
4c9294fcb17fb12326ff5db29e2f882cf4bd7fedTimo Sirainen primary storage is done if _ALT flag was removed from any message.
18a2214eedb08d043277cf1d3e75c45762014663Timo Sirainen /* list of file_ids that exist in primary storage. this list is looked
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen up while there is no locking, so it may not be accurate anymore by
18a2214eedb08d043277cf1d3e75c45762014663Timo Sirainen the time it's used. */
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen /* list of file_ids that we need to purge */
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen /* map_uid => mdbox_msg_action */
6b8f4863bb2b0938d40f774122baf6528a833ea0Timo Sirainenstatic int mdbox_map_file_msg_offset_cmp(const void *p1, const void *p2)
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen const struct mdbox_map_file_msg *m1 = p1, *m2 = p2;
6b8f4863bb2b0938d40f774122baf6528a833ea0Timo Sirainenmdbox_file_read_metadata_hdr(struct dbox_file *file,
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen const unsigned char *data;
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen ret = i_stream_read_data(file->input, &data, &size,
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen dbox_file_set_corrupted(file, "missing metadata");
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen mail_storage_set_critical(&file->storage->storage,
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen memcpy(meta_hdr_r, data, sizeof(*meta_hdr_r));
18a2214eedb08d043277cf1d3e75c45762014663Timo Sirainen if (memcmp(meta_hdr_r->magic_post, DBOX_MAGIC_POST,
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen dbox_file_set_corrupted(file, "invalid metadata magic");
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen i_stream_skip(file->input, sizeof(*meta_hdr_r));
e106213aebb4170904697814c168548e1ba97de9Timo Sirainenmdbox_file_metadata_copy(struct dbox_file *file, struct ostream *output)
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen if ((ret = mdbox_file_read_metadata_hdr(file, &meta_hdr)) <= 0)
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen o_stream_send(output, &meta_hdr, sizeof(meta_hdr));
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen buf_size = i_stream_get_max_buffer_size(file->input);
6b8f4863bb2b0938d40f774122baf6528a833ea0Timo Sirainen while ((line = i_stream_read_next_line(file->input)) != NULL) {
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen /* end of metadata */
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen i_stream_set_max_buffer_size(file->input, buf_size);
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen dbox_file_set_corrupted(file, "missing end-of-metadata line");
6b8f4863bb2b0938d40f774122baf6528a833ea0Timo Sirainenmdbox_metadata_get_extrefs(struct dbox_file *file, pool_t ext_refs_pool,
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen /* skip and ignore the header */
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen if ((ret = mdbox_file_read_metadata_hdr(file, &meta_hdr)) <= 0)
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen buf_size = i_stream_get_max_buffer_size(file->input);
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen while ((line = i_stream_read_next_line(file->input)) != NULL) {
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen /* end of metadata */
6b8f4863bb2b0938d40f774122baf6528a833ea0Timo Sirainen if (!dbox_attachment_parse_extref(line+1, ext_refs_pool,
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen i_warning("%s: Ignoring corrupted extref: %s",
6b8f4863bb2b0938d40f774122baf6528a833ea0Timo Sirainen i_stream_set_max_buffer_size(file->input, buf_size);
18a2214eedb08d043277cf1d3e75c45762014663Timo Sirainen dbox_file_set_corrupted(file, "missing end-of-metadata line");
6b8f4863bb2b0938d40f774122baf6528a833ea0Timo Sirainenmdbox_purge_want_altpath(struct mdbox_purge_context *ctx, uint32_t map_uid)
6b8f4863bb2b0938d40f774122baf6528a833ea0Timo Sirainen value = hash_table_lookup(ctx->altmoves, POINTER_CAST(map_uid));
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen action = POINTER_CAST_TO(value, enum mdbox_msg_action);
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen return action == MDBOX_MSG_ACTION_MOVE_TO_ALT;
6b8f4863bb2b0938d40f774122baf6528a833ea0Timo Sirainenmdbox_purge_save_msg(struct mdbox_purge_context *ctx, struct dbox_file *file,
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen struct dbox_file_append_context *out_file_append;
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen ctx->append_ctx = mdbox_map_append_begin(ctx->atomic);
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen append_flags = !mdbox_purge_want_altpath(ctx, msg->map_uid) ? 0 :
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen msg_size = file->msg_header_size + file->cur_physical_size;
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen if (mdbox_map_append_next(ctx->append_ctx, file->cur_physical_size,
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen input = i_stream_create_limit(file->input, msg_size);
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen mail_storage_set_critical(&file->storage->storage,
18a2214eedb08d043277cf1d3e75c45762014663Timo Sirainen mail_storage_set_critical(&file->storage->storage,
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen "write(%s) failed: %m",
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen dbox_file_set_corrupted(file, "truncated message at EOF");
f55b07916c82db8b915b28252e44ce6fb2bd3080Timo Sirainen /* copy metadata */
f55b07916c82db8b915b28252e44ce6fb2bd3080Timo Sirainen if ((ret = mdbox_file_metadata_copy(file, output)) <= 0)
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainenmdbox_file_purge_check_refcounts(struct mdbox_purge_context *ctx,
f55b07916c82db8b915b28252e44ce6fb2bd3080Timo Sirainen const ARRAY_TYPE(mdbox_map_file_msg) *msgs_arr)
e106213aebb4170904697814c168548e1ba97de9Timo Sirainen unsigned int i, count;
f55b07916c82db8b915b28252e44ce6fb2bd3080Timo Sirainen for (i = 0; i < count; i++) {
f55b07916c82db8b915b28252e44ce6fb2bd3080Timo Sirainen ret = mdbox_map_lookup_full(map, msgs[i].map_uid, &rec,
f55b07916c82db8b915b28252e44ce6fb2bd3080Timo Sirainen "Purging unexpectedly lost map_uid=%u",
f55b07916c82db8b915b28252e44ce6fb2bd3080Timo Sirainenmdbox_purge_attachments(struct mdbox_purge_context *ctx,
f55b07916c82db8b915b28252e44ce6fb2bd3080Timo Sirainen const ARRAY_TYPE(mail_attachment_extref) *extrefs_arr)
f55b07916c82db8b915b28252e44ce6fb2bd3080Timo Sirainen struct dbox_storage *storage = &ctx->storage->storage;
a1973d0f171b027f9a7c642bc1c2134293731e1cTimo Sirainen if (index_attachment_delete(&storage->storage,
99df8a838cd9c5257ea5a2554383a9a999191e38Pali Rohármdbox_file_purge(struct mdbox_purge_context *ctx, struct dbox_file *file,
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen struct mdbox_storage *dstorage = (struct mdbox_storage *)file->storage;
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen 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;