dovecot-2.0: lib-fs: Added fs-sis-queue for delayed SIS implemen...
dovecot at dovecot.org
dovecot at dovecot.org
Sat Oct 2 14:34:02 EEST 2010
details: http://hg.dovecot.org/dovecot-2.0/rev/8292084314be
changeset: 12252:8292084314be
user: Timo Sirainen <tss at iki.fi>
date: Fri Aug 13 18:49:06 2010 +0100
description:
lib-fs: Added fs-sis-queue for delayed SIS implementation.
diffstat:
src/lib-fs/Makefile.am | 3 +
src/lib-fs/fs-api-private.h | 1 +
src/lib-fs/fs-api.c | 3 +-
src/lib-fs/fs-sis-common.c | 58 ++++++++
src/lib-fs/fs-sis-common.h | 14 ++
src/lib-fs/fs-sis-queue.c | 322 ++++++++++++++++++++++++++++++++++++++++++++++
src/lib-fs/fs-sis.c | 90 ++----------
7 files changed, 415 insertions(+), 76 deletions(-)
diffs (truncated from 605 to 300 lines):
diff -r 6d0cd769d7ac -r 8292084314be src/lib-fs/Makefile.am
--- a/src/lib-fs/Makefile.am Fri Aug 13 18:46:30 2010 +0100
+++ b/src/lib-fs/Makefile.am Fri Aug 13 18:49:06 2010 +0100
@@ -7,11 +7,14 @@
fs-api.c \
fs-posix.c \
fs-sis.c \
+ fs-sis-common.c \
+ fs-sis-queue.c \
ostream-cmp.c
headers = \
fs-api.h \
fs-api-private.h \
+ fs-sis-common.h \
ostream-cmp.h
pkginc_libdir=$(pkgincludedir)
diff -r 6d0cd769d7ac -r 8292084314be src/lib-fs/fs-api-private.h
--- a/src/lib-fs/fs-api-private.h Fri Aug 13 18:46:30 2010 +0100
+++ b/src/lib-fs/fs-api-private.h Fri Aug 13 18:49:06 2010 +0100
@@ -54,6 +54,7 @@
extern struct fs fs_class_posix;
extern struct fs fs_class_sis;
+extern struct fs fs_class_sis_queue;
void fs_set_error(struct fs *fs, const char *fmt, ...) ATTR_FORMAT(2, 3);
void fs_set_critical(struct fs *fs, const char *fmt, ...) ATTR_FORMAT(2, 3);
diff -r 6d0cd769d7ac -r 8292084314be src/lib-fs/fs-api.c
--- a/src/lib-fs/fs-api.c Fri Aug 13 18:46:30 2010 +0100
+++ b/src/lib-fs/fs-api.c Fri Aug 13 18:49:06 2010 +0100
@@ -6,7 +6,8 @@
static struct fs *fs_classes[] = {
&fs_class_posix,
- &fs_class_sis
+ &fs_class_sis,
+ &fs_class_sis_queue
};
static struct fs *
diff -r 6d0cd769d7ac -r 8292084314be src/lib-fs/fs-sis-common.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib-fs/fs-sis-common.c Fri Aug 13 18:49:06 2010 +0100
@@ -0,0 +1,58 @@
+/* Copyright (c) 2010 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "fs-sis-common.h"
+
+#include <sys/stat.h>
+
+int fs_sis_path_parse(struct fs *fs, const char *path,
+ const char **dir_r, const char **hash_r)
+{
+ const char *fname, *p;
+
+ fname = strrchr(path, '/');
+ if (fname == NULL) {
+ *dir_r = ".";
+ fname = path;
+ } else {
+ *dir_r = t_strdup_until(path, fname);
+ fname++;
+ }
+
+ /* assume filename begins with "<hash>-" */
+ p = strchr(fname, '-');
+ if (p == NULL) {
+ fs_set_error(fs, "open(%s) failed: "
+ "Filenames must begin with '<hash>-'", path);
+ return -1;
+ }
+ *hash_r = t_strdup_until(fname, p);
+ return 0;
+}
+
+void fs_sis_try_unlink_hash_file(struct fs *fs, struct fs *super,
+ const char *path)
+{
+ struct stat st1, st2;
+ const char *dir, *hash, *hash_path, *hash_dir;
+
+ if (fs_sis_path_parse(fs, path, &dir, &hash) == 0 &&
+ fs_stat(super, path, &st1) == 0 && st1.st_nlink == 2) {
+ /* this may be the last link. if hashes/ file is the same,
+ delete it. */
+ hash_path = t_strdup_printf("%s/"HASH_DIR_NAME"/%s", dir, hash);
+ if (fs_stat(super, hash_path, &st2) == 0 &&
+ st1.st_ino == st2.st_ino &&
+ CMP_DEV_T(st1.st_dev, st2.st_dev)) {
+ if (fs_unlink(super, hash_path) < 0)
+ i_error("%s", fs_last_error(super));
+ else {
+ /* try to rmdir the hashes/ directory */
+ hash_dir = t_strdup_printf("%s/"HASH_DIR_NAME,
+ dir);
+ (void)fs_rmdir(super, hash_dir);
+ }
+ }
+ }
+}
+
diff -r 6d0cd769d7ac -r 8292084314be src/lib-fs/fs-sis-common.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib-fs/fs-sis-common.h Fri Aug 13 18:49:06 2010 +0100
@@ -0,0 +1,14 @@
+#ifndef FS_SIS_COMMON_H
+#define FS_SIS_COMMON_H
+
+#include "fs-api-private.h"
+
+#define HASH_DIR_NAME "hashes"
+
+int fs_sis_path_parse(struct fs *fs, const char *path,
+ const char **dir_r, const char **hash_r);
+void fs_sis_try_unlink_hash_file(struct fs *fs, struct fs *super,
+ const char *path);
+
+#endif
+
diff -r 6d0cd769d7ac -r 8292084314be src/lib-fs/fs-sis-queue.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib-fs/fs-sis-queue.c Fri Aug 13 18:49:06 2010 +0100
@@ -0,0 +1,322 @@
+/* Copyright (c) 2010 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "str.h"
+#include "istream.h"
+#include "fs-sis-common.h"
+
+#define QUEUE_DIR_NAME "queue"
+
+struct sis_queue_fs {
+ struct fs fs;
+ struct fs *super;
+ char *queue_dir;
+};
+
+struct sis_queue_fs_file {
+ struct fs_file file;
+ struct fs_file *super;
+};
+
+static void fs_sis_queue_copy_error(struct sis_queue_fs *fs)
+{
+ fs_set_error(&fs->fs, "%s", fs_last_error(fs->super));
+}
+
+static void fs_sis_queue_file_copy_error(struct sis_queue_fs_file *file)
+{
+ struct sis_queue_fs *fs = (struct sis_queue_fs *)file->file.fs;
+
+ fs_sis_queue_copy_error(fs);
+}
+
+static struct fs *
+fs_sis_queue_init(const char *args, const struct fs_settings *set)
+{
+ struct sis_queue_fs *fs;
+ const char *p, *parent_fs;
+
+ fs = i_new(struct sis_queue_fs, 1);
+ fs->fs = fs_class_sis_queue;
+
+ /* <queue_dir>:<parent fs>[:<args>] */
+
+ p = strchr(args, ':');
+ if (p == NULL || p[1] == '\0')
+ i_fatal("fs-sis-queue: Parent filesystem not given as parameter");
+
+ fs->queue_dir = i_strdup_until(args, p);
+ parent_fs = p + 1;
+
+ p = strchr(parent_fs, ':');
+ if (p == NULL)
+ fs->super = fs_init(parent_fs, "", set);
+ else
+ fs->super = fs_init(t_strdup_until(parent_fs, p), p+1, set);
+ return &fs->fs;
+}
+
+static void fs_sis_queue_deinit(struct fs *_fs)
+{
+ struct sis_queue_fs *fs = (struct sis_queue_fs *)_fs;
+
+ fs_deinit(&fs->super);
+ i_free(fs->queue_dir);
+ i_free(fs);
+}
+
+static int
+fs_sis_queue_open(struct fs *_fs, const char *path, enum fs_open_mode mode,
+ enum fs_open_flags flags, struct fs_file **file_r)
+{
+ struct sis_queue_fs *fs = (struct sis_queue_fs *)_fs;
+ struct sis_queue_fs_file *file;
+ struct fs_file *super;
+
+ if (mode == FS_OPEN_MODE_APPEND) {
+ fs_set_error(_fs, "APPEND mode not supported");
+ return -1;
+ }
+
+ if (fs_open(fs->super, path, mode | flags, &super) < 0) {
+ fs_sis_queue_copy_error(fs);
+ return -1;
+ }
+
+ switch (mode) {
+ case FS_OPEN_MODE_RDONLY:
+ *file_r = super;
+ return 0;
+ case FS_OPEN_MODE_CREATE:
+ case FS_OPEN_MODE_REPLACE:
+ break;
+ case FS_OPEN_MODE_APPEND:
+ i_unreached();
+ }
+
+ file = i_new(struct sis_queue_fs_file, 1);
+ file->file.fs = _fs;
+ file->file.path = i_strdup(fs_file_path(super));
+ file->super = super;
+ *file_r = &file->file;
+ return 0;
+}
+
+static void fs_sis_queue_close(struct fs_file *_file)
+{
+ struct sis_queue_fs_file *file = (struct sis_queue_fs_file *)_file;
+
+ fs_close(&file->super);
+ i_free(file->file.path);
+ i_free(file);
+}
+
+static ssize_t fs_sis_queue_read(struct fs_file *_file, void *buf, size_t size)
+{
+ struct sis_queue_fs_file *file = (struct sis_queue_fs_file *)_file;
+ ssize_t ret;
+
+ if ((ret = fs_read(file->super, buf, size)) < 0)
+ fs_sis_queue_file_copy_error(file);
+ return ret;
+}
+
+static struct istream *
+fs_sis_queue_read_stream(struct fs_file *_file, size_t max_buffer_size)
+{
+ struct sis_queue_fs_file *file = (struct sis_queue_fs_file *)_file;
+
+ return fs_read_stream(file->super, max_buffer_size);
+}
+
+static void fs_sis_queue_add(struct sis_queue_fs_file *file)
+{
+ struct sis_queue_fs *fs = (struct sis_queue_fs *)file->file.fs;
+ struct fs_file *queue_file;
+ const char *fname, *path, *queue_path;
+
+ path = fs_file_path(&file->file);
+ fname = strrchr(path, '/');
+ if (fname != NULL)
+ fname++;
+ else
+ fname = path;
+
+ queue_path = t_strdup_printf("%s/%s", fs->queue_dir, fname);
+ if (fs_open(fs->super, queue_path,
+ FS_OPEN_MODE_CREATE | FS_OPEN_FLAG_MKDIR,
+ &queue_file) < 0) {
+ i_error("fs-sis-queue: %s", fs_last_error(fs->super));
+ return;
+ }
+ if (fs_write(queue_file, "", 0) < 0 && errno != EEXIST)
+ i_error("fs-sis-queue: %s", fs_last_error(fs->super));
+ fs_close(&queue_file);
+}
+
+static int fs_sis_queue_write(struct fs_file *_file, const void *data, size_t size)
+{
+ struct sis_queue_fs_file *file = (struct sis_queue_fs_file *)_file;
+
+ if (fs_write(file->super, data, size) < 0) {
+ fs_sis_queue_file_copy_error(file);
+ return -1;
+ }
+ T_BEGIN {
+ fs_sis_queue_add(file);
+ } T_END;
+ return 0;
+}
+
+static void fs_sis_queue_write_stream(struct fs_file *_file)
+{
+ struct sis_queue_fs_file *file = (struct sis_queue_fs_file *)_file;
+
More information about the dovecot-cvs
mailing list