Mercurial > dovecot > original-hg > dovecot-1.2
changeset 957:c1a97fc30d1c HEAD
hash_resize() leaked memory, hash_insert/update didn't update value for
existing nodes.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Mon, 13 Jan 2003 22:00:23 +0200 |
parents | 26cafa3dc09c |
children | 2c7a2d90e0cb |
files | src/lib/hash.c |
diffstat | 1 files changed, 29 insertions(+), 36 deletions(-) [+] |
line wrap: on
line diff
--- a/src/lib/hash.c Sun Jan 12 01:49:45 2003 +0200 +++ b/src/lib/hash.c Mon Jan 13 22:00:23 2003 +0200 @@ -50,10 +50,7 @@ pool_t table_pool, node_pool; int frozen; - size_t nodes_count, removed_count; -#ifdef DEBUG - size_t collisions_count; -#endif + size_t initial_size, nodes_count, removed_count; size_t size; struct hash_node *nodes; @@ -90,18 +87,20 @@ table = p_new(table_pool, struct hash_table, 1); table->table_pool = table_pool; - table->node_pool = node_pool; - table->size = I_MAX(primes_closest(initial_size), - HASH_TABLE_MIN_SIZE); + table->node_pool = node_pool; + table->initial_size = initial_size; table->hash_cb = hash_cb != NULL ? hash_cb : direct_hash; table->key_compare_cb = key_compare_cb == NULL ? direct_cmp : key_compare_cb; + + table->size = I_MAX(primes_closest(initial_size), + HASH_TABLE_MIN_SIZE); + table->nodes = p_new(table_pool, struct hash_node, table->size); table->collisions_size = I_MAX(table->size / 10, COLLISIONS_MIN_SIZE); table->collisions = p_new(table_pool, struct collision_node, table->collisions_size); - return table; } @@ -166,9 +165,6 @@ table->nodes_count = 0; table->removed_count = 0; -#ifdef DEBUG - table->collisions_count = 0; -#endif } static struct hash_node * @@ -247,8 +243,10 @@ if (check_existing && table->removed_count > 0) { /* there may be holes, have to check everything */ node = hash_lookup_node(table, key, hash); - if (node != NULL) + if (node != NULL) { + node->value = value; return node; + } check_existing = FALSE; } @@ -264,8 +262,10 @@ } if (check_existing) { - if (table->key_compare_cb(node->key, key) == 0) + if (table->key_compare_cb(node->key, key) == 0) { + node->value = value; return node; + } } /* b) collisions list */ @@ -277,8 +277,10 @@ break; if (check_existing) { - if (table->key_compare_cb(cnode->node.key, key) == 0) - return node; + if (table->key_compare_cb(cnode->node.key, key) == 0) { + cnode->node.value = value; + return &cnode->node; + } } prev = cnode; @@ -305,9 +307,6 @@ cnode->node.key = key; cnode->node.value = value;; -#ifdef DEBUG - table->collisions_count++; -#endif table->nodes_count++; return &cnode->node; } @@ -340,9 +339,6 @@ if (next->node.key == NULL) { cnode->next = next->next; free_cnode(table, next); -#ifdef DEBUG - table->collisions_count--; -#endif } } @@ -359,9 +355,6 @@ memcpy(&croot->node, &next->node, sizeof(croot->node)); croot->next = next->next; free_cnode(table, next); -#ifdef DEBUG - table->collisions_count--; -#endif } /* see if node in primary table was deleted */ @@ -371,9 +364,6 @@ if (node->key == NULL) { memcpy(node, &croot->node, sizeof(*node)); croot->node.key = NULL; -#ifdef DEBUG - table->collisions_count--; -#endif } } while (croot->node.key == NULL); } @@ -484,14 +474,14 @@ static int hash_resize(struct hash_table *table) { struct hash_node *old_nodes; - struct collision_node *old_cnodes, *cnode; + struct collision_node *old_cnodes, *cnode, *next; size_t old_size, old_csize, i; float nodes_per_list; nodes_per_list = (float) table->nodes_count / (float) table->size; - if ((nodes_per_list > 0.3 || table->size <= HASH_TABLE_MIN_SIZE) && + if ((nodes_per_list > 0.3 || table->size <= table->initial_size) && (nodes_per_list < 2.0)) - return FALSE; + return FALSE; /* recreate primary table */ old_size = table->size; @@ -511,9 +501,6 @@ table->nodes_count = 0; table->removed_count = 0; -#ifdef DEBUG - table->collisions_count = 0; -#endif table->frozen++; @@ -528,13 +515,19 @@ for (i = 0; i < old_csize; i++) { cnode = &old_cnodes[i]; - do { + if (cnode->node.key != NULL) { + hash_insert_node(table, cnode->node.key, + cnode->node.value, FALSE); + } + + for (cnode = cnode->next; cnode != NULL; cnode = next) { + next = cnode->next; if (cnode->node.key != NULL) { hash_insert_node(table, cnode->node.key, cnode->node.value, FALSE); } - cnode = cnode->next; - } while (cnode != NULL); + free_cnode(table, cnode); + } } table->frozen--;