unsigned int pos;
};
+enum hash_table_operation{
+ HASH_TABLE_OP_INSERT,
+ HASH_TABLE_OP_UPDATE,
+ HASH_TABLE_OP_RESIZE
+};
+
static bool hash_table_resize(struct hash_table *table, bool grow);
void hash_table_create(struct hash_table **table_r, pool_t node_pool,
return TRUE;
}
-static struct hash_node * ATTR_NOWARN_UNUSED_RESULT
+static void
hash_table_insert_node(struct hash_table *table, void *key, void *value,
- bool check_existing)
+ enum hash_table_operation opcode)
{
struct hash_node *node, *prev;
unsigned int hash;
+ bool check_existing = TRUE;
i_assert(key != NULL);
+ if(opcode == HASH_TABLE_OP_RESIZE)
+ check_existing = FALSE;
hash = table->hash_cb(key);
if (check_existing && table->removed_count > 0) {
/* there may be holes, have to check everything */
node = hash_table_lookup_node(table, key, hash);
if (node != NULL) {
+ i_assert(opcode == HASH_TABLE_OP_UPDATE);
node->value = value;
- return node;
+ return;
}
- check_existing = FALSE;
+ check_existing = FALSE;
}
/* a) primary node */
node->key = key;
node->value = value;
- return node;
+ return;
}
-
if (check_existing) {
if (table->key_compare_cb(node->key, key) == 0) {
+ i_assert(opcode == HASH_TABLE_OP_UPDATE);
node->value = value;
- return node;
+ return;
}
}
if (check_existing) {
if (table->key_compare_cb(node->key, key) == 0) {
+ i_assert(opcode == HASH_TABLE_OP_UPDATE);
node->value = value;
- return node;
+ return;
}
}
-
prev = node;
node = node->next;
}
if (node == NULL) {
if (table->frozen == 0 && hash_table_resize(table, TRUE)) {
/* resized table, try again */
- return hash_table_insert_node(table, key, value, FALSE);
+ hash_table_insert_node(table, key, value, HASH_TABLE_OP_RESIZE);
+ return;
}
if (table->free_nodes == NULL)
node->value = value;
table->nodes_count++;
- return node;
}
void hash_table_insert(struct hash_table *table, void *key, void *value)
{
- struct hash_node *node;
-
- node = hash_table_insert_node(table, key, value, TRUE);
- node->key = key;
+ hash_table_insert_node(table, key, value, HASH_TABLE_OP_INSERT);
}
void hash_table_update(struct hash_table *table, void *key, void *value)
{
- hash_table_insert_node(table, key, value, TRUE);
+ hash_table_insert_node(table, key, value, HASH_TABLE_OP_UPDATE);
}
static void
node = &old_nodes[i];
if (node->key != NULL) {
hash_table_insert_node(table, node->key,
- node->value, FALSE);
+ node->value, HASH_TABLE_OP_RESIZE);
}
for (node = node->next; node != NULL; node = next) {
if (node->key != NULL) {
hash_table_insert_node(table, node->key,
- node->value, FALSE);
+ node->value, HASH_TABLE_OP_RESIZE);
}
free_node(table, node);
}
hash_table_lookup_full((table)._table, lookup_key, orig_key_r, value_r)
#endif
-/* Insert/update node in hash table. The difference is that hash_table_insert()
- replaces the key in table to given one, while hash_table_update() doesnt. */
+/* Suppose to insert a new key-value node to the hash table.
+ If the key already exists, assert-crash. */
void hash_table_insert(struct hash_table *table, void *key, void *value);
+/* If the key doesn't exists, do the exact same as hash_table_insert()
+ If the key already exists, preserve the original key and update only the value.*/
void hash_table_update(struct hash_table *table, void *key, void *value);
#define hash_table_insert(table, key, value) \
hash_table_insert((table)._table, \