changeset 3981:0d64f8888dcd HEAD

Removed immediate_stale_timeout and changed the stale_timeout behavior to check both dotlock and the file it protects, and overwrite the lock file whenever neither of them have been modified for stale_timeout seconds (ie. also immediately if their timestamps are old enough).
author Timo Sirainen <tss@iki.fi>
date Sun, 05 Feb 2006 14:46:07 +0200
parents 90638cc0d4e4
children 15c48c43cc75
files src/lib-index/mail-cache-private.h src/lib-index/mail-cache.c src/lib-index/mail-transaction-log.c src/lib-storage/index/dbox/dbox-sync.c src/lib-storage/index/maildir/maildir-uidlist.c src/lib-storage/index/mbox/mbox-lock.c src/lib-storage/subscription-file/subscription-file.c src/lib/file-dotlock.c src/lib/file-dotlock.h src/plugins/convert/convert-storage.c
diffstat 10 files changed, 59 insertions(+), 68 deletions(-) [+]
line wrap: on
line diff
--- a/src/lib-index/mail-cache-private.h	Sun Feb 05 14:08:13 2006 +0200
+++ b/src/lib-index/mail-cache-private.h	Sun Feb 05 14:46:07 2006 +0200
@@ -31,7 +31,6 @@
 
 #define MAIL_CACHE_LOCK_TIMEOUT 120
 #define MAIL_CACHE_LOCK_CHANGE_TIMEOUT 60
-#define MAIL_CACHE_LOCK_IMMEDIATE_TIMEOUT (5*60)
 
 #define CACHE_RECORD(cache, offset) \
 	((const struct mail_cache_record *) \
--- a/src/lib-index/mail-cache.c	Sun Feb 05 14:08:13 2006 +0200
+++ b/src/lib-index/mail-cache.c	Sun Feb 05 14:46:07 2006 +0200
@@ -278,8 +278,6 @@
 
 	cache->dotlock_settings.timeout = MAIL_CACHE_LOCK_TIMEOUT;
 	cache->dotlock_settings.stale_timeout = MAIL_CACHE_LOCK_CHANGE_TIMEOUT;
-	cache->dotlock_settings.immediate_stale_timeout =
-		MAIL_CACHE_LOCK_IMMEDIATE_TIMEOUT;
 
 	if (!MAIL_INDEX_IS_IN_MEMORY(index)) {
 		if (index->mmap_disable || index->mmap_no_write)
--- a/src/lib-index/mail-transaction-log.c	Sun Feb 05 14:08:13 2006 +0200
+++ b/src/lib-index/mail-transaction-log.c	Sun Feb 05 14:46:07 2006 +0200
@@ -21,8 +21,7 @@
 
 /* this lock should never exist for a long time.. */
 #define LOG_DOTLOCK_TIMEOUT 60
-#define LOG_DOTLOCK_STALE_TIMEOUT 0
-#define LOG_DOTLOCK_IMMEDIATE_STALE_TIMEOUT 60
+#define LOG_DOTLOCK_STALE_TIMEOUT 60
 
 #define MAIL_TRANSACTION_LOG_SUFFIX ".log"
 #define LOG_NEW_DOTLOCK_SUFFIX ".newlock"
@@ -230,8 +229,6 @@
 
 	log->dotlock_settings.timeout = LOG_DOTLOCK_TIMEOUT;
 	log->dotlock_settings.stale_timeout = LOG_DOTLOCK_STALE_TIMEOUT;
-	log->dotlock_settings.immediate_stale_timeout =
-		LOG_DOTLOCK_IMMEDIATE_STALE_TIMEOUT;
 
 	log->new_dotlock_settings = log->dotlock_settings;
 	log->new_dotlock_settings.lock_suffix = LOG_NEW_DOTLOCK_SUFFIX;
--- a/src/lib-storage/index/dbox/dbox-sync.c	Sun Feb 05 14:08:13 2006 +0200
+++ b/src/lib-storage/index/dbox/dbox-sync.c	Sun Feb 05 14:46:07 2006 +0200
@@ -253,6 +253,9 @@
 	unsigned int first_flag_offset;
 	int ret;
 
+	if (ctx->mbox->file->keyword_count == 0)
+		return 0;
+
 	t_push();
 	keyword_array = t_malloc(ctx->mbox->file->keyword_count);
 	keyword_mask = t_malloc(ctx->mbox->file->keyword_count);
--- a/src/lib-storage/index/maildir/maildir-uidlist.c	Sun Feb 05 14:08:13 2006 +0200
+++ b/src/lib-storage/index/maildir/maildir-uidlist.c	Sun Feb 05 14:46:07 2006 +0200
@@ -17,7 +17,7 @@
 #include <utime.h>
 
 /* how many seconds to wait before overriding uidlist.lock */
-#define UIDLIST_LOCK_STALE_TIMEOUT (60*5)
+#define UIDLIST_LOCK_STALE_TIMEOUT (60*2)
 
 #define UIDLIST_IS_LOCKED(uidlist) \
 	((uidlist)->lock_count > 0)
@@ -148,10 +148,8 @@
 				     maildir_hash, maildir_cmp);
 	uidlist->next_uid = 1;
 
-	uidlist->dotlock_settings.timeout = UIDLIST_LOCK_STALE_TIMEOUT;
+	uidlist->dotlock_settings.timeout = UIDLIST_LOCK_STALE_TIMEOUT + 2;
 	uidlist->dotlock_settings.stale_timeout = UIDLIST_LOCK_STALE_TIMEOUT;
-	uidlist->dotlock_settings.immediate_stale_timeout =
-		UIDLIST_LOCK_STALE_TIMEOUT;
 	uidlist->dotlock_settings.temp_prefix =
 		INDEX_STORAGE(mbox->storage)->temp_prefix;
 
--- a/src/lib-storage/index/mbox/mbox-lock.c	Sun Feb 05 14:08:13 2006 +0200
+++ b/src/lib-storage/index/mbox/mbox-lock.c	Sun Feb 05 14:46:07 2006 +0200
@@ -25,7 +25,7 @@
 /* lock timeout */
 #define DEFAULT_LOCK_TIMEOUT (10*60)
 /* assume stale dotlock if mbox file hasn't changed for n seconds */
-#define DEFAULT_DOTLOCK_CHANGE_TIMEOUT (5*60)
+#define DEFAULT_DOTLOCK_CHANGE_TIMEOUT (10)
 
 enum mbox_lock_type {
 	MBOX_LOCK_DOTLOCK,
--- a/src/lib-storage/subscription-file/subscription-file.c	Sun Feb 05 14:08:13 2006 +0200
+++ b/src/lib-storage/subscription-file/subscription-file.c	Sun Feb 05 14:46:07 2006 +0200
@@ -14,7 +14,6 @@
 
 #define SUBSCRIPTION_FILE_LOCK_TIMEOUT 120
 #define SUBSCRIPTION_FILE_CHANGE_TIMEOUT 30
-#define SUBSCRIPTION_FILE_IMMEDIATE_TIMEOUT (5*60)
 
 struct subsfile_list_context {
 	pool_t pool;
@@ -85,7 +84,6 @@
 	dotlock_set.temp_prefix = temp_prefix;
 	dotlock_set.timeout = SUBSCRIPTION_FILE_LOCK_TIMEOUT;
 	dotlock_set.stale_timeout = SUBSCRIPTION_FILE_CHANGE_TIMEOUT;
-	dotlock_set.immediate_stale_timeout = SUBSCRIPTION_FILE_IMMEDIATE_TIMEOUT;
 
 	/* FIXME: set lock notification callback */
 	fd_out = file_dotlock_open(&dotlock_set, path, 0, &dotlock);
--- a/src/lib/file-dotlock.c	Sun Feb 05 14:08:13 2006 +0200
+++ b/src/lib/file-dotlock.c	Sun Feb 05 14:46:07 2006 +0200
@@ -32,22 +32,24 @@
 	time_t lock_time;
 };
 
+struct file_change_info {
+	dev_t dev;
+	ino_t ino;
+	off_t size;
+	time_t ctime, mtime;
+};
+
 struct lock_info {
 	const struct dotlock_settings *set;
 	const char *path, *lock_path, *temp_path;
 	int fd;
 
-	dev_t dev;
-	ino_t ino;
-	off_t size;
-	time_t ctime, mtime;
-
-	off_t last_size;
-	time_t last_ctime, last_mtime;
-	time_t last_change;
+	struct file_change_info lock_info;
+	struct file_change_info file_info;
 
 	bool have_pid;
 	time_t last_pid_check;
+	time_t last_change;
 };
 
 static struct dotlock *
@@ -100,10 +102,33 @@
 	return (pid_t)strtoul(buf, NULL, 0);
 }
 
+static bool
+update_change_info(const struct stat *st, struct file_change_info *change,
+		   time_t *last_change_r, time_t now)
+{
+	if (change->ino != st->st_ino || !CMP_DEV_T(change->dev, st->st_dev) ||
+	    change->ctime != st->st_ctime || change->mtime != st->st_mtime ||
+	    change->size != st->st_size) {
+		time_t change_time = now;
+
+		if (change->ctime == 0) {
+			/* first check, set last_change to file's change time */
+			change_time = I_MAX(st->st_ctime, st->st_mtime);
+		}
+		if (*last_change_r < change_time)
+			*last_change_r = change_time;
+		change->ino = st->st_ino;
+		change->dev = st->st_dev;
+		change->ctime = st->st_ctime;
+		change->mtime = st->st_mtime;
+		change->size = st->st_size;
+		return TRUE;
+	}
+	return FALSE;
+}
+
 static int check_lock(time_t now, struct lock_info *lock_info)
 {
-	time_t immediate_stale_timeout =
-		lock_info->set->immediate_stale_timeout;
 	time_t stale_timeout = lock_info->set->stale_timeout;
 	struct stat st;
 	pid_t pid;
@@ -116,32 +141,11 @@
 		return 1;
 	}
 
-	if (lock_info->set->immediate_stale_timeout != 0 &&
-	    now > st.st_mtime + immediate_stale_timeout &&
-	    now > st.st_ctime + immediate_stale_timeout) {
-		/* old lock file */
-		if (unlink(lock_info->lock_path) < 0 && errno != ENOENT) {
-			i_error("unlink(%s) failed: %m", lock_info->lock_path);
-			return -1;
-		}
-		return 1;
-	}
-
-	if (lock_info->ino != st.st_ino ||
-	    !CMP_DEV_T(lock_info->dev, st.st_dev) ||
-	    lock_info->ctime != st.st_ctime ||
-	    lock_info->mtime != st.st_mtime ||
-	    lock_info->size != st.st_size) {
+	if (update_change_info(&st, &lock_info->lock_info,
+			       &lock_info->last_change, now)) {
 		/* either our first check or someone else got the lock file. */
-		lock_info->dev = st.st_dev;
-		lock_info->ino = st.st_ino;
-		lock_info->ctime = st.st_ctime;
-		lock_info->mtime = st.st_mtime;
-		lock_info->size = st.st_size;
-
 		pid = read_local_pid(lock_info->lock_path);
 		lock_info->have_pid = pid != -1;
-		lock_info->last_change = now;
 	} else if (!lock_info->have_pid) {
 		/* no pid checking */
 		pid = -1;
@@ -181,7 +185,9 @@
 		return 0;
 	}
 
-	if (lock_info->last_change != now) {
+	if (now > lock_info->last_change + stale_timeout) {
+		/* possibly stale lock file. check also the timestamp of the
+		   file we're protecting. */
 		if (stat(lock_info->path, &st) < 0) {
 			if (errno == ENOENT) {
 				/* file doesn't exist. treat it as if
@@ -190,13 +196,9 @@
 				i_error("stat(%s) failed: %m", lock_info->path);
 				return -1;
 			}
-		} else if (lock_info->last_size != st.st_size ||
-			   lock_info->last_ctime != st.st_ctime ||
-			   lock_info->last_mtime != st.st_mtime) {
-			lock_info->last_change = now;
-			lock_info->last_size = st.st_size;
-			lock_info->last_ctime = st.st_ctime;
-			lock_info->last_mtime = st.st_mtime;
+		} else {
+			(void)update_change_info(&st, &lock_info->file_info,
+						 &lock_info->last_change, now);
 		}
 	}
 
@@ -368,7 +370,6 @@
 	lock_info.path = path;
 	lock_info.set = set;
 	lock_info.lock_path = lock_path;
-	lock_info.last_change = now;
 	lock_info.fd = -1;
 
 	last_notify = 0; do_wait = FALSE;
--- a/src/lib/file-dotlock.h	Sun Feb 05 14:08:13 2006 +0200
+++ b/src/lib/file-dotlock.h	Sun Feb 05 14:46:07 2006 +0200
@@ -17,11 +17,9 @@
 
 	/* Abort after this many seconds. */
 	unsigned int timeout;
-	/* If file specified in path doesn't change in stale_timeout seconds
-	   and it's still locked, override the lock file. */
+	/* Override the lock file when it and the file we're protecting is
+	   older than stale_timeout. */
 	unsigned int stale_timeout;
-	/* If file is older than this, override the lock immediately. */
-	unsigned int immediate_stale_timeout;
 
 	/* Callback is called once in a while. stale is set to TRUE if stale
 	   lock is detected and will be overridden in secs_left. If callback
--- a/src/plugins/convert/convert-storage.c	Sun Feb 05 14:08:13 2006 +0200
+++ b/src/plugins/convert/convert-storage.c	Sun Feb 05 14:46:07 2006 +0200
@@ -11,17 +11,16 @@
 #define CONVERT_LOCK_FILENAME ".dovecot.convert"
 
 const struct dotlock_settings dotlock_settings = {
-	NULL,
-	NULL,
+	MEMBER(temp_prefix) NULL,
+	MEMBER(lock_suffix) NULL,
 
-	60*5,
-	0,
-	60*5,
+	MEMBER(timeout) 60*5,
+	MEMBER(stale_timeout) 60*5,
 
-	NULL,
-	NULL,
+	MEMBER(callback) NULL,
+	MEMBER(context) NULL,
 
-	FALSE
+	MEMBER(use_excl_lock) FALSE
 };
 
 static int sync_mailbox(struct mailbox *box)