Mercurial > dovecot > core-2.2
comparison src/director/user-directory.c @ 22633:9284bdc3c5c5
director: Don't recreate timeout on every user lookup
Recreate it only when the timeout should change.
author | Timo Sirainen <timo.sirainen@dovecot.fi> |
---|---|
date | Sat, 04 Nov 2017 01:34:02 +0200 |
parents | fd12e91c6718 |
children | a96fa917ced1 |
comparison
equal
deleted
inserted
replaced
22632:fd12e91c6718 | 22633:9284bdc3c5c5 |
---|---|
33 unsigned int timeout_secs; | 33 unsigned int timeout_secs; |
34 /* If user's expire time is less than this many seconds away, | 34 /* If user's expire time is less than this many seconds away, |
35 don't assume that other directors haven't yet expired it */ | 35 don't assume that other directors haven't yet expired it */ |
36 unsigned int user_near_expiring_secs; | 36 unsigned int user_near_expiring_secs; |
37 struct timeout *to_expire; | 37 struct timeout *to_expire; |
38 time_t to_expire_timestamp; | |
38 }; | 39 }; |
39 | 40 |
40 static void user_move_iters(struct user_directory *dir, struct user *user) | 41 static void user_move_iters(struct user_directory *dir, struct user *user) |
41 { | 42 { |
42 struct user_directory_iter *const *iterp; | 43 struct user_directory_iter *const *iterp; |
64 i_free(user); | 65 i_free(user); |
65 } | 66 } |
66 | 67 |
67 static bool user_directory_user_has_connections(struct user_directory *dir, | 68 static bool user_directory_user_has_connections(struct user_directory *dir, |
68 struct user *user, | 69 struct user *user, |
69 unsigned int *retry_secs_r) | 70 time_t *expire_timestamp_r) |
70 { | 71 { |
71 time_t expire_timestamp = user->timestamp + dir->timeout_secs; | 72 time_t expire_timestamp = user->timestamp + dir->timeout_secs; |
72 | 73 |
73 if (expire_timestamp > ioloop_time) { | 74 if (expire_timestamp > ioloop_time) { |
74 *retry_secs_r = expire_timestamp - ioloop_time; | 75 *expire_timestamp_r = expire_timestamp; |
75 return TRUE; | 76 return TRUE; |
76 } | 77 } |
77 | 78 |
78 if (USER_IS_BEING_KILLED(user)) { | 79 if (USER_IS_BEING_KILLED(user)) { |
79 /* don't free this user until the kill is finished */ | 80 /* don't free this user until the kill is finished */ |
80 *retry_secs_r = USER_BEING_KILLED_EXPIRE_RETRY_SECS; | 81 *expire_timestamp_r = ioloop_time + |
82 USER_BEING_KILLED_EXPIRE_RETRY_SECS; | |
81 return TRUE; | 83 return TRUE; |
82 } | 84 } |
83 | 85 |
84 if (user->weak) { | 86 if (user->weak) { |
85 if (expire_timestamp + USER_NEAR_EXPIRING_MAX > ioloop_time) { | 87 if (expire_timestamp + USER_NEAR_EXPIRING_MAX > ioloop_time) { |
86 *retry_secs_r = expire_timestamp + | 88 *expire_timestamp_r = expire_timestamp + |
87 USER_NEAR_EXPIRING_MAX - ioloop_time; | 89 USER_NEAR_EXPIRING_MAX; |
88 return TRUE; | 90 return TRUE; |
89 } | 91 } |
90 | 92 |
91 i_warning("User %u weakness appears to be stuck, removing it", | 93 i_warning("User %u weakness appears to be stuck, removing it", |
92 user->username_hash); | 94 user->username_hash); |
94 return FALSE; | 96 return FALSE; |
95 } | 97 } |
96 | 98 |
97 static void user_directory_drop_expired(struct user_directory *dir) | 99 static void user_directory_drop_expired(struct user_directory *dir) |
98 { | 100 { |
99 unsigned int retry_secs = 0; | 101 time_t expire_timestamp = 0; |
100 | 102 |
101 while (dir->head != NULL && | 103 while (dir->head != NULL && |
102 !user_directory_user_has_connections(dir, dir->head, &retry_secs)) | 104 !user_directory_user_has_connections(dir, dir->head, &expire_timestamp)) { |
103 user_free(dir, dir->head); | 105 user_free(dir, dir->head); |
104 if (dir->to_expire != NULL) | 106 expire_timestamp = 0; |
105 timeout_remove(&dir->to_expire); | 107 } |
106 if (retry_secs > 0) { | 108 i_assert(expire_timestamp > ioloop_time || expire_timestamp == 0); |
107 dir->to_expire = timeout_add(retry_secs * 1000, | 109 |
108 user_directory_drop_expired, dir); | 110 if (expire_timestamp != dir->to_expire_timestamp) { |
111 if (dir->to_expire != NULL) | |
112 timeout_remove(&dir->to_expire); | |
113 if (expire_timestamp != 0) { | |
114 struct timeval tv = { .tv_sec = expire_timestamp }; | |
115 dir->to_expire_timestamp = tv.tv_sec; | |
116 dir->to_expire = timeout_add_absolute(&tv, | |
117 user_directory_drop_expired, dir); | |
118 } | |
109 } | 119 } |
110 } | 120 } |
111 | 121 |
112 unsigned int user_directory_count(struct user_directory *dir) | 122 unsigned int user_directory_count(struct user_directory *dir) |
113 { | 123 { |
116 | 126 |
117 struct user *user_directory_lookup(struct user_directory *dir, | 127 struct user *user_directory_lookup(struct user_directory *dir, |
118 unsigned int username_hash) | 128 unsigned int username_hash) |
119 { | 129 { |
120 struct user *user; | 130 struct user *user; |
121 unsigned int retry_secs; | 131 time_t expire_timestamp; |
122 | 132 |
123 user_directory_drop_expired(dir); | 133 user_directory_drop_expired(dir); |
124 user = hash_table_lookup(dir->hash, POINTER_CAST(username_hash)); | 134 user = hash_table_lookup(dir->hash, POINTER_CAST(username_hash)); |
125 if (user != NULL && !user_directory_user_has_connections(dir, user, &retry_secs)) { | 135 if (user != NULL && !user_directory_user_has_connections(dir, user, &expire_timestamp)) { |
126 user_free(dir, user); | 136 user_free(dir, user); |
127 user = NULL; | 137 user = NULL; |
128 } | 138 } |
129 return user; | 139 return user; |
130 } | 140 } |
206 user); | 216 user); |
207 } | 217 } |
208 } | 218 } |
209 | 219 |
210 if (dir->to_expire == NULL) { | 220 if (dir->to_expire == NULL) { |
211 dir->to_expire = timeout_add(dir->timeout_secs * 1000, | 221 struct timeval tv = { .tv_sec = ioloop_time + dir->timeout_secs }; |
212 user_directory_drop_expired, dir); | 222 dir->to_expire_timestamp = tv.tv_sec; |
223 dir->to_expire = timeout_add_absolute(&tv, user_directory_drop_expired, dir); | |
213 } | 224 } |
214 dir->prev_insert_pos = user; | 225 dir->prev_insert_pos = user; |
215 hash_table_insert(dir->hash, POINTER_CAST(user->username_hash), user); | 226 hash_table_insert(dir->hash, POINTER_CAST(user->username_hash), user); |
216 return user; | 227 return user; |
217 } | 228 } |