dovecot-1.2: mbox: flock() and lockf() now use blocking alarm()e...

dovecot at dovecot.org dovecot at dovecot.org
Wed Feb 4 22:13:07 EET 2009


details:   http://hg.dovecot.org/dovecot-1.2/rev/8cca2bf6ab76
changeset: 8716:8cca2bf6ab76
user:      Timo Sirainen <tss at iki.fi>
date:      Wed Feb 04 15:13:01 2009 -0500
description:
mbox: flock() and lockf() now use blocking alarm()ed locking.

diffstat:

1 file changed, 75 insertions(+), 28 deletions(-)
src/lib-storage/index/mbox/mbox-lock.c |  103 +++++++++++++++++++++++---------

diffs (151 lines):

diff -r 25dfff279eda -r 8cca2bf6ab76 src/lib-storage/index/mbox/mbox-lock.c
--- a/src/lib-storage/index/mbox/mbox-lock.c	Wed Feb 04 14:59:41 2009 -0500
+++ b/src/lib-storage/index/mbox/mbox-lock.c	Wed Feb 04 15:13:01 2009 -0500
@@ -423,6 +423,7 @@ static int mbox_lock_flock(struct mbox_l
 			   time_t max_wait_time)
 {
 	time_t now, last_notify;
+	unsigned int next_alarm;
 
 	if (mbox_file_open_latest(ctx, lock_type) < 0)
 		return -1;
@@ -437,26 +438,49 @@ static int mbox_lock_flock(struct mbox_l
 	else
 		lock_type = LOCK_UN;
 
+	if (max_wait_time == 0) {
+		/* usually we're waiting here, but if we came from
+		   mbox_lock_dotlock(), we just want to try locking */
+		lock_type |= LOCK_NB;
+	} else {
+		now = time(NULL);
+		if (now >= max_wait_time)
+			alarm(1);
+		else
+			alarm(I_MIN(max_wait_time - now, 5));
+	}
+
         last_notify = 0;
-	while (flock(ctx->mbox->mbox_fd, lock_type | LOCK_NB) < 0) {
-		if (errno != EWOULDBLOCK) {
+	while (flock(ctx->mbox->mbox_fd, lock_type) < 0) {
+		if (errno != EINTR) {
+			if (errno == EWOULDBLOCK && max_wait_time == 0) {
+				/* non-blocking lock trying failed */
+				return 0;
+			}
+			alarm(0);
 			mbox_set_syscall_error(ctx->mbox, "flock()");
 			return -1;
 		}
 
 		now = time(NULL);
-		if (now >= max_wait_time)
+		if (now >= max_wait_time) {
+			alarm(0);
 			return 0;
-
-		if (now != last_notify) {
-			index_storage_lock_notify(&ctx->mbox->ibox,
-				MAILBOX_LOCK_NOTIFY_MAILBOX_ABORT,
-				max_wait_time - now);
-		}
-
-		usleep(LOCK_RANDOM_USLEEP_TIME);
-	}
-
+		}
+
+		/* notify locks once every 5 seconds.
+		   try to use rounded values. */
+		next_alarm = (max_wait_time - now) % 5;
+		if (next_alarm == 0)
+			next_alarm = 5;
+		alarm(next_alarm);
+
+		index_storage_lock_notify(&ctx->mbox->ibox,
+					  MAILBOX_LOCK_NOTIFY_MAILBOX_ABORT,
+					  max_wait_time - now);
+	}
+
+	alarm(0);
 	return 1;
 }
 #endif
@@ -466,6 +490,7 @@ static int mbox_lock_lockf(struct mbox_l
 			   time_t max_wait_time)
 {
 	time_t now, last_notify;
+	unsigned int next_alarm;
 
 	if (mbox_file_open_latest(ctx, lock_type) < 0)
 		return -1;
@@ -473,31 +498,53 @@ static int mbox_lock_lockf(struct mbox_l
 	if (lock_type == F_UNLCK && ctx->mbox->mbox_fd == -1)
 		return 1;
 
-	if (lock_type != F_UNLCK)
+	if (lock_type == F_UNLCK)
+		lock_type = F_ULOCK;
+	else if (max_wait_time == 0) {
+		/* usually we're waiting here, but if we came from
+		   mbox_lock_dotlock(), we just want to try locking */
 		lock_type = F_TLOCK;
-	else
-		lock_type = F_ULOCK;
+	} else {
+		now = time(NULL);
+		if (now >= max_wait_time)
+			alarm(1);
+		else
+			alarm(I_MIN(max_wait_time - now, 5));
+		lock_type = F_LOCK;
+	}
 
         last_notify = 0;
 	while (lockf(ctx->mbox->mbox_fd, lock_type, 0) < 0) {
-		if (errno != EAGAIN) {
+		if (errno != EINTR) {
+			if ((errno == EACCES || errno == EAGAIN) &&
+			    max_wait_time == 0) {
+				/* non-blocking lock trying failed */
+				return 0;
+			}
+			alarm(0);
 			mbox_set_syscall_error(ctx->mbox, "lockf()");
 			return -1;
 		}
 
 		now = time(NULL);
-		if (now >= max_wait_time)
+		if (now >= max_wait_time) {
+			alarm(0);
 			return 0;
-
-		if (now != last_notify) {
-			index_storage_lock_notify(&ctx->mbox->ibox,
-				MAILBOX_LOCK_NOTIFY_MAILBOX_ABORT,
-				max_wait_time - now);
-		}
-
-		usleep(LOCK_RANDOM_USLEEP_TIME);
-	}
-
+		}
+
+		/* notify locks once every 5 seconds.
+		   try to use rounded values. */
+		next_alarm = (max_wait_time - now) % 5;
+		if (next_alarm == 0)
+			next_alarm = 5;
+		alarm(next_alarm);
+
+		index_storage_lock_notify(&ctx->mbox->ibox,
+					  MAILBOX_LOCK_NOTIFY_MAILBOX_ABORT,
+					  max_wait_time - now);
+	}
+
+	alarm(0);
 	return 1;
 }
 #endif


More information about the dovecot-cvs mailing list