changeset 22675:d689d7d99b4f

director: Delay sorting users until there are no more user iterators This shouldn't have normally happened. Only when an outgoing handshake was going on at the same time as a) another outgoing handshake was going on, or b) doveadm was doing HOST-RESET-USERS
author Timo Sirainen <timo.sirainen@dovecot.fi>
date Sat, 25 Nov 2017 10:05:27 +0200
parents af1a9f282179
children c9549bea9106
files src/director/user-directory.c
diffstat 1 files changed, 14 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/src/director/user-directory.c	Sun Nov 26 01:31:08 2017 +0200
+++ b/src/director/user-directory.c	Sat Nov 25 10:05:27 2017 +0200
@@ -35,6 +35,8 @@
 	unsigned int user_near_expiring_secs;
 	struct timeout *to_expire;
 	time_t to_expire_timestamp;
+
+	bool sort_pending;
 };
 
 static void user_move_iters(struct user_directory *dir, struct user *user)
@@ -199,11 +201,21 @@
 	struct user *user, *const *userp;
 	unsigned int i, users_count = hash_table_count(dir->hash);
 
+	dir->sort_pending = FALSE;
+
 	if (users_count == 0) {
 		i_assert(dir->head == NULL);
 		return;
 	}
 
+	if (array_count(&dir->iters) > 0) {
+		/* We can't sort the directory while there are iterators
+		   or they'll skip users. Do the sort after there are no more
+		   iterators. */
+		dir->sort_pending = TRUE;
+		return;
+	}
+
 	/* place all users into array and sort it */
 	i_array_init(&users, users_count);
 	user = dir->head;
@@ -318,5 +330,7 @@
 			break;
 		}
 	}
+	if (array_count(&iter->dir->iters) == 0 && iter->dir->sort_pending)
+		user_directory_sort(iter->dir);
 	i_free(iter);
 }