]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
director: Delay sorting users until there are no more user iterators
authorTimo Sirainen <timo.sirainen@dovecot.fi>
Sat, 25 Nov 2017 08:05:27 +0000 (10:05 +0200)
committerTimo Sirainen <timo.sirainen@dovecot.fi>
Sun, 26 Nov 2017 11:04:54 +0000 (13:04 +0200)
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

src/director/user-directory.c

index 2d892a409449961d88d929f937c75f02f34c68bc..05b05bb27febf3b9aa856a7a98289b4cbc418b89 100644 (file)
@@ -35,6 +35,8 @@ struct user_directory {
        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 @@ void user_directory_sort(struct user_directory *dir)
        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 @@ void user_directory_iter_deinit(struct user_directory_iter **_iter)
                        break;
                }
        }
+       if (array_count(&iter->dir->iters) == 0 && iter->dir->sort_pending)
+               user_directory_sort(iter->dir);
        i_free(iter);
 }