dovecot: Initial commit for dbox redesign/rewrite. Currently sup...
dovecot at dovecot.org
dovecot at dovecot.org
Sat Sep 1 03:04:07 EEST 2007
details: http://hg.dovecot.org/dovecot/rev/7b71ba1250e3
changeset: 6340:7b71ba1250e3
user: Timo Sirainen <tss at iki.fi>
date: Sat Sep 01 03:04:02 2007 +0300
description:
Initial commit for dbox redesign/rewrite. Currently supports only one
message per file mode.
diffstat:
21 files changed, 3761 insertions(+), 4194 deletions(-)
src/lib-storage/index/dbox/Makefile.am | 15
src/lib-storage/index/dbox/dbox-file.c | 1282 +++++++++++++++++----
src/lib-storage/index/dbox/dbox-file.h | 232 +++
src/lib-storage/index/dbox/dbox-format.h | 67 -
src/lib-storage/index/dbox/dbox-index.c | 890 +++++++++++++++
src/lib-storage/index/dbox/dbox-index.h | 130 ++
src/lib-storage/index/dbox/dbox-keywords.c | 214 ---
src/lib-storage/index/dbox/dbox-keywords.h | 17
src/lib-storage/index/dbox/dbox-mail.c | 411 +++----
src/lib-storage/index/dbox/dbox-save.c | 623 +++++-----
src/lib-storage/index/dbox/dbox-storage.c | 386 ++----
src/lib-storage/index/dbox/dbox-storage.h | 87 -
src/lib-storage/index/dbox/dbox-sync-expunge.c | 503 --------
src/lib-storage/index/dbox/dbox-sync-file.c | 291 ++++
src/lib-storage/index/dbox/dbox-sync-full.c | 237 ----
src/lib-storage/index/dbox/dbox-sync-rebuild.c | 199 +++
src/lib-storage/index/dbox/dbox-sync.c | 825 +++++---------
src/lib-storage/index/dbox/dbox-sync.h | 61 -
src/lib-storage/index/dbox/dbox-transaction.c | 11
src/lib-storage/index/dbox/dbox-uidlist.c | 1402 ------------------------
src/lib-storage/index/dbox/dbox-uidlist.h | 72 -
diffs (truncated from 8577 to 300 lines):
diff -r 301d0f8e4f91 -r 7b71ba1250e3 src/lib-storage/index/dbox/Makefile.am
--- a/src/lib-storage/index/dbox/Makefile.am Sat Sep 01 01:36:10 2007 +0300
+++ b/src/lib-storage/index/dbox/Makefile.am Sat Sep 01 03:04:02 2007 +0300
@@ -10,23 +10,20 @@ AM_CPPFLAGS = \
libstorage_dbox_a_SOURCES = \
dbox-file.c \
- dbox-keywords.c \
+ dbox-index.c \
dbox-mail.c \
dbox-save.c \
dbox-sync.c \
- dbox-sync-expunge.c \
- dbox-sync-full.c \
+ dbox-sync-file.c \
+ dbox-sync-rebuild.c \
dbox-storage.c \
- dbox-transaction.c \
- dbox-uidlist.c
+ dbox-transaction.c
headers = \
dbox-file.h \
- dbox-format.h \
- dbox-keywords.h \
+ dbox-index.h \
dbox-storage.h \
- dbox-sync.h \
- dbox-uidlist.h
+ dbox-sync.h
if INSTALL_HEADERS
pkginc_libdir=$(pkgincludedir)/src/lib-storage/index/dbox
diff -r 301d0f8e4f91 -r 7b71ba1250e3 src/lib-storage/index/dbox/dbox-file.c
--- a/src/lib-storage/index/dbox/dbox-file.c Sat Sep 01 01:36:10 2007 +0300
+++ b/src/lib-storage/index/dbox/dbox-file.c Sat Sep 01 03:04:02 2007 +0300
@@ -1,311 +1,1053 @@
-/* Copyright (C) 2005-2006 Timo Sirainen */
+/* Copyright (C) 2007 Timo Sirainen */
#include "lib.h"
+#include "ioloop.h"
#include "array.h"
-#include "bsearch-insert-pos.h"
#include "hex-dec.h"
+#include "hostpid.h"
#include "istream.h"
#include "ostream.h"
-#include "read-full.h"
+#include "write-full.h"
+#include "str.h"
#include "dbox-storage.h"
+#include "dbox-index.h"
#include "dbox-file.h"
-int dbox_file_lookup_offset(struct dbox_mailbox *mbox,
- struct mail_index_view *view, uint32_t seq,
- uint32_t *file_seq_r, uoff_t *offset_r)
-{
- const void *data1, *data2;
- bool expunged;
-
- mail_index_lookup_ext(view, seq, mbox->dbox_file_ext_idx,
- &data1, &expunged);
- if (expunged)
- return 0;
- mail_index_lookup_ext(view, seq, mbox->dbox_offset_ext_idx,
- &data2, &expunged);
- if (expunged)
- return 0;
-
- if (data1 == NULL || data2 == NULL) {
- *file_seq_r = 0;
- return 1;
- }
-
- /* success */
- *file_seq_r = *((const uint32_t *)data1);
- *offset_r = *((const uint64_t *)data2);
- return 1;
-}
-
-void dbox_file_close(struct dbox_file *file)
-{
- if (array_is_created(&file->file_idx_keywords)) {
- array_free(&file->idx_file_keywords);
- array_free(&file->file_idx_keywords);
- }
-
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+enum mail_flags dbox_mail_flags_map[DBOX_METADATA_FLAGS_COUNT] = {
+ MAIL_ANSWERED,
+ MAIL_FLAGGED,
+ MAIL_DELETED,
+ MAIL_SEEN,
+ MAIL_DRAFT
+};
+
+char dbox_mail_flag_chars[DBOX_METADATA_FLAGS_COUNT] = {
+ 'A', 'F', 'D', 'S', 'T'
+};
+
+static int dbox_file_metadata_skip_header(struct dbox_file *file);
+
+static char *dbox_generate_tmp_filename(const char *path)
+{
+ static unsigned int create_count = 0;
+
+ return i_strdup_printf("%s/temp.%s.P%sQ%uM%s.%s",
+ path, dec2str(ioloop_timeval.tv_sec), my_pid,
+ create_count++,
+ dec2str(ioloop_timeval.tv_usec), my_hostname);
+}
+
+void dbox_file_set_syscall_error(struct dbox_file *file, const char *function)
+{
+ mail_storage_set_critical(file->mbox->ibox.box.storage,
+ "%s(%s) failed: %m", function, file->path);
+}
+
+static void
+dbox_file_set_corrupted(struct dbox_file *file, const char *reason)
+{
+ mail_storage_set_critical(file->mbox->ibox.box.storage,
+ "%s corrupted: %s", file->path, reason);
+}
+
+
+static struct dbox_file *
+dbox_find_and_move_open_file(struct dbox_mailbox *mbox, unsigned int file_id)
+{
+ struct dbox_file *const *files, *file;
+ unsigned int i, count;
+
+ files = array_get(&mbox->open_files, &count);
+ for (i = 0; i < count; i++) {
+ if (files[i]->file_id == file_id) {
+ /* move to last in the array */
+ file = files[i];
+ array_delete(&mbox->open_files, i, 1);
+ array_append(&mbox->open_files, &file, 1);
+ return file;
+ }
+ }
+ return NULL;
+}
+
+static void dbox_file_free(struct dbox_file *file)
+{
+ i_assert(file->refcount == 0);
+
+ if (file->metadata_pool != NULL)
+ pool_unref(file->metadata_pool);
if (file->input != NULL)
- i_stream_destroy(&file->input);
+ i_stream_unref(&file->input);
+ if (file->output != NULL)
+ o_stream_unref(&file->output);
if (file->fd != -1) {
if (close(file->fd) < 0)
- i_error("close(dbox) failed: %m");
- }
- i_free(file->seeked_keywords);
+ dbox_file_set_syscall_error(file, "close");
+ file->fd = -1;
+ }
i_free(file->path);
i_free(file);
}
-static int
-dbox_file_read_mail_header(struct dbox_mailbox *mbox, struct dbox_file *file,
- uoff_t offset)
-{
- const struct dbox_mail_header *hdr;
+void dbox_files_free(struct dbox_mailbox *mbox)
+{
+ struct dbox_file *const *files;
+ unsigned int i, count;
+
+ files = array_get(&mbox->open_files, &count);
+ for (i = 0; i < count; i++)
+ dbox_file_free(files[i]);
+ array_clear(&mbox->open_files);
+}
+
+static void
+dbox_close_open_files(struct dbox_mailbox *mbox, unsigned int close_count)
+{
+ struct dbox_file *const *files;
+ unsigned int i, count;
+
+ files = array_get(&mbox->open_files, &count);
+ for (i = 0; i < count;) {
+ if (files[i]->refcount == 0) {
+ dbox_file_free(files[i]);
+ array_delete(&mbox->open_files, i, 1);
+
+ if (--close_count == 0)
+ break;
+
+ files = array_get(&mbox->open_files, &count);
+ } else {
+ i++;
+ }
+ }
+}
+
+static char *
+dbox_file_id_get_path(struct dbox_mailbox *mbox, unsigned int file_id)
+{
+ if ((file_id & DBOX_FILE_ID_FLAG_UID) != 0) {
+ file_id &= ~DBOX_FILE_ID_FLAG_UID;
+ return i_strdup_printf("%s/"DBOX_MAIL_FILE_UID_FORMAT,
+ mbox->path, file_id);
+ } else {
+ return i_strdup_printf("%s/"DBOX_MAIL_FILE_MULTI_FORMAT,
+ mbox->path, file_id);
+ }
+}
+
+struct dbox_file *
+dbox_file_init(struct dbox_mailbox *mbox, unsigned int file_id)
+{
+ struct dbox_file *file;
+ unsigned int count;
+
+ file = file_id == 0 ? NULL :
+ dbox_find_and_move_open_file(mbox, file_id);
+ if (file != NULL) {
+ file->refcount++;
+ return file;
+ }
+
+ count = array_count(&mbox->open_files);
+ if (count > mbox->max_open_files)
+ dbox_close_open_files(mbox, count - mbox->max_open_files);
+
+ file = i_new(struct dbox_file, 1);
+ file->refcount = 1;
+ file->mbox = mbox;
+ if (file_id != 0) {
+ file->file_id = file_id;
+ file->path = dbox_file_id_get_path(mbox, file_id);
+ } else {
+ file->path = dbox_generate_tmp_filename(mbox->path);
+ }
+ file->fd = -1;
+
+ if (file_id != 0)
+ array_append(&file->mbox->open_files, &file, 1);
+ return file;
+}
+
+int dbox_file_assign_id(struct dbox_file *file, unsigned int file_id)
+{
+ char *new_path;
+
+ i_assert(file->file_id == 0);
+ i_assert(file_id != 0);
+
+ new_path = dbox_file_id_get_path(file->mbox, file_id);
+ if (rename(file->path, new_path) < 0) {
+ mail_storage_set_critical(file->mbox->ibox.box.storage,
+ "rename(%s, %s) failed: %m", file->path, new_path);
+ i_free(new_path);
+ return -1;
+ }
+
+ i_free(file->path);
+ file->path = new_path;
+
+ file->file_id = file_id;
+ array_append(&file->mbox->open_files, &file, 1);
+ return 0;
+}
+
+void dbox_file_unref(struct dbox_file **_file)
+{
+ struct dbox_file *file = *_file;
+ struct dbox_file *const *files;
+ unsigned int i, count;
+
+ *_file = NULL;
+
+ i_assert(file->refcount > 0);
+ if (--file->refcount > 0)
+ return;
+
+ /* don't cache metadata seeks while file isn't being referenced */
+ file->metadata_read_offset = 0;
+
+ if (file->file_id != 0) {
+ files = array_get(&file->mbox->open_files, &count);
+ if (!file->deleted && count <= file->mbox->max_open_files) {
+ /* we can leave this file open for now */
More information about the dovecot-cvs
mailing list