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