[dovecot-cvs] dovecot/src/lib-index/mbox mbox-lock.c,1.25,1.26

cras at procontrol.fi cras at procontrol.fi
Wed Feb 12 14:07:54 EET 2003


Update of /home/cvs/dovecot/src/lib-index/mbox
In directory danu:/tmp/cvs-serv28114/lib-index/mbox

Modified Files:
	mbox-lock.c 
Log Message:
Locking code cleanups and small fixes



Index: mbox-lock.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-index/mbox/mbox-lock.c,v
retrieving revision 1.25
retrieving revision 1.26
diff -u -d -r1.25 -r1.26
--- mbox-lock.c	8 Feb 2003 13:43:13 -0000	1.25
+++ mbox-lock.c	12 Feb 2003 12:07:51 -0000	1.26
@@ -141,152 +141,6 @@
 	return TRUE;
 }
 
-static int mbox_lock_dotlock(struct mail_index *index, const char *path,
-			     time_t max_wait_time, int checkonly)
-{
-	struct stat st;
-	time_t now, last_change, last_notify, last_mtime, stale_notify;
-	off_t last_size;
-	unsigned int secs_left;
-	int fd;
-
-	path = t_strconcat(path, ".lock", NULL);
-	stale_notify = dotlock_change_timeout/2;
-
-	/* don't bother with the temp files as we'd just leave them lying
-	   around. besides, postfix also relies on O_EXCL working so we
-	   might as well. */
-	last_change = time(NULL); last_notify = 0;
-	last_size = 0; last_mtime = 0;
-	do {
-		now = time(NULL);
-
-		if (lstat(path, &st) == 0) {
-			/* see if there's been any changes in mbox */
-			if (stat(index->mailbox_path, &st) < 0) {
-				mbox_set_syscall_error(index, "stat()");
-				break;
-			}
-
-			if (last_size != st.st_size ||
-			    last_mtime != st.st_mtime) {
-				last_change = now;
-				last_size = st.st_size;
-				last_mtime = st.st_mtime;
-			}
-
-			if (now > last_change + dotlock_change_timeout) {
-				/* no changes for a while, assume stale lock */
-				if (unlink(path) < 0 && errno != ENOENT) {
-					index_file_set_syscall_error(
-						index, path, "unlink()");
-					break;
-				}
-				continue;
-			}
-
-			if (last_notify != now &&
-			    index->lock_notify_cb != NULL) {
-				last_notify = now;
-				if (now > last_change + stale_notify) {
-					secs_left = now - last_change +
-						dotlock_change_timeout;
-					index->lock_notify_cb(
-					      MAIL_LOCK_NOTIFY_MAILBOX_OVERRIDE,
-					      secs_left,
-					      index->lock_notify_context);
-				} else {
-					index->lock_notify_cb(
-						MAIL_LOCK_NOTIFY_MAILBOX_ABORT,
-						max_wait_time - now,
-						index->lock_notify_context);
-				}
-			}
-
-			usleep(LOCK_RANDOM_USLEEP_TIME);
-			continue;
-		}
-
-		if (checkonly) {
-			/* we only wanted to check that the .lock file
-			   doesn't exist. This is racy of course, but I don't
-			   think there's any better way to do it really.
-			   The fcntl/flock later does the real locking, so
-			   problem comes only when someone uses only dotlock
-			   locking, and we can't fix that without dotlocking
-			   ourself (which we didn't want to do here) */
-			return TRUE;
-		}
-
-		fd = open(path, O_WRONLY | O_EXCL | O_CREAT, 0);
-		if (fd != -1) {
-			/* got it */
-			if (fstat(fd, &st) < 0) {
-				index_file_set_syscall_error(index, path,
-							     "fstat()");
-				(void)close(fd);
-				return FALSE;
-			}
-
-			index->mbox_dotlock_dev = st.st_dev;
-			index->mbox_dotlock_ino = st.st_ino;
-
-			if (close(fd) < 0) {
-				index_file_set_syscall_error(index, path,
-							     "close()");
-				return FALSE;
-			}
-			return TRUE;
-		}
-
-		if (errno != EEXIST) {
-			index_file_set_syscall_error(index, path, "open()");
-			return FALSE;
-		}
-	} while (now < max_wait_time);
-
-	index_set_error(index, "Timeout while waiting for release of mbox "
-			"dotlock %s", path);
-	index->mailbox_lock_timeout = TRUE;
-	return FALSE;
-}
-
-static int mbox_unlock_dotlock(struct mail_index *index, const char *path)
-{
-	struct stat st;
-	dev_t old_dev;
-	ino_t old_ino;
-
-	path = t_strconcat(path, ".lock", NULL);
-
-        old_dev = index->mbox_dotlock_dev;
-        old_ino = index->mbox_dotlock_ino;
-
-        memset(&index->mbox_dotlock_dev, 0, sizeof(index->mbox_dotlock_dev));
-        index->mbox_dotlock_ino = 0;
-
-	if (lstat(path, &st) < 0) {
-		if (errno == ENOENT)
-			return TRUE; /* doesn't exist anymore, ignore */
-
-		index_file_set_syscall_error(index, path, "stat()");
-		return FALSE;
-	}
-
-	/* make sure it's still our dotlock */
-	if (old_ino != st.st_ino ||
-	    !CMP_DEV_T(old_dev, st.st_dev)) {
-		index_set_error(index,
-			"Warning: Our dotlock file %s was overridden", path);
-		return FALSE;
-	}
-
-	if (unlink(path) < 0 && errno != ENOENT)
-		return index_file_set_syscall_error(index, path, "unlink()");
-
-	return TRUE;
-}
-
 static int mbox_file_locks(struct mail_index *index, time_t max_wait_time)
 {
 	if (use_fcntl_lock && fcntl_before_flock) {
@@ -309,10 +163,20 @@
 	return TRUE;
 }
 
+static void dotlock_callback(unsigned int secs_left, int stale, void *context)
+{
+	struct mail_index *index = context;
+
+	index->lock_notify_cb(stale ? MAIL_LOCK_NOTIFY_MAILBOX_OVERRIDE :
+			      MAIL_LOCK_NOTIFY_MAILBOX_ABORT,
+			      secs_left, index->lock_notify_context);
+}
+
 int mbox_lock(struct mail_index *index, enum mail_lock_type lock_type)
 {
 	struct stat st;
 	time_t max_wait_time;
+	int ret;
 
 	/* index must be locked before mbox file, to avoid deadlocks */
 	i_assert(index->lock_type != MAIL_LOCK_UNLOCK);
@@ -332,12 +196,25 @@
 	max_wait_time = time(NULL) + lock_timeout;
 
 	/* make .lock file first to protect overwriting the file */
-	if (use_dotlock && index->mbox_dotlock_ino == 0) {
-		if (!mbox_lock_dotlock(index, index->mailbox_path,
-				       max_wait_time,
-				       lock_type == MAIL_LOCK_SHARED &&
-				       !use_read_dotlock))
+	if (use_dotlock && index->mbox_dotlock.ino == 0) {
+		ret = file_lock_dotlock(index->mailbox_path,
+					lock_type == MAIL_LOCK_SHARED &&
+					!use_read_dotlock, lock_timeout,
+					dotlock_change_timeout,
+					dotlock_callback, index,
+					&index->mbox_dotlock);
+
+		if (ret < 0) {
+			mbox_set_syscall_error(index, "file_lock_dotlock()");
 			return FALSE;
+		}
+		if (ret == 0) {
+			index_set_error(index, "Timeout while waiting for "
+					"release of dotlock for mbox %s",
+					index->mailbox_path);
+			index->mailbox_lock_timeout = TRUE;
+			return FALSE;
+		}
 	}
 
 	/* now we need to have the file itself locked. open it if needed. */
@@ -383,9 +260,13 @@
 			failed = TRUE;
 	}
 
-	if (index->mbox_dotlock_ino != 0) {
-		if (!mbox_unlock_dotlock(index, index->mailbox_path))
+	if (index->mbox_dotlock.ino != 0) {
+		if (file_unlock_dotlock(index->mailbox_path,
+					&index->mbox_dotlock) <= 0) {
+                        mbox_set_syscall_error(index, "file_unlock_dotlock()");
 			failed = TRUE;
+		}
+                index->mbox_dotlock.ino = 0;
 	}
 
 	/* make sure we don't keep mmap() between locks - there could have




More information about the dovecot-cvs mailing list