[dovecot-cvs]
dovecot/src/lib-storage/index/mbox mbox-expunge.c,1.28,1.29
mbox-storage.c,1.60,1.61 mbox-storage.h,1.15,1.16
cras at procontrol.fi
cras at procontrol.fi
Sat Jul 26 20:33:25 EEST 2003
- Previous message: [dovecot-cvs]
dovecot/src/pop3 client.c,1.11,1.12 commands.c,1.8,1.9
mail-storage-callbacks.c,1.1,1.2
- Next message: [dovecot-cvs] dovecot/src/imap main.c,1.38,1.39 common.h,1.9,1.10
client.c,1.31,1.32
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
Update of /home/cvs/dovecot/src/lib-storage/index/mbox
In directory danu:/tmp/cvs-serv28560/lib-storage/index/mbox
Modified Files:
mbox-expunge.c mbox-storage.c mbox-storage.h
Log Message:
API change for expunging messages. Not exactly what I wanted, but good
enough.
Index: mbox-expunge.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-storage/index/mbox/mbox-expunge.c,v
retrieving revision 1.28
retrieving revision 1.29
diff -u -d -r1.28 -r1.29
--- mbox-expunge.c 21 Jul 2003 14:35:39 -0000 1.28
+++ mbox-expunge.c 26 Jul 2003 16:33:22 -0000 1.29
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002 Timo Sirainen */
+/* Copyright (C) 2002-2003 Timo Sirainen */
#include "lib.h"
#include "istream.h"
@@ -6,179 +6,204 @@
#include "mbox-index.h"
#include "mbox-storage.h"
#include "mbox-lock.h"
+#include "index-expunge.h"
#include <fcntl.h>
#include <unistd.h>
-static int expunge_real(struct index_mailbox *ibox,
- struct mail_index_record *rec, unsigned int seq,
- struct istream *input, struct ostream *output,
- int notify)
-{
- struct mail_index_record *first_rec, *last_rec;
- uoff_t offset, hdr_size, body_size;
- uoff_t end_offset, from_offset, copy_size, old_limit;
- const unsigned char *data;
- size_t size;
- unsigned int first_seq, last_seq;
- int expunges, skip_next, deleted, failed;
+struct mbox_expunge_context {
+ struct mail_expunge_context *ctx;
- if (seq == 1)
- end_offset = 0;
- else {
- /* we need to find offset to beginning of From-line.
- not the fastest way maybe, but easiest.. */
- rec = ibox->index->lookup(ibox->index, seq-1);
-
- if (!mbox_mail_get_location(ibox->index, rec, &offset,
- &hdr_size, &body_size))
- return FALSE;
- end_offset = offset + hdr_size + body_size;
+ struct index_mailbox *ibox;
+ struct istream *input;
+ struct ostream *output;
+ int failed, expunges;
- /* get back to the deleted record */
- rec = ibox->index->next(ibox->index, rec);
- }
+ uoff_t from_offset, move_offset;
+};
- old_limit = input->v_limit;
+struct mail_expunge_context *
+mbox_storage_expunge_init(struct mailbox *box,
+ enum mail_fetch_field wanted_fields, int expunge_all)
+{
+ struct index_mailbox *ibox = (struct index_mailbox *) box;
+ struct mbox_expunge_context *ctx;
+ struct mail_expunge_context *mctx;
+ struct istream *input;
- first_rec = last_rec = NULL;
- first_seq = last_seq = 0;
+ mctx = index_storage_expunge_init(box, wanted_fields, expunge_all);
+ if (mctx == NULL)
+ return NULL;
- expunges = FALSE; skip_next = FALSE;
- while (rec != NULL) {
- if (!mbox_mail_get_location(ibox->index, rec, &offset,
- &hdr_size, &body_size))
- return FALSE;
+ /* mbox must be already opened, synced and locked at this point.
+ we just want the istream. */
+ input = mbox_get_stream(ibox->index, 0, MAIL_LOCK_EXCLUSIVE);
+ if (input == NULL)
+ return NULL;
- from_offset = end_offset;
- end_offset = offset + hdr_size + body_size;
+ i_assert(ibox->index->mbox_sync_counter ==
+ ibox->index->mbox_lock_counter);
- deleted = (rec->msg_flags & MAIL_DELETED) != 0;
- if (deleted) {
- if (first_rec == NULL) {
- first_rec = rec;
- first_seq = seq;
- }
- last_rec = rec;
- last_seq = seq;
+ ctx = i_new(struct mbox_expunge_context, 1);
+ ctx->ctx = mctx;
+ ctx->ibox = ibox;
+ ctx->input = input;
+ ctx->output = o_stream_create_file(ibox->index->mbox_fd, default_pool,
+ 4096, FALSE);
+ ctx->from_offset = (uoff_t)-1;
+ ctx->move_offset = (uoff_t)-1;
+ o_stream_set_blocking(ctx->output, 60000, NULL, NULL);
+ return (struct mail_expunge_context *) ctx;
+}
- if (!expunges) {
- /* first expunged record, seek to position
- where we want to begin writing */
- if (o_stream_seek(output, from_offset) < 0)
- return FALSE;
- expunges = TRUE;
- }
- } else if (first_rec != NULL) {
- if (!index_expunge_mails(ibox, first_rec, last_rec,
- first_seq, last_seq, notify))
- return FALSE;
- first_rec = NULL;
+static int mbox_move_data(struct mbox_expunge_context *ctx)
+{
+ const unsigned char *data;
+ size_t size;
+ uoff_t old_limit;
+ int failed;
- rec = ibox->index->lookup(ibox->index, first_seq);
- seq = first_seq;
- skip_next = TRUE;
- }
+ i_assert(ctx->input->v_offset <= ctx->move_offset);
+ i_stream_skip(ctx->input, ctx->move_offset - ctx->input->v_offset);
- if (skip_next)
- skip_next = FALSE;
- else {
- rec = ibox->index->next(ibox->index, rec);
- seq++;
- }
+ if (ctx->output->offset == 0) {
+ /* we're writing to beginning of mbox, so we
+ don't want the [\r]\n there */
+ (void)i_stream_read_data(ctx->input, &data, &size, 1);
+ if (size > 0 && data[0] == '\n')
+ i_stream_skip(ctx->input, 1);
+ else if (size > 1 && data[0] == '\r' &&
+ data[1] == '\n')
+ i_stream_skip(ctx->input, 2);
+ }
- if (expunges && !deleted) {
- /* seek to wanted input position, and copy
- this messages */
- i_assert(input->v_offset <= from_offset);
- i_stream_skip(input, from_offset - input->v_offset);
+ old_limit = ctx->input->v_limit;
+ i_stream_set_read_limit(ctx->input, ctx->from_offset);
+ failed = o_stream_send_istream(ctx->output, ctx->input) < 0;
+ i_stream_set_read_limit(ctx->input, old_limit);
- if (output->offset == 0) {
- /* we're writing to beginning of mbox, so we
- don't want the [\r]\n there */
- (void)i_stream_read_data(input, &data,
- &size, 1);
- if (size > 0 && data[0] == '\n')
- i_stream_skip(input, 1);
- else if (size > 1 && data[0] == '\r' &&
- data[1] == '\n')
- i_stream_skip(input, 2);
- }
+ if (failed || ctx->input->v_offset != ctx->from_offset)
+ return FALSE;
+ return TRUE;
+}
- i_stream_set_read_limit(input, end_offset);
- failed = o_stream_send_istream(output, input) < 0;
- i_stream_set_read_limit(input, old_limit);
+int mbox_storage_expunge_deinit(struct mail_expunge_context *_ctx)
+{
+ struct mbox_expunge_context *ctx = (struct mbox_expunge_context *) _ctx;
+ int failed = ctx->failed;
- if (failed || input->v_offset != end_offset)
- return FALSE;
+ if (ctx->expunges) {
+ if (!failed && ctx->move_offset != (uoff_t)-1) {
+ ctx->from_offset = ctx->input->v_limit;
+ if (!mbox_move_data(ctx))
+ failed = TRUE;
+ } else if (failed && ctx->output->offset > 0) {
+ /* we moved some of the data. move the rest as well
+ so there won't be invalid holes in mbox file */
+ (void)o_stream_send_istream(ctx->output, ctx->input);
}
- }
- if (first_rec != NULL) {
- if (!index_expunge_mails(ibox, first_rec, last_rec,
- first_seq, last_seq, notify))
- return FALSE;
+ if (ftruncate(ctx->ibox->index->mbox_fd,
+ (off_t)ctx->output->offset) < 0) {
+ mail_storage_set_error(ctx->ibox->box.storage,
+ "ftruncate() failed for mbox file %s: %m",
+ ctx->ibox->index->mailbox_path);
+ failed = TRUE;
+ }
}
- i_stream_skip(input, end_offset - input->v_offset);
-
- /* copy the rest as well, should be only \n but someone might
- as well just appended more data.. but if we've deleted all mail,
- don't write the only \n there. */
- copy_size = input->v_size - input->v_offset;
- if (output->offset == 0 && copy_size == 1)
- return TRUE;
+ if (!index_storage_expunge_deinit(ctx->ctx))
+ failed = TRUE;
- return o_stream_send_istream(output, input) >= 0;
+ o_stream_unref(ctx->output);
+ i_free(ctx);
+ return !failed;
}
-int mbox_expunge_locked(struct index_mailbox *ibox, int notify)
+static int get_from_offset(struct mail_index *index,
+ struct mail_index_record *rec, uoff_t *offset_r)
{
- struct mail_index_record *rec;
- struct istream *input;
- struct ostream *output;
- unsigned int seq;
- int failed;
+ uoff_t offset, hdr_size, body_size;
- if (!index_expunge_seek_first(ibox, &seq, &rec))
+ if (!mbox_mail_get_location(index, rec, &offset,
+ &hdr_size, &body_size))
return FALSE;
- if (rec == NULL) {
- /* no deleted messages */
- return TRUE;
+ *offset_r = offset + hdr_size + body_size;
+ return TRUE;
+}
+
+struct mail *mbox_storage_expunge_fetch_next(struct mail_expunge_context *_ctx)
+{
+ struct mbox_expunge_context *ctx =
+ (struct mbox_expunge_context *) _ctx;
+ struct mail_expunge_context *mctx = ctx->ctx;
+ struct mail_index *index = ctx->ibox->index;
+
+ if (mctx->rec == NULL)
+ return NULL;
+
+ if (mctx->fetch_next) {
+ mctx->fetch_next = FALSE;
+ do {
+ if (!get_from_offset(index, mctx->rec,
+ &ctx->from_offset)) {
+ ctx->failed = TRUE;
+ return NULL;
+ }
+
+ mctx->seq++;
+ mctx->rec = index->next(index, mctx->rec);
+ if (mctx->rec == NULL)
+ return NULL;
+ } while ((mctx->rec->msg_flags & MAIL_DELETED) == 0 &&
+ !mctx->expunge_all);
}
- /* mbox must be already opened, synced and locked at this point.
- we just want the istream. */
- input = mbox_get_stream(ibox->index, 0, MAIL_LOCK_EXCLUSIVE);
- if (input == NULL)
- return FALSE;
+ return index_storage_expunge_fetch_next(ctx->ctx);
+}
- i_assert(ibox->index->mbox_sync_counter ==
- ibox->index->mbox_lock_counter);
+static int get_prev_from_offset(struct mbox_expunge_context *ctx,
+ unsigned int seq)
+{
+ struct mail_index_record *rec;
- t_push();
- output = o_stream_create_file(ibox->index->mbox_fd, data_stack_pool,
- 4096, FALSE);
- o_stream_set_blocking(output, 60000, NULL, NULL);
+ if (seq == 1)
+ ctx->from_offset = 0;
+ else {
+ rec = ctx->ibox->index->lookup(ctx->ibox->index, seq-1);
- failed = !expunge_real(ibox, rec, seq, input, output, notify);
+ if (!get_from_offset(ctx->ibox->index, rec, &ctx->from_offset))
+ return FALSE;
+ }
- if (failed && output->offset > 0) {
- /* we moved some of the data. move the rest as well so there
- won't be invalid holes in mbox file */
- (void)o_stream_send_istream(output, input);
+ return TRUE;
+}
+
+int mbox_storage_expunge(struct mail *mail, struct mail_expunge_context *_ctx,
+ unsigned int *seq_r, int notify)
+{
+ struct mbox_expunge_context *ctx = (struct mbox_expunge_context *) _ctx;
+ struct index_mail *imail = (struct index_mail *) mail;
+
+ if (ctx->from_offset == (uoff_t)-1) {
+ if (!get_prev_from_offset(ctx, imail->data.idx_seq))
+ return FALSE;
}
- if (ftruncate(ibox->index->mbox_fd, (off_t)output->offset) < 0) {
- mail_storage_set_error(ibox->box.storage, "ftruncate() failed "
- "for mbox file %s: %m",
- ibox->index->mailbox_path);
- failed = TRUE;
+ if (!ctx->expunges) {
+ /* first expunged message */
+ if (o_stream_seek(ctx->output, ctx->from_offset) < 0)
+ return FALSE;
+ ctx->expunges = TRUE;
+ } else if (ctx->move_offset != ctx->from_offset) {
+ if (!mbox_move_data(ctx))
+ return FALSE;
}
- o_stream_unref(output);
- t_pop();
+ if (!get_from_offset(ctx->ibox->index, imail->data.rec,
+ &ctx->move_offset))
+ return FALSE;
- return !failed;
+ return index_storage_expunge(mail, ctx->ctx, seq_r, notify);
}
Index: mbox-storage.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-storage/index/mbox/mbox-storage.c,v
retrieving revision 1.60
retrieving revision 1.61
diff -u -d -r1.60 -r1.61
--- mbox-storage.c 23 Jul 2003 02:55:12 -0000 1.60
+++ mbox-storage.c 26 Jul 2003 16:33:22 -0000 1.61
@@ -319,6 +319,11 @@
return t_strconcat(storage->dir, "/", name, NULL);
}
+static void mbox_mail_init(struct index_mail *mail)
+{
+ mail->mail.expunge = mbox_storage_expunge;
+}
+
static struct mailbox *mbox_open(struct mail_storage *storage, const char *name,
enum mailbox_open_flags flags)
{
@@ -349,7 +354,7 @@
ibox = index_storage_mailbox_init(storage, &mbox_mailbox, index,
name, flags);
if (ibox != NULL)
- ibox->expunge_locked = mbox_expunge_locked;
+ ibox->mail_init = mbox_mail_init;
return (struct mailbox *) ibox;
}
@@ -780,7 +785,6 @@
index_storage_get_status,
index_storage_sync,
mbox_storage_auto_sync,
- index_storage_expunge,
index_storage_fetch_init,
index_storage_fetch_deinit,
index_storage_fetch_next,
@@ -795,6 +799,9 @@
mbox_storage_save_next,
index_storage_copy_init,
index_storage_copy_deinit,
+ mbox_storage_expunge_init,
+ mbox_storage_expunge_deinit,
+ mbox_storage_expunge_fetch_next,
mail_storage_is_inconsistency_error,
FALSE,
Index: mbox-storage.h
===================================================================
RCS file: /home/cvs/dovecot/src/lib-storage/index/mbox/mbox-storage.h,v
retrieving revision 1.15
retrieving revision 1.16
diff -u -d -r1.15 -r1.16
--- mbox-storage.h 19 Feb 2003 19:55:27 -0000 1.15
+++ mbox-storage.h 26 Jul 2003 16:33:22 -0000 1.16
@@ -20,7 +20,13 @@
int mbox_list_mailbox_deinit(struct mailbox_list_context *ctx);
struct mailbox_list *mbox_list_mailbox_next(struct mailbox_list_context *ctx);
-int mbox_expunge_locked(struct index_mailbox *ibox, int notify);
+struct mail_expunge_context *
+mbox_storage_expunge_init(struct mailbox *box,
+ enum mail_fetch_field wanted_fields, int expunge_all);
+int mbox_storage_expunge_deinit(struct mail_expunge_context *ctx);
+struct mail *mbox_storage_expunge_fetch_next(struct mail_expunge_context *ctx);
+int mbox_storage_expunge(struct mail *mail, struct mail_expunge_context *ctx,
+ unsigned int *seq_r, int notify);
int mbox_is_valid_mask(const char *mask);
- Previous message: [dovecot-cvs]
dovecot/src/pop3 client.c,1.11,1.12 commands.c,1.8,1.9
mail-storage-callbacks.c,1.1,1.2
- Next message: [dovecot-cvs] dovecot/src/imap main.c,1.38,1.39 common.h,1.9,1.10
client.c,1.31,1.32
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
More information about the dovecot-cvs
mailing list