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);
(void)director_user_refresh(conn, username_hash, host,
timestamp, weak, &user);
+ if (user->timestamp < timestamp) {
+ conn->users_unsorted = TRUE;
+ user->timestamp = timestamp;
+ }
return TRUE;
}
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, "
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;
}
}
+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)
{
/* 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);