changeset 14987:77213cdc8d7f

director: Update existing users' timestamps during handshake.
author Timo Sirainen <tss@iki.fi>
date Mon, 29 Jul 2013 22:48:36 +0300
parents 15537f882a0b
children c9d7586d01ae
files src/director/director-connection.c src/director/user-directory.c src/director/user-directory.h
diffstat 3 files changed, 57 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/src/director/director-connection.c	Mon Jul 29 22:18:34 2013 +0300
+++ b/src/director/director-connection.c	Mon Jul 29 22:48:36 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 @@
 	}
 
 	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, "
@@ -1440,6 +1451,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;
--- a/src/director/user-directory.c	Mon Jul 29 22:18:34 2013 +0300
+++ b/src/director/user-directory.c	Mon Jul 29 22:48:36 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_DEFINE(users, struct user *);
+	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)
 {
--- a/src/director/user-directory.h	Mon Jul 29 22:18:34 2013 +0300
+++ b/src/director/user-directory.h	Mon Jul 29 22:48:36 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);