Mercurial > dovecot > original-hg > dovecot-2.1
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);