[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