dovecot-2.2: director: Update existing users' timestamps during ...

dovecot at dovecot.org dovecot at dovecot.org
Mon Jul 29 22:49:22 EEST 2013


details:   http://hg.dovecot.org/dovecot-2.2/rev/5ef62caea61b
changeset: 16621:5ef62caea61b
user:      Timo Sirainen <tss at iki.fi>
date:      Mon Jul 29 22:49:17 2013 +0300
description:
director: Update existing users' timestamps during handshake.

diffstat:

 src/director/director-connection.c |  17 +++++++++++++++++
 src/director/user-directory.c      |  37 +++++++++++++++++++++++++++++++++++++
 src/director/user-directory.h      |   3 +++
 3 files changed, 57 insertions(+), 0 deletions(-)

diffs (108 lines):

diff -r 366024103c09 -r 5ef62caea61b src/director/director-connection.c
--- a/src/director/director-connection.c	Mon Jul 29 22:19:03 2013 +0300
+++ b/src/director/director-connection.c	Mon Jul 29 22:49:17 2013 +0300
@@ -119,6 +119,7 @@
 	unsigned int synced:1;
 	unsigned int wrong_host:1;
 	unsigned int verifying_left:1;
+	unsigned int users_unsorted:1;
 };
 
 static void director_connection_disconnected(struct director_connection **conn);
@@ -578,6 +579,10 @@
 
 	(void)director_user_refresh(conn, username_hash, host,
 				    timestamp, weak, &user);
+	if (user->timestamp < timestamp) {
+		conn->users_unsorted = TRUE;
+		user->timestamp = timestamp;
+	}
 	return TRUE;
 }
 
@@ -975,6 +980,12 @@
 	unsigned int handshake_secs = time(NULL) - conn->created;
 	string_t *str;
 
+	if (conn->users_unsorted && conn->user_iter == NULL) {
+		/* we sent our user list before receiving remote's */
+		conn->users_unsorted = FALSE;
+		user_directory_sort(conn->dir->users);
+	}
+
 	if (handshake_secs >= DIRECTOR_HANDSHAKE_WARN_SECS || director_debug) {
 		str = t_str_new(128);
 		str_printfa(str, "director(%s): Handshake took %u secs, "
@@ -1437,6 +1448,12 @@
 	user_directory_iter_deinit(&conn->user_iter);
 	director_connection_send(conn, "DONE\n");
 
+	if (conn->users_unsorted && conn->handshake_received) {
+		/* we received remote's list of users before sending ours */
+		conn->users_unsorted = FALSE;
+		user_directory_sort(conn->dir->users);
+	}
+
 	ret = o_stream_flush(conn->output);
 	timeout_reset(conn->to_ping);
 	return ret;
diff -r 366024103c09 -r 5ef62caea61b src/director/user-directory.c
--- a/src/director/user-directory.c	Mon Jul 29 22:19:03 2013 +0300
+++ b/src/director/user-directory.c	Mon Jul 29 22:49:17 2013 +0300
@@ -210,6 +210,43 @@
 	}
 }
 
+static int user_timestamp_cmp(struct user *const *user1,
+			      struct user *const *user2)
+{
+	if ((*user1)->timestamp < (*user2)->timestamp)
+		return -1;
+	if ((*user1)->timestamp > (*user2)->timestamp)
+		return 1;
+	return 0;
+}
+
+void user_directory_sort(struct user_directory *dir)
+{
+	ARRAY(struct user *) users;
+	struct user *user, *const *userp;
+	unsigned int i, users_count = hash_table_count(dir->hash);
+
+	if (users_count == 0) {
+		i_assert(dir->head == NULL);
+		return;
+	}
+
+	/* place all users into array and sort it */
+	i_array_init(&users, users_count);
+	user = dir->head;
+	for (i = 0; i < users_count; i++, user = user->next)
+		array_append(&users, &user, 1);
+	i_assert(user == NULL);
+	array_sort(&users, user_timestamp_cmp);
+
+	/* recreate the linked list */
+	dir->head = dir->tail = NULL;
+	array_foreach(&users, userp)
+		DLLIST2_APPEND(&dir->head, &dir->tail, *userp);
+	i_assert(dir->head->timestamp <= dir->tail->timestamp);
+	array_free(&users);
+}
+
 unsigned int user_directory_get_username_hash(struct user_directory *dir,
 					      const char *username)
 {
diff -r 366024103c09 -r 5ef62caea61b src/director/user-directory.h
--- a/src/director/user-directory.h	Mon Jul 29 22:19:03 2013 +0300
+++ b/src/director/user-directory.h	Mon Jul 29 22:49:17 2013 +0300
@@ -64,6 +64,9 @@
 /* Remove all users that have pointers to given host */
 void user_directory_remove_host(struct user_directory *dir,
 				struct mail_host *host);
+/* Sort users based on the timestamp. This is called only after updating
+   timestamps based on remote director's user list after handshake. */
+void user_directory_sort(struct user_directory *dir);
 
 unsigned int user_directory_get_username_hash(struct user_directory *dir,
 					      const char *username);


More information about the dovecot-cvs mailing list