[dovecot-cvs] dovecot/src/lib-storage/index/maildir maildir-copy.c,1.19,1.20 maildir-save.c,1.15,1.16 maildir-storage.c,1.23,1.24 maildir-storage.h,1.11,1.12
cras at procontrol.fi
cras at procontrol.fi
Wed Jan 22 21:23:30 EET 2003
- Previous message: [dovecot-cvs] dovecot/src/lib-storage/index/mbox mbox-save.c,1.31,1.32 mbox-storage.c,1.33,1.34 mbox-storage.h,1.13,1.14
- Next message: [dovecot-cvs] dovecot/src/lib-index mail-index.c,1.82,1.83 mail-index.h,1.64,1.65 mail-modifylog.c,1.39,1.40
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
Update of /home/cvs/dovecot/src/lib-storage/index/maildir
In directory danu:/tmp/cvs-serv16040/src/lib-storage/index/maildir
Modified Files:
maildir-copy.c maildir-save.c maildir-storage.c
maildir-storage.h
Log Message:
Support for MULTIAPPEND extension. COPY now behaves like spec says - if it
fails, none of the messages are copied. maildir_copy_with_hardlinks didn't
actually work.
Index: maildir-copy.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-storage/index/maildir/maildir-copy.c,v
retrieving revision 1.19
retrieving revision 1.20
diff -u -d -r1.19 -r1.20
--- maildir-copy.c 20 Jan 2003 14:52:51 -0000 1.19
+++ maildir-copy.c 22 Jan 2003 19:23:28 -0000 1.20
@@ -10,24 +10,38 @@
#include <stdlib.h>
#include <unistd.h>
+struct rollback {
+ struct rollback *next;
+ const char *fname;
+};
+
static int hardlink_messageset(struct messageset_context *ctx,
struct index_mailbox *src,
struct index_mailbox *dest)
{
- struct mail_index *index = src->index;
+ struct mail_index *index = src->index;
+ pool_t pool;
+ struct rollback *rollbacks, *rb;
const struct messageset_mail *mail;
enum mail_flags flags;
const char **custom_flags;
- const char *fname, *src_fname, *dest_fname;
+ const char *fname, *src_path, *dest_fname, *dest_path;
+ int ret;
+
+ pool = pool_alloconly_create("hard copy rollbacks", 2048);
+ rollbacks = NULL;
custom_flags = mail_custom_flags_list_get(index->custom_flags);
+ ret = 1;
while ((mail = index_messageset_next(ctx)) != NULL) {
flags = mail->rec->msg_flags;
if (!index_mailbox_fix_custom_flags(dest, &flags,
custom_flags,
- MAIL_CUSTOM_FLAGS_COUNT))
- return -1;
+ MAIL_CUSTOM_FLAGS_COUNT)) {
+ ret = -1;
+ break;
+ }
/* link the file */
fname = index->lookup_field(index, mail->rec,
@@ -36,31 +50,50 @@
index_set_corrupted(index,
"Missing location field for record %u",
mail->rec->uid);
- return -1;
+ ret = -1;
+ break;
}
t_push();
- src_fname = t_strconcat(index->mailbox_path, "cur/",
- fname, NULL);
- dest_fname = t_strconcat(dest->index->mailbox_path, "new/",
- maildir_filename_set_flags(
+ src_path = t_strconcat(index->mailbox_path, "/cur/",
+ fname, NULL);
+ dest_fname = t_strconcat(maildir_filename_set_flags(
maildir_generate_tmp_filename(), flags), NULL);
+ dest_path = t_strconcat(dest->index->mailbox_path, "/new/",
+ dest_fname, NULL);
- if (link(src_fname, dest_fname) < 0) {
+ if (link(src_path, dest_path) == 0) {
+ rb = p_new(pool, struct rollback, 1);
+ rb->fname = p_strdup(pool, dest_fname);
+ rb->next = rollbacks;
+ rollbacks = rb;
+ } else {
if (errno != EXDEV) {
mail_storage_set_critical(src->box.storage,
"link(%s, %s) failed: %m",
- src_fname, dest_fname);
+ src_path, dest_path);
t_pop();
- return -1;
+ ret = -1;
+ break;
}
t_pop();
- return 0;
+ ret = 0;
+ break;
}
t_pop();
}
- return 1;
+ if (ret <= 0) {
+ for (rb = rollbacks; rb != NULL; rb = rb->next) {
+ t_push();
+ (void)unlink(t_strconcat(dest->index->mailbox_path,
+ "new/", rb->fname, NULL));
+ t_pop();
+ }
+ }
+
+ pool_unref(pool);
+ return ret;
}
static int copy_with_hardlinks(struct index_mailbox *src,
@@ -68,15 +101,21 @@
const char *messageset, int uidset)
{
struct messageset_context *ctx;
- int ret;
+ int ret, ret2;
if (!index_storage_sync_and_lock(src, TRUE, MAIL_LOCK_SHARED))
return -1;
- ctx = index_messageset_init(src, messageset, uidset);
+ ctx = index_messageset_init(src, messageset, uidset, FALSE);
ret = hardlink_messageset(ctx, src, dest);
- if (index_messageset_deinit(ctx) < 0)
+ ret2 = index_messageset_deinit(ctx);
+ if (ret2 < 0)
ret = -1;
+ else {
+ mail_storage_set_error(src->box.storage,
+ "Some of the requested messages no longer exist.");
+ ret = -1;
+ }
(void)index_storage_lock(src, MAIL_LOCK_UNLOCK);
Index: maildir-save.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-storage/index/maildir/maildir-save.c,v
retrieving revision 1.15
retrieving revision 1.16
diff -u -d -r1.15 -r1.16
--- maildir-save.c 20 Jan 2003 14:52:51 -0000 1.15
+++ maildir-save.c 22 Jan 2003 19:23:28 -0000 1.16
@@ -12,6 +12,21 @@
#include <fcntl.h>
#include <utime.h>
+struct mail_filename {
+ struct mail_filename *next;
+ const char *src, *dest;
+};
+
+struct mail_save_context {
+ pool_t pool;
+
+ struct index_mailbox *ibox;
+ int transaction;
+
+ const char *tmpdir, *newdir;
+ struct mail_filename *files;
+};
+
const char *maildir_generate_tmp_filename(void)
{
static unsigned int create_count = 0;
@@ -49,7 +64,7 @@
static const char *
maildir_read_into_tmp(struct mail_storage *storage, const char *dir,
- struct istream *input, uoff_t data_size)
+ struct istream *input)
{
const char *fname, *path;
struct ostream *output;
@@ -65,7 +80,7 @@
o_stream_set_blocking(output, 60000, NULL, NULL);
path = t_strconcat(dir, "/", fname, NULL);
- if (!index_storage_save(storage, path, input, output, data_size))
+ if (!index_storage_save(storage, path, input, output))
fname = NULL;
o_stream_unref(output);
@@ -78,25 +93,48 @@
return fname;
}
-int maildir_storage_save(struct mailbox *box,
- const struct mail_full_flags *flags,
- time_t internal_date,
- int timezone_offset __attr_unused__,
- struct istream *data, uoff_t data_size)
+static int maildir_copy(struct mail_save_context *ctx,
+ const char *src, const char *dest)
+{
+ const char *tmp_path, *new_path;
+
+ t_push();
+
+ tmp_path = t_strconcat(ctx->tmpdir, "/", src, NULL);
+ new_path = t_strconcat(ctx->newdir, "/", dest, NULL);
+
+ if (rename(tmp_path, new_path) == 0) {
+ t_pop();
+ return TRUE;
+ }
+
+ if (errno == ENOSPC) {
+ mail_storage_set_error(ctx->ibox->box.storage,
+ "Not enough disk space");
+ } else {
+ mail_storage_set_critical(ctx->ibox->box.storage,
+ "rename(%s, %s) failed: %m",
+ tmp_path, new_path);
+ }
+
+ (void)unlink(tmp_path);
+ t_pop();
+ return FALSE;
+}
+
+int maildir_storage_save_next(struct mail_save_context *ctx,
+ const struct mail_full_flags *flags,
+ time_t received_date,
+ int timezone_offset __attr_unused__,
+ struct istream *data)
{
- struct index_mailbox *ibox = (struct index_mailbox *) box;
enum mail_flags mail_flags;
struct utimbuf buf;
- const char *tmpdir, *fname, *tmp_path, *new_path;
+ const char *fname, *dest_fname, *tmp_path;
int failed;
- if (box->readonly) {
- mail_storage_set_error(box->storage, "Mailbox is read-only");
- return FALSE;
- }
-
mail_flags = flags->flags;
- if (!index_mailbox_fix_custom_flags(ibox, &mail_flags,
+ if (!index_mailbox_fix_custom_flags(ctx->ibox, &mail_flags,
flags->custom_flags,
flags->custom_flags_count))
return FALSE;
@@ -104,44 +142,100 @@
t_push();
/* create the file into tmp/ directory */
- tmpdir = t_strconcat(ibox->index->mailbox_path, "/tmp", NULL);
- fname = maildir_read_into_tmp(box->storage, tmpdir, data, data_size);
+ fname = maildir_read_into_tmp(ctx->ibox->box.storage,
+ ctx->tmpdir, data);
if (fname == NULL) {
t_pop();
return FALSE;
}
- tmp_path = t_strconcat(tmpdir, "/", fname, NULL);
- fname = maildir_filename_set_flags(fname, mail_flags);
- new_path = t_strconcat(ibox->index->mailbox_path, "/new/", fname, NULL);
+ tmp_path = t_strconcat(ctx->tmpdir, "/", fname, NULL);
- /* set the internal_date by modifying mtime */
+ /* set the received_date by modifying mtime */
buf.actime = ioloop_time;
- buf.modtime = internal_date;
+ buf.modtime = received_date;
if (utime(tmp_path, &buf) < 0) {
- /* just warn, don't bother actually failing */
- mail_storage_set_critical(box->storage, "utime() failed for "
- "%s: %m", tmp_path);
+ mail_storage_set_critical(ctx->ibox->box.storage,
+ "utime() failed for %s: %m",
+ tmp_path);
+ t_pop();
+ return FALSE;
}
- /* move the file into new/ directory - syncing will pick it
- up from there */
- if (rename(tmp_path, new_path) == 0)
+ /* now, if we want to be able to rollback the whole append session,
+ we'll just store the name of this temp file and move it later
+ into new/ */
+ dest_fname = maildir_filename_set_flags(fname, mail_flags);
+ if (ctx->transaction) {
+ struct mail_filename *mf;
+
+ mf = p_new(ctx->pool, struct mail_filename, 1);
+ mf->next = ctx->files;
+ mf->src = p_strdup(ctx->pool, fname);
+ mf->dest = p_strdup(ctx->pool, dest_fname);
+ ctx->files = mf;
+
failed = FALSE;
- else {
- if (errno == ENOSPC) {
- mail_storage_set_error(box->storage,
- "Not enough disk space");
- } else {
- mail_storage_set_critical(box->storage,
- "rename(%s, %s) failed: %m",
- tmp_path, new_path);
+ } else {
+ failed = !maildir_copy(ctx, fname, dest_fname);
+ }
+
+ t_pop();
+ return !failed;
+}
+
+struct mail_save_context *
+maildir_storage_save_init(struct mailbox *box, int transaction)
+{
+ struct index_mailbox *ibox = (struct index_mailbox *) box;
+ struct mail_save_context *ctx;
+ pool_t pool;
+
+ if (box->readonly) {
+ mail_storage_set_error(box->storage, "Mailbox is read-only");
+ return NULL;
+ }
+
+ pool = pool_alloconly_create("mail_save_context", 2048);
+ ctx = p_new(pool, struct mail_save_context, 1);
+ ctx->pool = pool;
+ ctx->ibox = ibox;
+ ctx->transaction = transaction;
+
+ ctx->tmpdir = p_strconcat(pool, ibox->index->mailbox_path,
+ "/tmp", NULL);
+ ctx->newdir = p_strconcat(pool, ibox->index->mailbox_path,
+ "/new", NULL);
+
+ return ctx;
+}
+
+int maildir_storage_save_deinit(struct mail_save_context *ctx, int rollback)
+{
+ struct mail_filename *mf, *mf2;
+ const char *new_path;
+ int failed = FALSE;
+
+ if (!rollback) {
+ for (mf = ctx->files; mf != NULL; mf = mf->next) {
+ if (!maildir_copy(ctx, mf->src, mf->dest)) {
+ failed = TRUE;
+ break;
+ }
}
- (void)unlink(tmp_path);
- failed = TRUE;
+ if (failed) {
+ /* failed, try to unlink the mails already moved */
+ for (mf2 = ctx->files; mf2 != mf; mf2 = mf2->next) {
+ t_push();
+ new_path = t_strconcat(ctx->newdir, "/",
+ mf2->dest, NULL);
+ (void)unlink(new_path);
+ t_pop();
+ }
+ }
}
- t_pop();
+ pool_unref(ctx->pool);
return !failed;
}
Index: maildir-storage.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-storage/index/maildir/maildir-storage.c,v
retrieving revision 1.23
retrieving revision 1.24
diff -u -d -r1.23 -r1.24
--- maildir-storage.c 20 Jan 2003 14:52:51 -0000 1.23
+++ maildir-storage.c 22 Jan 2003 19:23:28 -0000 1.24
@@ -569,7 +569,9 @@
index_storage_search_init,
index_storage_search_deinit,
index_storage_search_next,
- maildir_storage_save,
+ maildir_storage_save_init,
+ maildir_storage_save_deinit,
+ maildir_storage_save_next,
mail_storage_is_inconsistency_error,
FALSE,
Index: maildir-storage.h
===================================================================
RCS file: /home/cvs/dovecot/src/lib-storage/index/maildir/maildir-storage.h,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -d -r1.11 -r1.12
--- maildir-storage.h 20 Jan 2003 14:52:51 -0000 1.11
+++ maildir-storage.h 22 Jan 2003 19:23:28 -0000 1.12
@@ -5,10 +5,14 @@
int maildir_storage_copy(struct mailbox *box, struct mailbox *destbox,
const char *messageset, int uidset);
-int maildir_storage_save(struct mailbox *box,
- const struct mail_full_flags *flags,
- time_t internal_date, int timezone_offset,
- struct istream *data, uoff_t data_size);
+
+struct mail_save_context *
+maildir_storage_save_init(struct mailbox *box, int transaction);
+int maildir_storage_save_deinit(struct mail_save_context *ctx, int rollback);
+int maildir_storage_save_next(struct mail_save_context *ctx,
+ const struct mail_full_flags *flags,
+ time_t received_date, int timezone_offset,
+ struct istream *data);
int maildir_find_mailboxes(struct mail_storage *storage, const char *mask,
mailbox_list_callback_t callback, void *context);
- Previous message: [dovecot-cvs] dovecot/src/lib-storage/index/mbox mbox-save.c,1.31,1.32 mbox-storage.c,1.33,1.34 mbox-storage.h,1.13,1.14
- Next message: [dovecot-cvs] dovecot/src/lib-index mail-index.c,1.82,1.83 mail-index.h,1.64,1.65 mail-modifylog.c,1.39,1.40
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
More information about the dovecot-cvs
mailing list