[dovecot-cvs] dovecot/src/lib-index mail-cache-compress.c, 1.33, 1.34 mail-cache.c, 1.65, 1.66 mail-index-lock.c, 1.39, 1.40 mail-index-private.h, 1.53, 1.54 mail-index-sync.c, 1.53, 1.54 mail-index.c, 1.195, 1.196 mail-transaction-log-append.c, 1.6, 1.7 mail-transaction-log-private.h, 1.9, 1.10 mail-transaction-log.c, 1.91, 1.92

cras at dovecot.org cras at dovecot.org
Tue Mar 29 15:18:52 EEST 2005


Update of /var/lib/cvs/dovecot/src/lib-index
In directory talvi:/tmp/cvs-serv2413

Modified Files:
	mail-cache-compress.c mail-cache.c mail-index-lock.c 
	mail-index-private.h mail-index-sync.c mail-index.c 
	mail-transaction-log-append.c mail-transaction-log-private.h 
	mail-transaction-log.c 
Log Message:
In-memory indexes work again. Just pass dir as NULL to mail_index_alloc().



Index: mail-cache-compress.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-index/mail-cache-compress.c,v
retrieving revision 1.33
retrieving revision 1.34
diff -u -d -r1.33 -r1.34
--- mail-cache-compress.c	16 Jan 2005 19:18:24 -0000	1.33
+++ mail-cache-compress.c	29 Mar 2005 12:18:49 -0000	1.34
@@ -300,6 +300,9 @@
 {
 	int ret;
 
+	if (MAIL_INDEX_IS_IN_MEMORY(cache->index))
+		return 0;
+
 	if (cache->index->lock_method == MAIL_INDEX_LOCK_DOTLOCK) {
 		/* we're using dotlocking, cache file creation itself creates
 		   the dotlock file we need. */

Index: mail-cache.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-index/mail-cache.c,v
retrieving revision 1.65
retrieving revision 1.66
diff -u -d -r1.65 -r1.66
--- mail-cache.c	24 Mar 2005 22:12:12 -0000	1.65
+++ mail-cache.c	29 Mar 2005 12:18:49 -0000	1.66
@@ -69,8 +69,9 @@
 	struct mail_index_view *view;
 	const struct mail_index_ext *ext;
 
-	if (MAIL_CACHE_IS_UNUSABLE(cache) && cache->need_compress) {
-		/* unusable, we're just waiting for compression */
+	if (MAIL_CACHE_IS_UNUSABLE(cache) &&
+	    (cache->need_compress || MAIL_INDEX_IS_IN_MEMORY(cache->index))) {
+		/* reopening does no good */
 		return 0;
 	}
 
@@ -192,8 +193,10 @@
 			mail_cache_set_syscall_error(cache, "munmap()");
 	} else {
 		if (cache->fd == -1) {
-			/* unusable, waiting for compression */
-			i_assert(cache->need_compress);
+			/* unusable, waiting for compression or
+			   index is in memory */
+			i_assert(cache->need_compress ||
+				 MAIL_INDEX_IS_IN_MEMORY(cache->index));
 			return -1;
 		}
 	}
@@ -222,6 +225,9 @@
 
 static int mail_cache_open_and_verify(struct mail_cache *cache)
 {
+	if (MAIL_INDEX_IS_IN_MEMORY(cache->index))
+		return 0;
+
 	cache->fd = open(cache->filepath, O_RDWR);
 	if (cache->fd == -1) {
 		if (errno == ENOENT) {
@@ -261,8 +267,10 @@
 	cache->dotlock_settings.immediate_stale_timeout =
 		MAIL_CACHE_LOCK_IMMEDIATE_TIMEOUT;
 
-	if (index->mmap_disable || index->mmap_no_write)
-		cache->file_cache = file_cache_new(-1);
+	if (!MAIL_INDEX_IS_IN_MEMORY(index)) {
+		if (index->mmap_disable || index->mmap_no_write)
+			cache->file_cache = file_cache_new(-1);
+	}
 
 	cache->ext_id =
 		mail_index_ext_register(index, "cache", 0,

Index: mail-index-lock.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-index/mail-index-lock.c,v
retrieving revision 1.39
retrieving revision 1.40
diff -u -d -r1.39 -r1.40
--- mail-index-lock.c	5 Dec 2004 04:10:43 -0000	1.39
+++ mail-index-lock.c	29 Mar 2005 12:18:49 -0000	1.40
@@ -41,6 +41,9 @@
 	if (timeout_secs != 0)
 		alarm(MAIL_INDEX_LOCK_WAIT_TIME);
 
+	if (MAIL_INDEX_IS_IN_MEMORY(index))
+		return 1;
+
 	switch (index->lock_method) {
 	case MAIL_INDEX_LOCK_FCNTL: {
 #ifndef HAVE_FCNTL
@@ -233,6 +236,8 @@
 	const char *path;
 	int ret, fd;
 
+	i_assert(!MAIL_INDEX_IS_IN_MEMORY(index));
+
 	fd = mail_index_create_tmp_file(index, &path);
 	if (fd == -1)
 		return -1;
@@ -367,11 +372,14 @@
 			i_free(index->copy_lock_path);
 			index->copy_lock_path = NULL;
 		}
-		fd = mail_index_copy(index);
-		if (fd == -1)
-			mail_index_set_inconsistent(index);
-		else
-			(void)close(fd);
+
+		if (!MAIL_INDEX_IS_IN_MEMORY(index)) {
+			fd = mail_index_copy(index);
+			if (fd == -1)
+				mail_index_set_inconsistent(index);
+			else
+				(void)close(fd);
+		}
 	}
 
 	if (index->shared_lock_count > 0 &&

Index: mail-index-private.h
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-index/mail-index-private.h,v
retrieving revision 1.53
retrieving revision 1.54
diff -u -d -r1.53 -r1.54
--- mail-index-private.h	27 Mar 2005 12:22:21 -0000	1.53
+++ mail-index-private.h	29 Mar 2005 12:18:49 -0000	1.54
@@ -20,6 +20,9 @@
    rewritten by another computer than us). */
 #define MAIL_INDEX_ESTALE_RETRY_COUNT 10
 
+#define MAIL_INDEX_IS_IN_MEMORY(index) \
+	((index)->dir == NULL)
+
 #define MAIL_INDEX_MAP_IS_IN_MEMORY(map) \
 	((map) != NULL && (map)->buffer != NULL)
 

Index: mail-index-sync.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-index/mail-index-sync.c,v
retrieving revision 1.53
retrieving revision 1.54
diff -u -d -r1.53 -r1.54
--- mail-index-sync.c	27 Mar 2005 12:22:21 -0000	1.53
+++ mail-index-sync.c	29 Mar 2005 12:18:49 -0000	1.54
@@ -630,7 +630,6 @@
 	return &ctx->index->keywords;
 }
 
-
 void mail_index_sync_flags_apply(const struct mail_index_sync_rec *sync_rec,
 				 uint8_t *flags)
 {

Index: mail-index.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-index/mail-index.c,v
retrieving revision 1.195
retrieving revision 1.196
diff -u -d -r1.195 -r1.196
--- mail-index.c	27 Mar 2005 12:22:21 -0000	1.195
+++ mail-index.c	29 Mar 2005 12:18:49 -0000	1.196
@@ -16,6 +16,8 @@
 #include <sys/stat.h>
 
 static int mail_index_try_open_only(struct mail_index *index);
+static void mail_index_create_in_memory(struct mail_index *index,
+					const struct mail_index_header *hdr);
 
 struct mail_index *mail_index_alloc(const char *dir, const char *prefix)
 {
@@ -886,6 +888,12 @@
 	i_assert(index->map == NULL || index->map->refcount > 0);
 	i_assert(index->lock_type != F_UNLCK);
 
+	if (MAIL_INDEX_IS_IN_MEMORY(index)) {
+		if (index->map == NULL)
+			mail_index_create_in_memory(index, NULL);
+		return 1;
+	}
+
 	index->mapping = TRUE;
 
 	if (!force && index->map != NULL) {
@@ -1052,6 +1060,8 @@
 {
 	int i;
 
+	i_assert(!MAIL_INDEX_IS_IN_MEMORY(index));
+
 	for (i = 0; i < 3; i++) {
 		index->fd = open(index->filepath, O_RDWR);
 		if (index->fd == -1 && errno == EACCES) {
@@ -1086,6 +1096,9 @@
 	if (lock_id_r != NULL)
 		*lock_id_r = 0;
 
+	if (MAIL_INDEX_IS_IN_MEMORY(index))
+		return 0;
+
 	ret = mail_index_try_open_only(index);
 	if (ret <= 0)
 		return ret;
@@ -1126,9 +1139,12 @@
 			return mail_index_set_syscall_error(index, "msync()");
 		index->map->hdr = *hdr;
 	} else {
-		if (pwrite_full(index->fd, hdr, hdr_size, 0) < 0) {
-			mail_index_set_syscall_error(index, "pwrite_full()");
-			return -1;
+		if (!MAIL_INDEX_IS_IN_MEMORY(index)) {
+			if (pwrite_full(index->fd, hdr, hdr_size, 0) < 0) {
+				mail_index_set_syscall_error(index,
+							     "pwrite_full()");
+				return -1;
+			}
 		}
 
 		index->map->hdr = *hdr;
@@ -1144,6 +1160,8 @@
 	const char *path;
 	int fd;
 
+	i_assert(!MAIL_INDEX_IS_IN_MEMORY(index));
+
 	path = *path_r = t_strconcat(index->filepath, ".tmp", NULL);
 	old_mask = umask(0);
 	fd = open(path, O_RDWR|O_CREAT|O_TRUNC, index->mode);
@@ -1167,6 +1185,7 @@
 	uoff_t offset;
 	int ret;
 
+	i_assert(!MAIL_INDEX_IS_IN_MEMORY(index));
 	i_assert(index->lock_type == F_UNLCK);
 
 	/* log file lock protects index creation */
@@ -1243,6 +1262,27 @@
 	hdr->next_uid = 1;
 }
 
+static void mail_index_create_in_memory(struct mail_index *index,
+					const struct mail_index_header *hdr)
+{
+        struct mail_index_header tmp_hdr;
+	struct mail_index_map tmp_map;
+
+	if (hdr == NULL) {
+		mail_index_header_init(&tmp_hdr);
+		hdr = &tmp_hdr;
+	}
+
+	memset(&tmp_map, 0, sizeof(tmp_map));
+	tmp_map.hdr = *hdr;
+	tmp_map.hdr_base = hdr;
+
+	/* a bit kludgy way to do this, but it initializes everything
+	   nicely and correctly */
+	index->map = mail_index_map_clone(&tmp_map, hdr->record_size);
+	index->hdr = &index->map->hdr;
+}
+
 /* returns -1 = error, 0 = won't create, 1 = ok */
 static int mail_index_open_files(struct mail_index *index,
 				 enum mail_index_open_flags flags)
@@ -1274,8 +1314,12 @@
 			mail_index_unlock(index, lock_id);
 			lock_id = 0;
 		}
-		if (mail_index_create(index, &hdr) < 0)
-			return -1;
+		if (!MAIL_INDEX_IS_IN_MEMORY(index)) {
+			if (mail_index_create(index, &hdr) < 0)
+				return -1;
+		} else {
+			mail_index_create_in_memory(index, &hdr);
+		}
 		created = TRUE;
 	}
 
@@ -1307,7 +1351,9 @@
 		}
 	}
 
-	index->filepath = i_strconcat(index->dir, "/", index->prefix, NULL);
+	index->filepath = MAIL_INDEX_IS_IN_MEMORY(index) ?
+		i_strdup("(in-memory index)") :
+		i_strconcat(index->dir, "/", index->prefix, NULL);
 
 	do {
 		index->shared_lock_count = 0;
@@ -1397,6 +1443,8 @@
 	unsigned int old_shared_locks, old_lock_id, lock_id = 0;
 	int ret, old_fd, old_lock_type;
 
+	i_assert(!MAIL_INDEX_IS_IN_MEMORY(index));
+
 	old_map = index->map;
 	old_fd = index->fd;
 	old_map->refcount++;
@@ -1463,6 +1511,9 @@
 {
 	struct stat st1, st2;
 
+	if (MAIL_INDEX_IS_IN_MEMORY(index))
+		return 0;
+
 	if (fstat(index->fd, &st1) < 0)
 		return mail_index_set_syscall_error(index, "fstat()");
 	if (stat(index->filepath, &st2) < 0) {
@@ -1490,6 +1541,9 @@
 	unsigned int lock_id;
 	int ret;
 
+	if (MAIL_INDEX_IS_IN_MEMORY(index))
+		return 0;
+
 	if (index->excl_lock_count > 0) {
 		/* we have index exclusively locked, nothing could
 		   have changed. */
@@ -1552,7 +1606,7 @@
 	hdr = *index->hdr;
 	hdr.flags |= MAIL_INDEX_HDR_FLAG_CORRUPTED;
 	if (mail_index_write_base_header(index, &hdr) == 0) {
-		if (fsync(index->fd) < 0)
+		if (!MAIL_INDEX_IS_IN_MEMORY(index) && fsync(index->fd) < 0)
 			mail_index_set_syscall_error(index, "fsync()");
 	}
 }

Index: mail-transaction-log-append.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-index/mail-transaction-log-append.c,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- mail-transaction-log-append.c	18 Mar 2005 17:34:11 -0000	1.6
+++ mail-transaction-log-append.c	29 Mar 2005 12:18:49 -0000	1.7
@@ -41,29 +41,41 @@
 	if (external)
 		hdr.type |= MAIL_TRANSACTION_EXTERNAL;
 
-	hdr_size =
-		mail_index_uint32_to_offset(sizeof(hdr) + size + hdr_data_size);
-	if (file->first_append_size == 0) {
-		/* size will be written later once everything is in disk */
-		file->first_append_size = hdr_size;
-	} else {
-		hdr.size = hdr_size;
-	}
+	hdr_size = mail_index_uint32_to_offset(sizeof(hdr) + size +
+					       hdr_data_size);
+	if (!MAIL_TRANSACTION_LOG_FILE_IN_MEMORY(file)) {
+		if (file->first_append_size == 0) {
+			/* size will be written later once everything is in
+			   disk */
+			file->first_append_size = hdr_size;
+		} else {
+			hdr.size = hdr_size;
+		}
+		if (pwrite_full(file->fd, &hdr, sizeof(hdr),
+				file->sync_offset) < 0)
+			return -1;
+		file->sync_offset += sizeof(hdr);
 
-	if (pwrite_full(file->fd, &hdr, sizeof(hdr), file->sync_offset) < 0)
-		return -1;
-	file->sync_offset += sizeof(hdr);
+		if (hdr_data_size > 0) {
+			if (pwrite_full(file->fd, hdr_data, hdr_data_size,
+					file->sync_offset) < 0)
+				return -1;
+			file->sync_offset += hdr_data_size;
+		}
 
-	if (hdr_data_size > 0) {
-		if (pwrite_full(file->fd, hdr_data, hdr_data_size,
-				file->sync_offset) < 0)
+		if (pwrite_full(file->fd, data, size, file->sync_offset) < 0)
 			return -1;
-		file->sync_offset += hdr_data_size;
-	}
+		file->sync_offset += size;
+	} else {
+		hdr.size = hdr_size;
 
-	if (pwrite_full(file->fd, data, size, file->sync_offset) < 0)
-		return -1;
-	file->sync_offset += size;
+		i_assert(file->buffer_offset + file->buffer->used ==
+			 file->sync_offset);
+		buffer_append(file->buffer, &hdr, sizeof(hdr));
+		buffer_append(file->buffer, hdr_data, hdr_data_size);
+		buffer_append(file->buffer, data, size);
+		file->sync_offset = file->buffer_offset + file->buffer->used;
+	}
 	return 0;
 }
 
@@ -421,22 +433,24 @@
 						       append_offset);
 	}
 
-	if (ret == 0 && fsync(file->fd) < 0) {
-		/* we don't know how much of it got written,
-		   it may be corrupted now.. */
-		mail_index_file_set_syscall_error(log->index, file->filepath,
-						  "fsync()");
-		ret = -1;
-	}
-
-	if (ret == 0 && file->first_append_size != 0) {
-		/* synced - rewrite first record's header */
-		ret = pwrite_full(file->fd, &file->first_append_size,
-				  sizeof(uint32_t), append_offset);
-		if (ret < 0) {
+	if (!MAIL_TRANSACTION_LOG_FILE_IN_MEMORY(file)) {
+		if (ret == 0 && fsync(file->fd) < 0) {
+			/* we don't know how much of it got written,
+			   it may be corrupted now.. */
 			mail_index_file_set_syscall_error(log->index,
 							  file->filepath,
-							  "pwrite()");
+							  "fsync()");
+			ret = -1;
+		}
+
+		if (ret == 0 && file->first_append_size != 0) {
+			/* synced - rewrite first record's header */
+			ret = pwrite_full(file->fd, &file->first_append_size,
+					  sizeof(uint32_t), append_offset);
+			if (ret < 0) {
+				mail_index_file_set_syscall_error(log->index,
+					file->filepath, "pwrite()");
+			}
 		}
 	}
 

Index: mail-transaction-log-private.h
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-index/mail-transaction-log-private.h,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -d -r1.9 -r1.10
--- mail-transaction-log-private.h	5 Mar 2005 19:23:28 -0000	1.9
+++ mail-transaction-log-private.h	29 Mar 2005 12:18:49 -0000	1.10
@@ -7,6 +7,8 @@
 #define MAIL_TRANSACTION_LOG_ROTATE_SIZE (1024*128)
 #define MAIL_TRANSACTION_LOG_ROTATE_TIME (60*5)
 
+#define MAIL_TRANSACTION_LOG_FILE_IN_MEMORY(file) ((file)->fd == -1)
+
 struct mail_transaction_log_file {
 	struct mail_transaction_log *log;
         struct mail_transaction_log_file *next;

Index: mail-transaction-log.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-index/mail-transaction-log.c,v
retrieving revision 1.91
retrieving revision 1.92
diff -u -d -r1.91 -r1.92
--- mail-transaction-log.c	24 Mar 2005 18:05:36 -0000	1.91
+++ mail-transaction-log.c	29 Mar 2005 12:18:49 -0000	1.92
@@ -37,10 +37,12 @@
 	va_list va;
 
 	file->hdr.indexid = 0;
-	if (pwrite_full(file->fd, &file->hdr.indexid,
-			sizeof(file->hdr.indexid), 0) < 0) {
-		mail_index_file_set_syscall_error(file->log->index,
-						  file->filepath, "pwrite()");
+	if (!MAIL_TRANSACTION_LOG_FILE_IN_MEMORY(file)) {
+		if (pwrite_full(file->fd, &file->hdr.indexid,
+				sizeof(file->hdr.indexid), 0) < 0) {
+			mail_index_file_set_syscall_error(file->log->index,
+				file->filepath, "pwrite()");
+		}
 	}
 
 	va_start(va, fmt);
@@ -122,6 +124,11 @@
 	if (file->locked)
 		return 0;
 
+	if (MAIL_TRANSACTION_LOG_FILE_IN_MEMORY(file)) {
+		file->locked = TRUE;
+		return 0;
+	}
+
 	if (file->log->index->lock_method == MAIL_INDEX_LOCK_DOTLOCK)
 		return mail_transaction_log_file_dotlock(file);
 
@@ -155,6 +162,9 @@
 
 	file->locked = FALSE;
 
+	if (MAIL_TRANSACTION_LOG_FILE_IN_MEMORY(file))
+		return;
+
 	if (file->log->index->lock_method == MAIL_INDEX_LOCK_DOTLOCK) {
 		mail_transaction_log_file_undotlock(file);
 		return;
@@ -278,9 +288,12 @@
 		}
 	}
 
-	if (close(file->fd) < 0) {
-		mail_index_file_set_syscall_error(file->log->index,
-						  file->filepath, "close()");
+	if (file->fd != -1) {
+		if (close(file->fd) < 0) {
+			mail_index_file_set_syscall_error(file->log->index,
+							  file->filepath,
+							  "close()");
+		}
 	}
 
 	i_free(file->filepath);
@@ -293,6 +306,8 @@
         struct mail_transaction_log_file *f;
 	int ret;
 
+	i_assert(!MAIL_INDEX_IS_IN_MEMORY(file->log->index));
+
 	ret = pread_full(file->fd, &file->hdr, sizeof(file->hdr), 0);
 	if (ret < 0) {
 		// FIXME: handle ESTALE
@@ -362,6 +377,43 @@
 }
 
 static int
+mail_transaction_log_init_hdr(struct mail_transaction_log *log,
+			      struct mail_transaction_log_header *hdr)
+{
+	struct mail_index *index = log->index;
+	unsigned int lock_id;
+
+	memset(hdr, 0, sizeof(*hdr));
+	hdr->major_version = MAIL_TRANSACTION_LOG_MAJOR_VERSION;
+	hdr->minor_version = MAIL_TRANSACTION_LOG_MINOR_VERSION;
+	hdr->hdr_size = sizeof(struct mail_transaction_log_header);
+	hdr->indexid = log->index->indexid;
+	hdr->create_stamp = ioloop_time;
+
+	if (index->fd != -1) {
+		/* not creating index - make sure we have latest header */
+		if (mail_index_lock_shared(index, TRUE, &lock_id) < 0)
+			return -1;
+		if (mail_index_map(index, FALSE) <= 0) {
+			mail_index_unlock(index, lock_id);
+			return -1;
+		}
+	}
+	hdr->prev_file_seq = index->hdr->log_file_seq;
+	hdr->prev_file_offset = index->hdr->log_file_int_offset;
+	hdr->file_seq = index->hdr->log_file_seq+1;
+
+	if (index->fd != -1)
+		mail_index_unlock(index, lock_id);
+
+	if (log->head != NULL && hdr->file_seq <= log->head->hdr.file_seq) {
+		/* make sure the sequence grows */
+		hdr->file_seq = log->head->hdr.file_seq+1;
+	}
+	return 0;
+}
+
+static int
 mail_transaction_log_file_create2(struct mail_transaction_log *log,
 				  const char *path, int fd,
 				  struct dotlock **dotlock,
@@ -370,7 +422,6 @@
 	struct mail_index *index = log->index;
 	struct mail_transaction_log_header hdr;
 	struct stat st;
-	unsigned int lock_id;
 	int fd2, ret;
 
 	/* log creation is locked now - see if someone already created it */
@@ -397,33 +448,8 @@
 		return -1;
 	}
 
-	memset(&hdr, 0, sizeof(hdr));
-	hdr.major_version = MAIL_TRANSACTION_LOG_MAJOR_VERSION;
-	hdr.minor_version = MAIL_TRANSACTION_LOG_MINOR_VERSION;
-	hdr.hdr_size = sizeof(struct mail_transaction_log_header);
-	hdr.indexid = index->indexid;
-	hdr.create_stamp = ioloop_time;
-
-	if (index->fd != -1) {
-		if (mail_index_lock_shared(index, TRUE, &lock_id) < 0)
-			return -1;
-		if (mail_index_map(index, FALSE) <= 0) {
-			mail_index_unlock(index, lock_id);
-			return -1;
-		}
-
-		hdr.prev_file_seq = index->hdr->log_file_seq;
-		hdr.prev_file_offset = index->hdr->log_file_int_offset;
-	}
-	hdr.file_seq = index->hdr->log_file_seq+1;
-
-	if (index->fd != -1)
-		mail_index_unlock(index, lock_id);
-
-	if (log->head != NULL && hdr.file_seq <= log->head->hdr.file_seq) {
-		/* make sure the sequence grows */
-		hdr.file_seq = log->head->hdr.file_seq+1;
-	}
+	if (mail_transaction_log_init_hdr(log, &hdr) < 0)
+		return -1;
 
 	if (write_full(fd, &hdr, sizeof(hdr)) < 0) {
 		mail_index_file_set_syscall_error(index, path,
@@ -448,6 +474,8 @@
         mode_t old_mask;
 	int fd, fd2;
 
+	i_assert(!MAIL_INDEX_IS_IN_MEMORY(log->index));
+
 	/* With dotlocking we might already have path.lock created, so this
 	   filename has to be different. */
 	old_mask = umask(log->index->mode ^ 0666);
@@ -476,15 +504,39 @@
 	return fd2;
 }
 
+static void
+mail_transaction_log_file_alloc_finish(struct mail_transaction_log_file *file)
+{
+	struct mail_transaction_log *log = file->log;
+	struct mail_transaction_log_file **p;
+
+	if (log->index->map != NULL &&
+	    file->hdr.file_seq == log->index->map->hdr.log_file_seq &&
+	    log->index->map->hdr.log_file_int_offset != 0) {
+		/* we can get a valid log offset from index file. initialize
+		   sync_offset from it so we don't have to read the whole log
+		   file from beginning. */
+		file->sync_offset = log->index->map->hdr.log_file_int_offset;
+	} else {
+		file->sync_offset = file->hdr.hdr_size;
+	}
+
+	/* append to end of list. */
+	for (p = &log->tail; *p != NULL; p = &(*p)->next)
+		i_assert((*p)->hdr.file_seq < file->hdr.file_seq);
+	*p = file;
+}
+
 static struct mail_transaction_log_file *
 mail_transaction_log_file_fd_open(struct mail_transaction_log *log,
 				  const char *path, int fd)
 {
-	struct mail_transaction_log_file **p;
         struct mail_transaction_log_file *file;
 	struct stat st;
 	int ret;
 
+	i_assert(!MAIL_INDEX_IS_IN_MEMORY(log->index));
+
 	if (fstat(fd, &st) < 0) {
 		mail_index_file_set_syscall_error(log->index, path, "fstat()");
 		(void)close(fd);
@@ -532,22 +584,30 @@
 		return NULL;
 	}
 
-	if (log->index->map != NULL &&
-	    file->hdr.file_seq == log->index->map->hdr.log_file_seq &&
-	    log->index->map->hdr.log_file_int_offset != 0) {
-		/* we can get a valid log offset from index file. initialize
-		   sync_offset from it so we don't have to read the whole log
-		   file from beginning. */
-		file->sync_offset = log->index->map->hdr.log_file_int_offset;
-	} else {
-		file->sync_offset = file->hdr.hdr_size;
+        mail_transaction_log_file_alloc_finish(file);
+	return file;
+}
+
+static struct mail_transaction_log_file *
+mail_transaction_log_file_alloc_in_memory(struct mail_transaction_log *log)
+{
+	struct mail_transaction_log_file *file;
+
+	file = i_new(struct mail_transaction_log_file, 1);
+	file->refcount = 1;
+	file->log = log;
+	file->filepath = i_strdup("(in-memory transaction log file)");
+	file->fd = -1;
+
+	if (mail_transaction_log_init_hdr(log, &file->hdr) < 0) {
+		i_free(file);
+		return NULL;
 	}
 
-	/* append to end of list. */
-	for (p = &log->tail; *p != NULL; p = &(*p)->next)
-		i_assert((*p)->hdr.file_seq < file->hdr.file_seq);
-	*p = file;
+	file->buffer = buffer_create_dynamic(default_pool, 4096);
+	file->buffer_offset = sizeof(file->hdr);
 
+	mail_transaction_log_file_alloc_finish(file);
 	return file;
 }
 
@@ -557,6 +617,9 @@
 {
 	int fd;
 
+	if (MAIL_INDEX_IS_IN_MEMORY(log->index))
+		return mail_transaction_log_file_alloc_in_memory(log);
+
 	fd = open(path, O_RDWR);
 	if (fd == -1) {
 		if (errno != ENOENT) {
@@ -591,26 +654,31 @@
 int mail_transaction_log_rotate(struct mail_transaction_log *log, int lock)
 {
 	struct mail_transaction_log_file *file;
+	const char *path = log->head->filepath;
 	struct stat st;
 	int fd;
 
 	i_assert(log->head->locked);
 
-	if (fstat(log->head->fd, &st) < 0) {
-		mail_index_file_set_syscall_error(log->index,
-						  log->head->filepath,
-						  "fstat()");
-		return -1;
-	}
+	if (MAIL_INDEX_IS_IN_MEMORY(log->index))
+		file = mail_transaction_log_file_alloc_in_memory(log);
+	else {
+		if (fstat(log->head->fd, &st) < 0) {
+			mail_index_file_set_syscall_error(log->index, path,
+							  "fstat()");
+			return -1;
+		}
 
-	fd = mail_transaction_log_file_create(log, log->head->filepath,
-					      st.st_dev, st.st_ino, st.st_size);
-	if (fd == -1)
-		return -1;
+		fd = mail_transaction_log_file_create(log, path,
+						      st.st_dev, st.st_ino,
+						      st.st_size);
+		if (fd == -1)
+			return -1;
 
-	file = mail_transaction_log_file_fd_open(log, log->head->filepath, fd);
-	if (file == NULL)
-		return -1;
+		file = mail_transaction_log_file_fd_open(log, path, fd);
+		if (file == NULL)
+			return -1;
+	}
 
 	if (lock) {
 		if (mail_transaction_log_file_lock(file) < 0) {
@@ -637,6 +705,9 @@
 	struct stat st;
 	const char *path;
 
+	if (MAIL_TRANSACTION_LOG_FILE_IN_MEMORY(log->head))
+		return 0;
+
 	path = t_strconcat(log->index->filepath,
 			   MAIL_TRANSACTION_LOG_PREFIX, NULL);
 	if (stat(path, &st) < 0) {
@@ -830,6 +901,9 @@
 		return 0;
 	}
 
+	if (MAIL_TRANSACTION_LOG_FILE_IN_MEMORY(file))
+		return 1;
+
 	if (start_offset < file->hdr.hdr_size) {
 		mail_transaction_log_file_set_corrupted(file,
 			"offset (%"PRIuUOFF_T") < header size (%"PRIuSIZE_T")",



More information about the dovecot-cvs mailing list