]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
Changed hash_foreach() to iterator.
authorTimo Sirainen <tss@iki.fi>
Wed, 3 Dec 2003 00:40:21 +0000 (02:40 +0200)
committerTimo Sirainen <tss@iki.fi>
Wed, 3 Dec 2003 00:40:21 +0000 (02:40 +0200)
--HG--
branch : HEAD

12 files changed:
src/auth/auth-client-connection.c
src/auth/db-ldap.c
src/imap-login/client.c
src/imap/imap-thread.c
src/lib-index/maildir/maildir-sync.c
src/lib/hash.c
src/lib/hash.h
src/login-common/ssl-proxy-gnutls.c
src/login-common/ssl-proxy-openssl.c
src/master/auth-process.c
src/master/login-process.c
src/pop3-login/client.c

index a0a07944a3775dbb1bc445d86015a11a40fc3de2..f51179025f98ca04cf3b550de5ab32b649d4b912 100644 (file)
@@ -207,14 +207,6 @@ auth_client_connection_create(struct auth_master_connection *master, int fd)
        return conn;
 }
 
-static void auth_request_hash_destroy(void *key __attr_unused__, void *value,
-                                     void *context __attr_unused__)
-{
-       struct auth_request *auth_request = value;
-
-       auth_request->conn = NULL;
-}
-
 void auth_client_connection_destroy(struct auth_client_connection *conn)
 {
        struct auth_client_connection **pos;
@@ -244,10 +236,19 @@ void auth_client_connection_destroy(struct auth_client_connection *conn)
 
 static void auth_client_connection_unref(struct auth_client_connection *conn)
 {
+       struct hash_iterate_context *iter;
+       void *key, *value;
+
        if (--conn->refcount > 0)
                return;
 
-       hash_foreach(conn->auth_requests, auth_request_hash_destroy, NULL);
+       iter = hash_iterate_init(conn->auth_requests);
+       while (hash_iterate(iter, &key, &value)) {
+               struct auth_request *auth_request = value;
+
+               auth_request->conn = NULL;
+       }
+       hash_iterate_deinit(iter);
        hash_destroy(conn->auth_requests);
 
        i_stream_unref(conn->input);
@@ -256,20 +257,32 @@ static void auth_client_connection_unref(struct auth_client_connection *conn)
        pool_unref(conn->pool);
 }
 
-static void auth_request_hash_timeout_check(void *key __attr_unused__,
-                                           void *value, void *context)
+static void
+auth_client_connection_check_timeouts(struct auth_client_connection *conn)
 {
-       struct auth_client_connection *conn = context;
-       struct auth_request *auth_request = value;
-
-       if (auth_request->created + AUTH_REQUEST_TIMEOUT < ioloop_time) {
-               i_warning("Login process has too old (%us) requests, "
-                         "killing it.",
-                         (unsigned int)(ioloop_time - auth_request->created));
+       struct hash_iterate_context *iter;
+       void *key, *value;
+       unsigned int secs;
+       int destroy = FALSE;
+
+       iter = hash_iterate_init(conn->auth_requests);
+       while (hash_iterate(iter, &key, &value)) {
+               struct auth_request *auth_request = value;
+
+               if (auth_request->created + AUTH_REQUEST_TIMEOUT < ioloop_time) {
+                       secs = (unsigned int) (ioloop_time -
+                                              auth_request->created);
+                       i_warning("Login process has too old (%us) requests, "
+                                 "killing it.", secs);
+
+                       destroy = TRUE;
+                       break;
+               }
+       }
+       hash_iterate_deinit(iter);
 
+       if (destroy)
                auth_client_connection_destroy(conn);
-               hash_foreach_stop();
-       }
 }
 
 static void request_timeout(void *context __attr_unused__)
@@ -279,11 +292,7 @@ static void request_timeout(void *context __attr_unused__)
 
        for (conn = master->clients; conn != NULL; conn = next) {
                next = conn->next;
-
-               conn->refcount++;
-               hash_foreach(conn->auth_requests,
-                            auth_request_hash_timeout_check, conn);
-               auth_client_connection_unref(conn);
+               auth_client_connection_check_timeouts(conn);
        }
 }
 
index fbf17d05f3067c33e28ca0bf0e31e47d6b1236a6..14d13b514eaabe028a7bc1f1bb6e87bbec35ed7f 100644 (file)
@@ -226,19 +226,19 @@ static int ldap_conn_open(struct ldap_connection *conn)
        return TRUE;
 }
 
-static void hash_ldap_request_destroy(void *key __attr_unused__,
-                                     void *value, void *context)
+static void ldap_conn_close(struct ldap_connection *conn)
 {
-       struct ldap_request *request = value;
-       struct ldap_connection *conn = context;
+       struct hash_iterate_context *iter;
+       void *key, *value;
 
-       request->callback(conn, request, NULL);
-       i_free(request);
-}
+       iter = hash_iterate_init(conn->requests);
+       while (hash_iterate(iter, &key, &value)) {
+               struct ldap_request *request = value;
 
-static void ldap_conn_close(struct ldap_connection *conn)
-{
-       hash_foreach(conn->requests, hash_ldap_request_destroy, conn);
+               request->callback(conn, request, NULL);
+               i_free(request);
+       }
+       hash_iterate_deinit(iter);
        hash_clear(conn->requests, FALSE);
 
        conn->connected = FALSE;
index 156c4c232459aa60ddfa283b88e5c812a004902c..bc1f11e5058f6b001cf7bd1ebfa912e3ba471830 100644 (file)
@@ -309,45 +309,40 @@ void client_input(void *context)
                o_stream_flush(client->output);
 }
 
-static void client_hash_destroy_oldest(void *key, void *value __attr_unused__,
-                                      void *context)
-{
-       struct imap_client *client = key;
-       struct imap_client *const *destroy_clients;
-       buffer_t *destroy_buf = context;
-       size_t i, count;
-
-       destroy_clients = buffer_get_data(destroy_buf, &count);
-       count /= sizeof(struct imap_client *);
-
-       for (i = 0; i < count; i++) {
-               if (destroy_clients[i]->created > client->created) {
-                       buffer_insert(destroy_buf,
-                                     i * sizeof(struct imap_client *),
-                                     &client, sizeof(struct imap_client *));
-                       break;
-               }
-       }
-}
-
 static void client_destroy_oldest(void)
 {
-       struct imap_client *const *destroy_clients;
-       buffer_t *destroy_buf;
-       size_t i, count;
+       struct hash_iterate_context *iter;
+       void *key, *value;
+       struct imap_client *destroy_buf[CLIENT_DESTROY_OLDEST_COUNT];
+       int i;
 
        /* find the oldest clients and put them to destroy-buffer */
-       destroy_buf = buffer_create_static_hard(pool_datastack_create(),
-                                               sizeof(struct imap_client *) *
-                                               CLIENT_DESTROY_OLDEST_COUNT);
-       hash_foreach(clients, client_hash_destroy_oldest, destroy_buf);
+       memset(destroy_buf, 0, sizeof(destroy_buf));
+
+       iter = hash_iterate_init(clients);
+       while (hash_iterate(iter, &key, &value)) {
+               struct imap_client *client = key;
+
+               for (i = 0; i < CLIENT_DESTROY_OLDEST_COUNT; i++) {
+                       if (destroy_buf[i] == NULL ||
+                           destroy_buf[i]->created > client->created) {
+                               /* @UNSAFE */
+                               memmove(destroy_buf+i+1, destroy_buf+i,
+                                       sizeof(destroy_buf) -
+                                       (i+1) * sizeof(struct imap_client *));
+                               destroy_buf[i] = client;
+                               break;
+                       }
+               }
+       }
+       hash_iterate_deinit(iter);
 
        /* then kill them */
-       destroy_clients = buffer_get_data(destroy_buf, &count);
-       count /= sizeof(struct imap_client *);
+       for (i = 0; i < CLIENT_DESTROY_OLDEST_COUNT; i++) {
+               if (destroy_buf[i] == NULL)
+                       break;
 
-       for (i = 0; i < count; i++) {
-               client_destroy(destroy_clients[i],
+               client_destroy(destroy_buf[i],
                               "Disconnected: Connection queue full");
        }
 }
@@ -474,11 +469,8 @@ void client_syslog(struct imap_client *client, const char *text)
        i_info("%s [%s]", text, addr);
 }
 
-static void client_hash_check_idle(void *key, void *value __attr_unused__,
-                                  void *context __attr_unused__)
+static void client_check_idle(struct imap_client *client)
 {
-       struct imap_client *client = key;
-
        if (ioloop_time - client->last_input >= CLIENT_LOGIN_IDLE_TIMEOUT) {
                client_send_line(client, "* BYE Disconnected for inactivity.");
                client_destroy(client, "Disconnected: Inactivity");
@@ -487,7 +479,16 @@ static void client_hash_check_idle(void *key, void *value __attr_unused__,
 
 static void idle_timeout(void *context __attr_unused__)
 {
-       hash_foreach(clients, client_hash_check_idle, NULL);
+       struct hash_iterate_context *iter;
+       void *key, *value;
+
+       iter = hash_iterate_init(clients);
+       while (hash_iterate(iter, &key, &value)) {
+               struct imap_client *client = key;
+
+               client_check_idle(client);
+       }
+       hash_iterate_deinit(iter);
 }
 
 unsigned int clients_get_count(void)
@@ -495,31 +496,35 @@ unsigned int clients_get_count(void)
        return hash_size(clients);
 }
 
-static void client_hash_check_io(void *key, void *value __attr_unused__,
-                                void *context __attr_unused__)
+void clients_notify_auth_connected(void)
 {
-       struct imap_client *client = key;
+       struct hash_iterate_context *iter;
+       void *key, *value;
+
+       iter = hash_iterate_init(clients);
+       while (hash_iterate(iter, &key, &value)) {
+               struct imap_client *client = key;
 
-       if (client->input_blocked) {
-               client->input_blocked = FALSE;
-               client_input(client);
+               if (client->input_blocked) {
+                       client->input_blocked = FALSE;
+                       client_input(client);
+               }
        }
+       hash_iterate_deinit(iter);
 }
 
-void clients_notify_auth_connected(void)
+void clients_destroy_all(void)
 {
-       hash_foreach(clients, client_hash_check_io, NULL);
-}
+       struct hash_iterate_context *iter;
+       void *key, *value;
 
-static void client_hash_destroy(void *key, void *value __attr_unused__,
-                               void *context __attr_unused__)
-{
-       client_destroy(key, NULL);
-}
+       iter = hash_iterate_init(clients);
+       while (hash_iterate(iter, &key, &value)) {
+               struct imap_client *client = key;
 
-void clients_destroy_all(void)
-{
-       hash_foreach(clients, client_hash_destroy, NULL);
+               client_destroy(client, NULL);
+       }
+       hash_iterate_deinit(iter);
 }
 
 void clients_init(void)
index 87a468d2bde4ef01011f37378042ef6008cb0999..a9891d13f2d247cfb37dede3ce0fcae7cf0e00b3 100644 (file)
@@ -898,21 +898,21 @@ static void send_roots(struct thread_context *ctx)
        (void)o_stream_send(ctx->output, str_data(str), str_len(str));
 }
 
-static void save_root_cb(void *key __attr_unused__, void *value, void *context)
-{
-       struct thread_context *ctx = context;
-       struct node *node = value;
-
-       if (node->parent == NULL)
-               add_root(ctx, node);
-}
-
 static void mail_thread_finish(struct thread_context *ctx)
 {
+       struct hash_iterate_context *iter;
+       void *key, *value;
        struct node *node;
 
        /* (2) save root nodes and drop the msgids */
-       hash_foreach(ctx->msgid_hash, save_root_cb, ctx);
+       iter = hash_iterate_init(ctx->msgid_hash);
+       while (hash_iterate(iter, &key, &value)) {
+               struct node *node = value;
+
+               if (node->parent == NULL)
+                       add_root(ctx, node);
+       }
+       hash_iterate_deinit(iter);
 
        /* drop the memory allocated for message-IDs and msgid_hash,
           reuse their memory for base subjects */
index 95456d9ee75f316f80563e6c000eb5b4b9f3d0bb..24342b5afb82c175b366ae0d0f03ef5241ea3b9c 100644 (file)
@@ -361,15 +361,6 @@ static int maildir_sync_open_uidlist(struct maildir_sync_context *ctx)
        return TRUE;
 }
 
-static void uidlist_hash_get_filenames(void *key, void *value, void *context)
-{
-       buffer_t *buf = context;
-       struct maildir_hash_rec *hash_rec = value;
-
-       if (ACTION(hash_rec) == MAILDIR_FILE_ACTION_NEW)
-               buffer_append(buf, (const void *) &key, sizeof(const char *));
-}
-
 static int maildir_time_cmp(const void *p1, const void *p2)
 {
        const char *s1 = *((const char **) p1);
@@ -393,6 +384,8 @@ static int maildir_time_cmp(const void *p1, const void *p2)
 
 static int maildir_full_sync_finish_new_mails(struct maildir_sync_context *ctx)
 {
+       struct hash_iterate_context *iter;
+       void *key, *value;
        const char *dir, **new_files;
        buffer_t *buf;
        unsigned int i;
@@ -404,7 +397,16 @@ static int maildir_full_sync_finish_new_mails(struct maildir_sync_context *ctx)
           so we should get them to same order as they were created. */
        buf = buffer_create_static_hard(ctx->pool,
                                        ctx->new_count * sizeof(const char *));
-       hash_foreach(ctx->files, uidlist_hash_get_filenames, buf);
+       iter = hash_iterate_init(ctx->files);
+       while (hash_iterate(iter, &key, &value)) {
+               struct maildir_hash_rec *hash_rec = value;
+
+               if (ACTION(hash_rec) == MAILDIR_FILE_ACTION_NEW) {
+                       buffer_append(buf, (const void *) &key,
+                                     sizeof(const char *));
+               }
+       }
+       hash_iterate_deinit(iter);
        i_assert(buffer_get_used_size(buf) ==
                 ctx->new_count * sizeof(const char *));
 
@@ -781,33 +783,11 @@ static int maildir_fix_duplicate(struct mail_index *index,
        return ret;
 }
 
-static void maildir_sync_hash_fix_allocs(void *key, void *value, void *context)
-{
-        struct maildir_sync_context *ctx = context;
-       struct maildir_hash_rec *hash_rec = value;
-
-       switch (ACTION(hash_rec)) {
-       case MAILDIR_FILE_ACTION_NONE:
-               hash_remove(ctx->files, key);
-               break;
-       case MAILDIR_FILE_ACTION_EXPUNGE:
-               if (hash_rec->action & MAILDIR_FILE_FLAG_ALLOCED) {
-                       /* we're getting here because our recently
-                          inserted node is traversed as well */
-                       break;
-               }
-
-               hash_rec->action |= MAILDIR_FILE_FLAG_ALLOCED;
-               hash_insert(ctx->files, p_strdup(ctx->pool, key), value);
-               break;
-       default:
-               break;
-       }
-}
-
 static int maildir_full_sync_dir(struct maildir_sync_context *ctx,
                                 int new_dir, DIR *dirp, struct dirent *d)
 {
+       struct hash_iterate_context *iter;
+       void *key, *value;
        struct maildir_hash_rec *hash_rec;
        void *orig_key, *orig_value;
        int newflag;
@@ -864,7 +844,30 @@ static int maildir_full_sync_dir(struct maildir_sync_context *ctx,
        /* records that are left to hash must not have any (filename) pointers
           to cache file. So remove none actions, and p_strdup() expunge
           actions. */
-       hash_foreach(ctx->files, maildir_sync_hash_fix_allocs, ctx);
+       iter = hash_iterate_init(ctx->files);
+       while (hash_iterate(iter, &key, &value)) {
+               struct maildir_hash_rec *hash_rec = value;
+
+               switch (ACTION(hash_rec)) {
+               case MAILDIR_FILE_ACTION_NONE:
+                       hash_remove(ctx->files, key);
+                       break;
+               case MAILDIR_FILE_ACTION_EXPUNGE:
+                       if (hash_rec->action & MAILDIR_FILE_FLAG_ALLOCED) {
+                               /* we're getting here because our recently
+                                  inserted node is traversed as well */
+                               break;
+                       }
+
+                       hash_rec->action |= MAILDIR_FILE_FLAG_ALLOCED;
+                       hash_insert(ctx->files,
+                                   p_strdup(ctx->pool, key), value);
+                       break;
+               default:
+                       break;
+               }
+       }
+       hash_iterate_deinit(iter);
 
        return TRUE;
 }
index 233884ceae9270caf8064c3fa8bf1e2035deb7ab..3512189015c7e8ffbbce6b893c473ba453a4a513 100644 (file)
@@ -32,8 +32,6 @@ struct hash_table {
 
 static int hash_resize(struct hash_table *table, int grow);
 
-static int foreach_stop;
-
 static int direct_cmp(const void *p1, const void *p2)
 {
        return p1 == p2 ? 0 : 1;
@@ -321,37 +319,65 @@ size_t hash_size(struct hash_table *table)
        return table->nodes_count;
 }
 
-void hash_foreach(struct hash_table *table, hash_foreach_callback_t *callback,
-                 void *context)
+struct hash_iterate_context {
+       struct hash_table *table;
+       struct hash_node *next;
+       size_t pos;
+};
+
+struct hash_iterate_context *hash_iterate_init(struct hash_table *table)
 {
-       struct hash_node *node;
-       size_t i;
+       struct hash_iterate_context *ctx;
 
        hash_freeze(table);
 
-       foreach_stop = FALSE;
-
-       for (i = 0; i < table->size; i++) {
-               node = &table->nodes[i];
+       ctx = i_new(struct hash_iterate_context, 1);
+       ctx->table = table;
+       ctx->next = &table->nodes[0];
+       return ctx;
+}
 
-               do {
-                       if (node->key != NULL) {
-                               callback(node->key, node->value, context);
-                               if (foreach_stop) {
-                                       table->frozen--;
-                                       return;
-                               }
+static struct hash_node *hash_iterate_next(struct hash_iterate_context *ctx,
+                                          struct hash_node *node)
+{
+       do {
+               if (node == NULL) {
+                       if (++ctx->pos == ctx->table->size) {
+                               ctx->pos--;
+                               return NULL;
                        }
+                       node = &ctx->table->nodes[ctx->pos];
+               } else {
                        node = node->next;
-               } while (node != NULL);
+               }
+       } while (node->key == NULL);
+
+       return node;
+}
+
+int hash_iterate(struct hash_iterate_context *ctx,
+                void **key_r, void **value_r)
+{
+       struct hash_node *node;
+
+       node = ctx->next;
+       if (node != NULL && node->key == NULL)
+               node = hash_iterate_next(ctx, node);
+       if (node == NULL) {
+               *key_r = *value_r = NULL;
+               return FALSE;
        }
+       *key_r = node->key;
+       *value_r = node->value;
 
-       hash_thaw(table);
+       ctx->next = hash_iterate_next(ctx, node);
+       return TRUE;
 }
 
-void hash_foreach_stop(void)
+void hash_iterate_deinit(struct hash_iterate_context *ctx)
 {
-        foreach_stop = TRUE;
+       hash_thaw(ctx->table);
+       i_free(ctx);
 }
 
 void hash_freeze(struct hash_table *table)
index 89faf88a7ec9244e02047ac14a145aee1dc2825a..b1f179c19609f431dbaafada83a95389e48a5782 100644 (file)
@@ -5,7 +5,6 @@
 typedef unsigned int hash_callback_t(const void *p);
 /* Returns 0 if the pointers are equal. */
 typedef int hash_cmp_callback_t(const void *p1, const void *p2);
-typedef void hash_foreach_callback_t(void *key, void *value, void *context);
 
 /* Create a new hash table. If initial_size is 0, the default value is used.
    If hash_cb or key_compare_cb is NULL, direct hashing/comparing is used.
@@ -35,13 +34,13 @@ void hash_update(struct hash_table *table, void *key, void *value);
 void hash_remove(struct hash_table *table, const void *key);
 size_t hash_size(struct hash_table *table);
 
-/* Calls the given function for each node in hash table. You may safely
-   call hash_*() functions inside your function, but if you add any
-   new nodes, they may or may not be called for in this foreach loop. */
-void hash_foreach(struct hash_table *table,
-                 hash_foreach_callback_t *callback, void *context);
-/* Stop the active hash_foreach() loop */
-void hash_foreach_stop(void);
+/* Iterates through all nodes in hash table. You may safely call hash_*()
+   functions while iterating, but if you add any new nodes, they may or may
+   not be called for in this iteration. */
+struct hash_iterate_context *hash_iterate_init(struct hash_table *table);
+int hash_iterate(struct hash_iterate_context *ctx,
+                void **key_r, void **value_r);
+void hash_iterate_deinit(struct hash_iterate_context *ctx);
 
 /* Hash table isn't resized, and removed nodes aren't removed from
    the list while hash table is freezed. Supports nesting. */
index 009724dd540fe8a2d063d6a2b2e8bd2a71d081c1..4bea406d1509824991dbacad185c6255604472d4 100644 (file)
@@ -527,18 +527,18 @@ void ssl_proxy_init(void)
        ssl_initialized = TRUE;
 }
 
-static void ssl_proxy_destroy_hash(void *key __attr_unused__, void *value,
-                                  void *context __attr_unused__)
-{
-       ssl_proxy_destroy(value);
-}
-
 void ssl_proxy_deinit(void)
 {
+       struct hash_iterate_context *iter;
+       void *key, *value;
+
        if (!ssl_initialized)
                return;
 
-       hash_foreach(ssl_proxies, ssl_proxy_destroy_hash, NULL);
+       iter = hash_iterate_init(ssl_proxies);
+       while (hash_iterate(iter, &key, &value))
+               ssl_proxy_destroy(value);
+       hash_iterate_deinit(iter);
        hash_destroy(ssl_proxies);
 
        gnutls_certificate_free_cred(x509_cred);
index 9f0b1bb99a7d8b632d7aefc063eb909dcdc35b6e..5ee0ff6d4ff18402f5b8033675cac3a9900f63da 100644 (file)
@@ -451,18 +451,18 @@ void ssl_proxy_init(void)
        ssl_initialized = TRUE;
 }
 
-static void ssl_proxy_destroy_hash(void *key __attr_unused__, void *value,
-                                  void *context __attr_unused__)
-{
-       ssl_proxy_unref(value);
-}
-
 void ssl_proxy_deinit(void)
 {
+       struct hash_iterate_context *iter;
+       void *key, *value;
+
        if (!ssl_initialized)
                return;
 
-       hash_foreach(ssl_proxies, ssl_proxy_destroy_hash, NULL);
+       iter = hash_iterate_init(ssl_proxies);
+       while (hash_iterate(iter, &key, &value))
+               ssl_proxy_destroy(value);
+       hash_iterate_deinit(iter);
        hash_destroy(ssl_proxies);
 
        SSL_CTX_free(ssl_ctx);
index e01350bcbac6289302fe7f817901b3b33937cbbf..2ab2737a23f3f718e0791b9c1747c55eb080e384 100644 (file)
@@ -216,14 +216,10 @@ auth_process_new(pid_t pid, int fd, struct auth_process_group *group)
        return p;
 }
 
-static void request_hash_destroy(void *key __attr_unused__,
-                                void *value, void *context __attr_unused__)
-{
-       auth_master_callback(NULL, NULL, value);
-}
-
 static void auth_process_destroy(struct auth_process *p)
 {
+       struct hash_iterate_context *iter;
+       void *key, *value;
        struct auth_process **pos;
 
        if (!p->initialized && io_loop_is_running(ioloop)) {
@@ -239,7 +235,10 @@ static void auth_process_destroy(struct auth_process *p)
        }
        p->group->process_count--;
 
-       hash_foreach(p->requests, request_hash_destroy, NULL);
+       iter = hash_iterate_init(p->requests);
+       while (hash_iterate(iter, &key, &value))
+               auth_master_callback(NULL, NULL, value);
+       hash_iterate_deinit(iter);
        hash_destroy(p->requests);
 
        i_stream_unref(p->input);
index 0ff2ee7377f325ceec3a3c49d54a2bacb501566e..52e1a25a73e0a3a98d7aebb7b5b6c5102f690d2b 100644 (file)
@@ -506,15 +506,15 @@ void login_process_abormal_exit(pid_t pid)
                p->group->wanted_processes_count = 0;
 }
 
-static void login_hash_destroy(void *key __attr_unused__, void *value,
-                              void *context __attr_unused__)
-{
-       login_process_destroy(value);
-}
-
 void login_processes_destroy_all(void)
 {
-       hash_foreach(processes, login_hash_destroy, NULL);
+       struct hash_iterate_context *iter;
+       void *key, *value;
+
+       iter = hash_iterate_init(processes);
+       while (hash_iterate(iter, &key, &value))
+               login_process_destroy(value);
+       hash_iterate_deinit(iter);
 
        while (login_groups != NULL) {
                struct login_group *group = login_groups;
index 568babe19902b92ebc11d1e8177b1face646a74b..e0b998457822b28afdb4554583050a03e89c9350 100644 (file)
@@ -189,45 +189,40 @@ void client_input(void *context)
                o_stream_flush(client->output);
 }
 
-static void client_hash_destroy_oldest(void *key, void *value __attr_unused__,
-                                      void *context)
-{
-       struct pop3_client *client = key;
-       struct pop3_client *const *destroy_clients;
-       buffer_t *destroy_buf = context;
-       size_t i, count;
-
-       destroy_clients = buffer_get_data(destroy_buf, &count);
-       count /= sizeof(struct pop3_client *);
-
-       for (i = 0; i < count; i++) {
-               if (destroy_clients[i]->created > client->created) {
-                       buffer_insert(destroy_buf,
-                                     i * sizeof(struct pop3_client *),
-                                     &client, sizeof(struct pop3_client *));
-                       break;
-               }
-       }
-}
-
 static void client_destroy_oldest(void)
 {
-       struct pop3_client *const *destroy_clients;
-       buffer_t *destroy_buf;
-       size_t i, count;
+       struct hash_iterate_context *iter;
+       void *key, *value;
+       struct pop3_client *destroy_buf[CLIENT_DESTROY_OLDEST_COUNT];
+       int i;
 
        /* find the oldest clients and put them to destroy-buffer */
-       destroy_buf = buffer_create_static_hard(pool_datastack_create(),
-                                               sizeof(struct pop3_client *) *
-                                               CLIENT_DESTROY_OLDEST_COUNT);
-       hash_foreach(clients, client_hash_destroy_oldest, destroy_buf);
+       memset(destroy_buf, 0, sizeof(destroy_buf));
+
+       iter = hash_iterate_init(clients);
+       while (hash_iterate(iter, &key, &value)) {
+               struct pop3_client *client = key;
+
+               for (i = 0; i < CLIENT_DESTROY_OLDEST_COUNT; i++) {
+                       if (destroy_buf[i] == NULL ||
+                           destroy_buf[i]->created > client->created) {
+                               /* @UNSAFE */
+                               memmove(destroy_buf+i+1, destroy_buf+i,
+                                       sizeof(destroy_buf) -
+                                       (i+1) * sizeof(struct pop3_client *));
+                               destroy_buf[i] = client;
+                               break;
+                       }
+               }
+       }
+       hash_iterate_deinit(iter);
 
        /* then kill them */
-       destroy_clients = buffer_get_data(destroy_buf, &count);
-       count /= sizeof(struct pop3_client *);
+       for (i = 0; i < CLIENT_DESTROY_OLDEST_COUNT; i++) {
+               if (destroy_buf[i] == NULL)
+                       break;
 
-       for (i = 0; i < count; i++) {
-               client_destroy(destroy_clients[i],
+               client_destroy(destroy_buf[i],
                               "Disconnected: Connection queue full");
        }
 }
@@ -344,18 +339,24 @@ void client_syslog(struct pop3_client *client, const char *text)
        i_info("%s [%s]", text, addr);
 }
 
-static void client_hash_check_idle(void *key, void *value __attr_unused__,
-                                  void *context __attr_unused__)
+static void client_check_idle(struct pop3_client *client)
 {
-       struct pop3_client *client = key;
-
        if (ioloop_time - client->last_input >= CLIENT_LOGIN_IDLE_TIMEOUT)
                client_destroy(client, "Disconnected: Inactivity");
 }
 
 static void idle_timeout(void *context __attr_unused__)
 {
-       hash_foreach(clients, client_hash_check_idle, NULL);
+       struct hash_iterate_context *iter;
+       void *key, *value;
+
+       iter = hash_iterate_init(clients);
+       while (hash_iterate(iter, &key, &value)) {
+               struct pop3_client *client = key;
+
+               client_check_idle(client);
+       }
+       hash_iterate_deinit(iter);
 }
 
 unsigned int clients_get_count(void)
@@ -363,31 +364,35 @@ unsigned int clients_get_count(void)
        return hash_size(clients);
 }
 
-static void client_hash_check_io(void *key, void *value __attr_unused__,
-                                void *context __attr_unused__)
+void clients_notify_auth_connected(void)
 {
-       struct pop3_client *client = key;
+       struct hash_iterate_context *iter;
+       void *key, *value;
+
+       iter = hash_iterate_init(clients);
+       while (hash_iterate(iter, &key, &value)) {
+               struct pop3_client *client = key;
 
-       if (client->input_blocked) {
-               client->input_blocked = FALSE;
-               client_input(client);
+               if (client->input_blocked) {
+                       client->input_blocked = FALSE;
+                       client_input(client);
+               }
        }
+       hash_iterate_deinit(iter);
 }
 
-void clients_notify_auth_connected(void)
+void clients_destroy_all(void)
 {
-       hash_foreach(clients, client_hash_check_io, NULL);
-}
+       struct hash_iterate_context *iter;
+       void *key, *value;
 
-static void client_hash_destroy(void *key, void *value __attr_unused__,
-                               void *context __attr_unused__)
-{
-       client_destroy(key, NULL);
-}
+       iter = hash_iterate_init(clients);
+       while (hash_iterate(iter, &key, &value)) {
+               struct pop3_client *client = key;
 
-void clients_destroy_all(void)
-{
-       hash_foreach(clients, client_hash_destroy, NULL);
+               client_destroy(client, NULL);
+       }
+       hash_iterate_deinit(iter);
 }
 
 void clients_init(void)