[dovecot-cvs] dovecot/src/lib-storage/index/mbox mbox-lock.c, 1.2, 1.3 mbox-sync-parse.c, 1.7, 1.8 mbox-sync.c, 1.10, 1.11

cras at procontrol.fi cras at procontrol.fi
Thu Jun 3 18:01:29 EEST 2004


Update of /home/cvs/dovecot/src/lib-storage/index/mbox
In directory talvi:/tmp/cvs-serv23527/src/lib-storage/index/mbox

Modified Files:
	mbox-lock.c mbox-sync-parse.c mbox-sync.c 
Log Message:
Separate mbox_locks/mbox_read_dotlock to mbox_read_locks and
mbox_write_locks. Added support for lockf() method.



Index: mbox-lock.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-storage/index/mbox/mbox-lock.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- a/mbox-lock.c	9 May 2004 21:06:48 -0000	1.2
+++ b/mbox-lock.c	3 Jun 2004 15:01:27 -0000	1.3
@@ -19,7 +19,8 @@
 #define LOCK_RANDOM_USLEEP_TIME (100000 + (unsigned int)rand() % 100000)
 
 /* lock methods to use in wanted order */
-#define DEFAULT_LOCK_METHODS "dotlock fcntl"
+#define DEFAULT_READ_LOCK_METHODS "fcntl"
+#define DEFAULT_WRITE_LOCK_METHODS "dotlock fcntl"
 /* lock timeout */
 #define DEFAULT_LOCK_TIMEOUT 300
 /* assume stale dotlock if mbox file hasn't changed for n seconds */
@@ -31,34 +32,98 @@
 	int last_stale;
 };
 
+enum mbox_lock_type {
+	MBOX_LOCK_DOTLOCK,
+	MBOX_LOCK_FCNTL,
+	MBOX_LOCK_FLOCK,
+	MBOX_LOCK_LOCKF,
+
+	MBOX_LOCK_COUNT
+};
+
+struct mbox_lock_data {
+	enum mbox_lock_type type;
+	const char *name;
+	int (*func)(struct index_mailbox *ibox, int lock_type,
+		    time_t max_wait_time);
+};
+
+static int mbox_lock_fcntl(struct index_mailbox *ibox, int lock_type,
+			   time_t max_wait_time);
+#ifdef HAVE_FLOCK
+static int mbox_lock_flock(struct index_mailbox *ibox, int lock_type,
+			   time_t max_wait_time);
+#else
+#  define mbox_lock_flock NULL
+#endif
+#ifdef HAVE_LOCKF
+static int mbox_lock_lockf(struct index_mailbox *ibox, int lock_type,
+			   time_t max_wait_time);
+#else
+#  define mbox_lock_lockf NULL
+#endif
+
+struct mbox_lock_data lock_data[] = {
+	{ MBOX_LOCK_DOTLOCK, "dotlock", NULL },
+	{ MBOX_LOCK_FCNTL, "fcntl", mbox_lock_fcntl },
+	{ MBOX_LOCK_FLOCK, "flock", mbox_lock_flock },
+	{ MBOX_LOCK_LOCKF, "lockf", mbox_lock_lockf },
+	{ 0, NULL, NULL }
+};
+
 static int lock_settings_initialized = FALSE;
-static int use_dotlock, use_fcntl_lock, use_flock, fcntl_before_flock;
-static int use_read_dotlock, lock_timeout, dotlock_change_timeout;
+static enum mbox_lock_type read_locks[MBOX_LOCK_COUNT+1];
+static enum mbox_lock_type write_locks[MBOX_LOCK_COUNT+1];
+static int lock_timeout, dotlock_change_timeout;
 
 static int mbox_unlock_files(struct index_mailbox *ibox);
 
-static void mbox_init_lock_settings(void)
+static void mbox_read_lock_methods(const char *str, const char *env,
+				   enum mbox_lock_type *locks)
 {
-	const char *str;
+        enum mbox_lock_type type;
 	const char *const *lock;
+	int i, dest;
 
-        use_dotlock = use_fcntl_lock = use_flock = fcntl_before_flock = FALSE;
+	for (lock = t_strsplit(str, " "), dest = 0; *lock != NULL; lock++) {
+		for (type = 0; lock_data[type].name != NULL; type++) {
+			if (strcasecmp(*lock, lock_data[type].name) == 0) {
+				type = lock_data[type].type;
+				break;
+			}
+		}
+		if (lock_data[type].name == NULL)
+			i_fatal("%s: Invalid value %s", env, *lock);
+		if (lock_data[type].func == NULL && type != MBOX_LOCK_DOTLOCK) {
+			i_fatal("%s: Support for lock type %s "
+				"not compiled into binary", env, *lock);
+		}
 
-	str = getenv("MBOX_LOCKS");
-	if (str == NULL) str = DEFAULT_LOCK_METHODS;
-	for (lock = t_strsplit(str, " "); *lock != NULL; lock++) {
-		if (strcasecmp(*lock, "dotlock") == 0)
-			use_dotlock = TRUE;
-		else if (strcasecmp(*lock, "fcntl") == 0) {
-			use_fcntl_lock = TRUE;
-			fcntl_before_flock = use_flock == FALSE;
-		} else if (strcasecmp(*lock, "flock") == 0)
-			use_flock = TRUE;
-		else
-			i_fatal("MBOX_LOCKS: Invalid value %s", *lock);
+		for (i = 0; i < dest; i++) {
+			if (locks[i] == type)
+				i_fatal("%s: Duplicated value %s", env, *lock);
+		}
+
+		if (type == MBOX_LOCK_DOTLOCK && dest != 0)
+			i_fatal("%s: dotlock must be first in the list", *lock);
+
+		/* @UNSAFE */
+		locks[dest++] = type;
 	}
+	locks[dest] = (enum mbox_lock_type)-1;
+}
 
-	use_read_dotlock = getenv("MBOX_READ_DOTLOCK") != NULL;
+static void mbox_init_lock_settings(void)
+{
+	const char *str;
+
+	str = getenv("MBOX_READ_LOCKS");
+	if (str == NULL) str = DEFAULT_READ_LOCK_METHODS;
+	mbox_read_lock_methods(str, "MBOX_READ_LOCKS", read_locks);
+
+	str = getenv("MBOX_WRITE_LOCKS");
+	if (str == NULL) str = DEFAULT_WRITE_LOCK_METHODS;
+	mbox_read_lock_methods(str, "MBOX_WRITE_LOCKS", write_locks);
 
 	str = getenv("MBOX_LOCK_TIMEOUT");
 	lock_timeout = str == NULL ? DEFAULT_LOCK_TIMEOUT : atoi(str);
@@ -110,6 +175,44 @@
 }
 #endif
 
+#ifdef HAVE_LOCKF
+static int mbox_lock_lockf(struct index_mailbox *ibox, int lock_type,
+			   time_t max_wait_time)
+{
+	time_t now, last_notify;
+
+	if (lock_type != F_UNLCK)
+		lock_type = F_TLOCK;
+	else
+		lock_type = F_ULOCK;
+
+        last_notify = 0;
+	while (lockf(ibox->mbox_fd, lock_type, 0) < 0) {
+		if (errno != EAGAIN) {
+			mbox_set_syscall_error(ibox, "lockf()");
+			return -1;
+		}
+
+		if (max_wait_time == 0)
+			return 0;
+
+		now = time(NULL);
+		if (now >= max_wait_time)
+			return 0;
+
+		if (now != last_notify) {
+			index_storage_lock_notify(ibox,
+				MAILBOX_LOCK_NOTIFY_MAILBOX_ABORT,
+				max_wait_time - now);
+		}
+
+		usleep(LOCK_RANDOM_USLEEP_TIME);
+	}
+
+	return 1;
+}
+#endif
+
 static int mbox_lock_fcntl(struct index_mailbox *ibox, int lock_type,
 			   time_t max_wait_time)
 {
@@ -145,8 +248,9 @@
 static int mbox_file_locks(struct index_mailbox *ibox, int lock_type,
 			   time_t max_wait_time)
 {
+	enum mbox_lock_type *lock_types;
 	struct stat st;
-	int ret;
+	int i, ret;
 
 	/* now we need to have the file itself locked. open it if needed. */
 	if (stat(ibox->path, &st) < 0) {
@@ -164,36 +268,30 @@
 		}
 	}
 
-	if (use_fcntl_lock && fcntl_before_flock) {
-		ret = mbox_lock_fcntl(ibox, lock_type, max_wait_time);
-		if (ret <= 0)
-			return ret;
-	}
-#ifdef HAVE_FLOCK
-	if (use_flock) {
-		ret = mbox_lock_flock(ibox, lock_type, max_wait_time);
-		if (ret <= 0)
-			return ret;
-	}
-#endif
-	if (use_fcntl_lock && !fcntl_before_flock) {
-		ret = mbox_lock_fcntl(ibox, lock_type, max_wait_time);
-		if (ret <= 0)
-			return ret;
+	lock_types = lock_type == F_WRLCK ? write_locks : read_locks;
+	for (i = 0; lock_types[i] != (enum mbox_lock_type)-1; i++) {
+		if (lock_data[lock_types[i]].type != MBOX_LOCK_DOTLOCK) {
+			ret = lock_data[lock_types[i]].func(ibox, lock_type,
+							    max_wait_time);
+			if (ret <= 0)
+				return ret;
+		}
 	}
 	return 1;
 }
 
 static int mbox_file_unlock(struct index_mailbox *ibox)
 {
-	int ret = 0;
+	enum mbox_lock_type *lock_types;
+	int i, ret = 0;
 
-#ifdef HAVE_FLOCK
-	if (use_flock && mbox_lock_flock(ibox, F_UNLCK, 0) < 0)
-		ret = -1;
-#endif
-	if (use_fcntl_lock && mbox_lock_fcntl(ibox, F_UNLCK, 0) < 0)
-		ret = -1;
+	lock_types = ibox->mbox_lock_type == F_WRLCK ? write_locks : read_locks;
+	for (i = 0; lock_types[i] != (enum mbox_lock_type)-1; i++) {
+		if (lock_data[lock_types[i]].type != MBOX_LOCK_DOTLOCK) {
+			if (lock_data[lock_types[i]].func(ibox, F_UNLCK, 0) < 0)
+				ret = -1;
+		}
+	}
 
 	return ret;
 }
@@ -242,16 +340,16 @@
 	max_wait_time = time(NULL) + lock_timeout;
 
 	/* make .lock file first to protect overwriting the file */
-	if (use_dotlock && ibox->mbox_dotlock.ino == 0) {
+	if (((lock_type == F_RDLCK && read_locks[0] == MBOX_LOCK_DOTLOCK) ||
+	     (lock_type == F_WRLCK && write_locks[0] == MBOX_LOCK_DOTLOCK)) &&
+	    ibox->mbox_dotlock.ino == 0) {
 		struct dotlock_context ctx;
 
 		ctx.ibox = ibox;
 		ctx.lock_type = lock_type;
 		ctx.last_stale = -1;
 
-		ret = file_lock_dotlock(ibox->path, NULL,
-					lock_type == F_RDLCK &&
-					!use_read_dotlock, lock_timeout,
+		ret = file_lock_dotlock(ibox->path, NULL, FALSE, lock_timeout,
 					dotlock_change_timeout, 0,
 					dotlock_callback, &ctx,
 					&ibox->mbox_dotlock);

Index: mbox-sync-parse.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-storage/index/mbox/mbox-sync-parse.c,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -d -r1.7 -r1.8
--- a/mbox-sync-parse.c	24 May 2004 03:03:03 -0000	1.7
+++ b/mbox-sync-parse.c	3 Jun 2004 15:01:27 -0000	1.8
@@ -108,6 +108,11 @@
 		ctx->sync_ctx->next_uid = uid_last+1;
 	}
 
+	if (ctx->sync_ctx->prev_msg_uid >= ctx->sync_ctx->next_uid) {
+		/* broken, update */
+                ctx->sync_ctx->next_uid = ctx->sync_ctx->prev_msg_uid+1;
+	}
+
 	ctx->hdr_pos[MBOX_HDR_X_IMAPBASE] = str_len(ctx->header);
 	ctx->seen_imapbase = TRUE;
 
@@ -167,6 +172,11 @@
 		extra_space++;
 	}
 
+	if (value >= ctx->sync_ctx->next_uid) {
+		/* next_uid broken - fix it */
+		ctx->sync_ctx->next_uid = value+1;
+	}
+
 	if (value <= ctx->sync_ctx->prev_msg_uid) {
 		/* broken - UIDs must be growing */
 		return FALSE;

Index: mbox-sync.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-storage/index/mbox/mbox-sync.c,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -d -r1.10 -r1.11
--- a/mbox-sync.c	24 May 2004 03:03:03 -0000	1.10
+++ b/mbox-sync.c	3 Jun 2004 15:01:27 -0000	1.11
@@ -166,7 +166,7 @@
 	buffer_t *mails, *syncs;
 	size_t size;
 	struct stat st;
-	int ret = 0;
+	int sync_expunge, ret = 0;
 
 	t = mail_index_transaction_begin(sync_view, FALSE);
 
@@ -205,13 +205,19 @@
 		mbox_sync_next_mail(&sync_ctx, &mail_ctx, seq);
 
 		/* get all sync records related to this message */
-		ret = 1;
+		ret = 1; sync_expunge = FALSE;
 		mbox_sync_buffer_delete_old(syncs, mail_ctx.mail.uid);
 		while (mail_ctx.mail.uid >= sync_rec.uid1 && ret > 0) {
 			if (sync_rec.uid1 != 0) {
 				i_assert(mail_ctx.mail.uid <= sync_rec.uid2);
 				buffer_append(syncs, &sync_rec,
 					      sizeof(sync_rec));
+
+				if (sync_rec.type ==
+				    MAIL_INDEX_SYNC_TYPE_EXPUNGE) {
+					sync_expunge = TRUE;
+					break;
+				}
 			}
 			ret = mail_index_sync_next(index_sync_ctx, &sync_rec);
 			if (ret == 0)
@@ -278,7 +284,9 @@
 			break;
 		}
 
-		if (rec != NULL) {
+		if (sync_expunge) {
+			/* .. */
+		} else if (rec != NULL) {
 			/* see if flags changed */
 			keywords_mask_t old_keywords;
 			uint8_t old_flags;
@@ -340,7 +348,7 @@
 		}
 	}
 
-	if (need_space_seq != 0) {
+	if (need_space_seq != 0 && ret >= 0) {
 		i_assert(space_diff < 0);
 		extra_space = MBOX_HEADER_EXTRA_SPACE *
 			(seq - need_space_seq + 1);
@@ -362,13 +370,16 @@
 		}
 	}
 
-	if (rec != NULL)
-		mail_index_expunge(t, idx_seq);
-	while (idx_seq < messages_count)
-		mail_index_expunge(t, ++idx_seq);
+	if (ret >= 0) {
+		if (rec != NULL)
+			mail_index_expunge(t, idx_seq);
+		while (idx_seq < messages_count)
+			mail_index_expunge(t, ++idx_seq);
 
-	if (sync_ctx.base_uid_last+1 != sync_ctx.next_uid) {
-		// FIXME: rewrite X-IMAPbase header
+		if (sync_ctx.base_uid_last+1 != sync_ctx.next_uid) {
+
+			// FIXME: rewrite X-IMAPbase header
+		}
 	}
 
 	if (ret >= 0) {



More information about the dovecot-cvs mailing list