[dovecot-cvs] dovecot/src/lib-index mail-transaction-log-private.h, 1.10, 1.11 mail-transaction-log-view.c, 1.38, 1.39 mail-transaction-log.c, 1.94, 1.95

cras at dovecot.org cras at dovecot.org
Sat Apr 23 12:56:41 EEST 2005


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

Modified Files:
	mail-transaction-log-private.h mail-transaction-log-view.c 
	mail-transaction-log.c 
Log Message:
index.log file is now rotated to .index.log.2 file. When log file is
missing, it's used if the wanted log is in it.



Index: mail-transaction-log-private.h
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-index/mail-transaction-log-private.h,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -d -r1.10 -r1.11
--- mail-transaction-log-private.h	29 Mar 2005 12:18:49 -0000	1.10
+++ mail-transaction-log-private.h	23 Apr 2005 09:56:39 -0000	1.11
@@ -21,6 +21,7 @@
 	ino_t st_ino;
 	dev_t st_dev;
 	time_t last_mtime;
+	uoff_t last_size;
 
 	buffer_t *buffer;
 	uoff_t buffer_offset;

Index: mail-transaction-log-view.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-index/mail-transaction-log-view.c,v
retrieving revision 1.38
retrieving revision 1.39
diff -u -d -r1.38 -r1.39
--- mail-transaction-log-view.c	17 Apr 2005 15:59:16 -0000	1.38
+++ mail-transaction-log-view.c	23 Apr 2005 09:56:39 -0000	1.39
@@ -112,6 +112,7 @@
 		}
 	}
 
+	/* find the oldest log file first. */
 	ret = mail_transaction_log_file_find(view->log, min_file_seq, &file);
 	if (ret <= 0) {
 		if (ret == 0) {
@@ -145,6 +146,7 @@
 	ret = mail_transaction_log_file_map(file, min_file_offset, end_offset);
 	if (ret <= 0) {
 		if (ret == 0) {
+			/* File is corrupted or stale NFS handle */
 			mail_index_set_error(view->log->index,
 				"Lost transaction log file %s seq %u",
 				file->filepath, file->hdr.file_seq);
@@ -156,13 +158,27 @@
 
 	for (seq = min_file_seq+1; seq <= max_file_seq; seq++) {
 		file = file->next;
-		if (file == NULL || file->hdr.file_seq != seq)  {
+		if (file == NULL || file->hdr.file_seq != seq) {
+			/* see if we could find the missing file */
+			ret = mail_transaction_log_file_find(view->log,
+							     seq, &file);
+			if (ret <= 0) {
+				if (ret < 0)
+					return -1;
+
+				/* not found / corrupted */
+				file = NULL;
+			}
+		}
+
+		if (file == NULL || file->hdr.file_seq != seq) {
 			if (file == NULL && max_file_seq == (uint32_t)-1) {
 				/* we just wanted to sync everything */
 				max_file_seq = seq-1;
 				break;
 			}
 
+			/* missing files in the middle */
 			mail_index_set_error(view->log->index,
 				"Lost transaction log file %s seq %u",
 				view->log->tail->filepath, seq);
@@ -175,6 +191,7 @@
 		ret = mail_transaction_log_file_map(file, file->hdr.hdr_size,
 						    end_offset);
 		if (ret == 0) {
+			/* File is corrupted or stale NFS handle */
 			mail_index_set_error(view->log->index,
 				"Lost transaction log file %s seq %u",
 				file->filepath, file->hdr.file_seq);

Index: mail-transaction-log.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-index/mail-transaction-log.c,v
retrieving revision 1.94
retrieving revision 1.95
diff -u -d -r1.94 -r1.95
--- mail-transaction-log.c	23 Apr 2005 09:07:31 -0000	1.94
+++ mail-transaction-log.c	23 Apr 2005 09:56:39 -0000	1.95
@@ -14,6 +14,7 @@
 #include "mail-index-transaction-private.h"
 
 #include <stddef.h>
+#include <stdio.h>
 #include <sys/stat.h>
 
 #define LOG_PREFETCH 1024
@@ -301,7 +302,8 @@
 }
 
 static int
-mail_transaction_log_file_read_hdr(struct mail_transaction_log_file *file)
+mail_transaction_log_file_read_hdr(struct mail_transaction_log_file *file,
+				   int head)
 {
         struct mail_transaction_log_file *f;
 	int ret;
@@ -362,14 +364,29 @@
 
 	/* make sure we already don't have a file with the same sequence
 	   opened. it shouldn't happen unless the old log file was
-	   corrupted. */
-	for (f = file->log->tail; f != NULL; f = f->next) {
-		if (f->hdr.file_seq >= file->hdr.file_seq) {
-			mail_transaction_log_file_set_corrupted(file,
-				"invalid new transaction log sequence "
-				"(%u >= %u)",
-				f->hdr.file_seq, file->hdr.file_seq);
-			return 0;
+	   corrupted.
+
+	   If we're opening head log file, make sure the sequence is larger
+	   than any existing one. */
+	if (head) {
+		for (f = file->log->tail; f != NULL; f = f->next) {
+			if (f->hdr.file_seq >= file->hdr.file_seq) {
+				mail_transaction_log_file_set_corrupted(file,
+					"invalid new transaction log sequence "
+					"(%u >= %u)",
+					f->hdr.file_seq, file->hdr.file_seq);
+				return 0;
+			}
+		}
+	} else {
+		for (f = file->log->tail; f != NULL; f = f->next) {
+			if (f->hdr.file_seq == file->hdr.file_seq) {
+				mail_transaction_log_file_set_corrupted(file,
+					"old transaction log already opened "
+					"(%u == %u)",
+					f->hdr.file_seq, file->hdr.file_seq);
+				return 0;
+			}
 		}
 	}
 
@@ -422,7 +439,8 @@
 	struct mail_index *index = log->index;
 	struct mail_transaction_log_header hdr;
 	struct stat st;
-	int fd2, ret;
+	const char *path2;
+	int fd2, ret, found;
 
 	/* log creation is locked now - see if someone already created it */
 	fd2 = open(path, O_RDWR);
@@ -443,9 +461,12 @@
 
 		if (ret < 0)
 			return -1;
+		found = TRUE;
 	} else if (errno != ENOENT) {
 		mail_index_file_set_syscall_error(index, path, "open()");
 		return -1;
+	} else {
+		found = FALSE;
 	}
 
 	if (mail_transaction_log_init_hdr(log, &hdr) < 0)
@@ -457,6 +478,17 @@
 		return -1;
 	}
 
+	/* keep two log files */
+	if (found) {
+		path2 = t_strconcat(path, ".2", NULL);
+		if (rename(path, path2) < 0) {
+			i_error("rename(%s, %s) failed: %m", path, path2);
+			/* ignore the error. we don't care that much about the
+			   second log file and we're going to overwrite this
+			   first one. */
+		}
+	}
+
 	if (file_dotlock_replace(dotlock,
 				 DOTLOCK_REPLACE_FLAG_DONT_CLOSE_FD) <= 0)
 		return -1;
@@ -506,7 +538,7 @@
 }
 
 static void
-mail_transaction_log_file_alloc_finish(struct mail_transaction_log_file *file)
+mail_transaction_log_file_add_to_head(struct mail_transaction_log_file *file)
 {
 	struct mail_transaction_log *log = file->log;
 	struct mail_transaction_log_file **p;
@@ -528,9 +560,29 @@
 	*p = file;
 }
 
-static struct mail_transaction_log_file *
+static void
+mail_transaction_log_file_add_to_list(struct mail_transaction_log_file *file)
+{
+	struct mail_transaction_log *log = file->log;
+	struct mail_transaction_log_file **p;
+
+	file->sync_offset = file->hdr.hdr_size;
+
+	/* insert it to correct position */
+	for (p = &log->tail; *p != NULL; p = &(*p)->next) {
+		i_assert((*p)->hdr.file_seq != file->hdr.file_seq);
+		if ((*p)->hdr.file_seq > file->hdr.file_seq)
+			break;
+	}
+
+	file->next = *p;
+	*p = file;
+}
+
+static int
 mail_transaction_log_file_fd_open(struct mail_transaction_log *log,
-				  const char *path, int fd)
+                                  struct mail_transaction_log_file **file_r,
+				  const char *path, int fd, int head)
 {
         struct mail_transaction_log_file *file;
 	struct stat st;
@@ -538,10 +590,12 @@
 
 	i_assert(!MAIL_INDEX_IS_IN_MEMORY(log->index));
 
+	*file_r = NULL;
+
 	if (fstat(fd, &st) < 0) {
 		mail_index_file_set_syscall_error(log->index, path, "fstat()");
 		(void)close(fd);
-		return NULL;
+		return -1;
 	}
 
 	file = i_new(struct mail_transaction_log_file, 1);
@@ -552,12 +606,36 @@
 	file->st_dev = st.st_dev;
 	file->st_ino = st.st_ino;
 	file->last_mtime = st.st_mtime;
+	file->last_size = st.st_size;
+
+	ret = mail_transaction_log_file_read_hdr(file, head);
+	if (ret < 0) {
+		mail_transaction_log_file_close(file);
+		return -1;
+	}
+
+	*file_r = file;
+	return ret;
+}
+
+
+static struct mail_transaction_log_file *
+mail_transaction_log_file_fd_open_or_create(struct mail_transaction_log *log,
+					    const char *path, int fd)
+{
+	struct mail_transaction_log_file *file;
+	struct stat st;
+	int ret;
+
+	ret = mail_transaction_log_file_fd_open(log, &file, path, fd, TRUE);
+	if (ret < 0)
+		return NULL;
 
-	ret = mail_transaction_log_file_read_hdr(file);
 	if (ret == 0) {
 		/* corrupted header */
-		fd = mail_transaction_log_file_create(log, path, st.st_dev,
-						      st.st_ino, st.st_size);
+		fd = mail_transaction_log_file_create(log, path, file->st_dev,
+						      file->st_ino,
+						      file->last_size);
 		if (fd == -1)
 			ret = -1;
 		else if (fstat(fd, &st) < 0) {
@@ -575,9 +653,10 @@
 			file->st_dev = st.st_dev;
 			file->st_ino = st.st_ino;
 			file->last_mtime = st.st_mtime;
+			file->last_size = st.st_size;
 
 			memset(&file->hdr, 0, sizeof(file->hdr));
-			ret = mail_transaction_log_file_read_hdr(file);
+			ret = mail_transaction_log_file_read_hdr(file, TRUE);
 		}
 	}
 	if (ret <= 0) {
@@ -585,7 +664,7 @@
 		return NULL;
 	}
 
-        mail_transaction_log_file_alloc_finish(file);
+        mail_transaction_log_file_add_to_head(file);
 	return file;
 }
 
@@ -608,7 +687,7 @@
 	file->buffer = buffer_create_dynamic(default_pool, 4096);
 	file->buffer_offset = sizeof(file->hdr);
 
-	mail_transaction_log_file_alloc_finish(file);
+	mail_transaction_log_file_add_to_head(file);
 	return file;
 }
 
@@ -634,7 +713,7 @@
 			return NULL;
 	}
 
-	return mail_transaction_log_file_fd_open(log, path, fd);
+	return mail_transaction_log_file_fd_open_or_create(log, path, fd);
 }
 
 void mail_transaction_logs_clean(struct mail_transaction_log *log)
@@ -676,7 +755,8 @@
 		if (fd == -1)
 			return -1;
 
-		file = mail_transaction_log_file_fd_open(log, path, fd);
+		file = mail_transaction_log_file_fd_open_or_create(log,
+								   path, fd);
 		if (file == NULL)
 			return -1;
 	}
@@ -743,6 +823,9 @@
 				   struct mail_transaction_log_file **file_r)
 {
 	struct mail_transaction_log_file *file;
+	struct stat st;
+	const char *path;
+	int ret, fd;
 
 	if (file_seq > log->head->hdr.file_seq) {
 		if (mail_transaction_log_refresh(log) < 0)
@@ -756,7 +839,51 @@
 		}
 	}
 
-	return 0;
+	/* see if we have it in log.2 file */
+	path = t_strconcat(log->index->filepath,
+			   MAIL_TRANSACTION_LOG_SUFFIX".2", NULL);
+	fd = open(path, O_RDWR);
+	if (fd == -1) {
+		if (errno == ENOENT)
+			return 0;
+
+		mail_index_file_set_syscall_error(log->index, path, "open()");
+		return -1;
+	}
+
+	if (fstat(fd, &st) < 0) {
+		mail_index_file_set_syscall_error(log->index, path, "fstat()");
+		return -1;
+	}
+
+	/* see if we have it already opened */
+	for (file = log->tail; file != NULL; file = file->next) {
+		if (file->st_ino == st.st_ino &&
+		    CMP_DEV_T(file->st_dev, st.st_dev)) {
+			if (close(fd) < 0)
+				i_error("close() failed: %m");
+			return 0;
+		}
+	}
+
+	ret = mail_transaction_log_file_fd_open(log, &file, path, fd, FALSE);
+	if (ret <= 0) {
+		if (ret == 0) {
+			mail_transaction_log_file_close(file);
+			return 0;
+		}
+		return -1;
+	}
+
+	/* got it */
+	mail_transaction_log_file_add_to_list(file);
+
+	/* but is it what we expected? */
+	if (file->hdr.file_seq != file_seq)
+		return 0;
+
+	*file_r = file;
+	return 1;
 }
 
 static int



More information about the dovecot-cvs mailing list