/* Hash Functions * Resize the hash to minumim for this number of entries */ DirectResult fusion_hash_resize (FusionHash *hash) { FusionHashNode **new_nodes; FusionHashNode *node; FusionHashNode *next; unsigned int hash_val; int new_size; int i; D_MAGIC_ASSERT( hash, FusionHash ); new_size = spaced_primes_closest (hash->nnodes); if (new_size > FUSION_HASH_MAX_SIZE ) new_size = FUSION_HASH_MAX_SIZE; if (new_size < FUSION_HASH_MIN_SIZE) new_size = FUSION_HASH_MIN_SIZE; if (hash->local) new_nodes = D_CALLOC (new_size, sizeof(FusionHashNode*)); else new_nodes = SHCALLOC (hash->pool, new_size, sizeof(FusionHashNode*)); if (!new_nodes) return hash->local?DFB_NOSYSTEMMEMORY:DFB_NOSHAREDMEMORY; for (i = 0; i < hash->size; i++) for (node = hash->nodes[i]; node; node = next) { next = node->next; /*TODO We could also optimize pointer hashing*/ if (hash->key_type == HASH_STRING ) { unsigned int h; const signed char *p = node->key; HASH_STR(h, p) hash_val = h % new_size; } else hash_val = ((unsigned long)node->key) % new_size; node->next = new_nodes[hash_val]; new_nodes[hash_val] = node; } if (hash->local) D_FREE(hash->nodes); else SHFREE(hash->pool, hash->nodes); hash->nodes = new_nodes; hash->size = new_size; return true; }
/* * fluid_hashtable_resize: * @hashtable: our #fluid_hashtable_t * * Resizes the hash table to the optimal size based on the number of * nodes currently held. If you call this function then a resize will * occur, even if one does not need to occur. Use * fluid_hashtable_maybe_resize() instead. */ static void fluid_hashtable_resize (fluid_hashtable_t *hashtable) { fluid_hashnode_t **new_nodes; fluid_hashnode_t *node; fluid_hashnode_t *next; unsigned int hash_val; int new_size; int i; new_size = spaced_primes_closest (hashtable->nnodes); new_size = (new_size < HASH_TABLE_MIN_SIZE) ? HASH_TABLE_MIN_SIZE : ((new_size > HASH_TABLE_MAX_SIZE) ? HASH_TABLE_MAX_SIZE : new_size); new_nodes = FLUID_ARRAY (fluid_hashnode_t *, new_size); if (!new_nodes) { FLUID_LOG (FLUID_ERR, "Out of memory"); return; } FLUID_MEMSET (new_nodes, 0, new_size * sizeof (fluid_hashnode_t *)); for (i = 0; i < hashtable->size; i++) for (node = hashtable->nodes[i]; node; node = next) { next = node->next; hash_val = node->key_hash % new_size; node->next = new_nodes[hash_val]; new_nodes[hash_val] = node; } FLUID_FREE (hashtable->nodes); hashtable->nodes = new_nodes; hashtable->size = new_size; }
DirectResult direct_hash_insert( DirectHash *hash, unsigned long key, void *value ) { int pos; DirectHashElement *element; D_MAGIC_ASSERT( hash, DirectHash ); D_ASSERT( hash->size > 0 ); D_ASSERT( value != NULL ); if (!hash->Elements) { if (hash->disable_debugging_alloc) hash->Elements = direct_calloc( hash->size, sizeof(DirectHashElement) ); else hash->Elements = D_CALLOC( hash->size, sizeof(DirectHashElement) ); if (!hash->Elements) return D_OOM(); } /* Need to resize the hash table? */ if ((hash->count + hash->removed) > hash->size / 2) { int i, size; DirectHashElement *elements; size = spaced_primes_closest( hash->size ); if (size > DIRECT_HASH_MAX_SIZE) size = DIRECT_HASH_MAX_SIZE; if (size < DIRECT_HASH_MIN_SIZE) size = DIRECT_HASH_MIN_SIZE; D_DEBUG_AT( Direct_Hash, "Resizing from %d to %d... (count %d, removed %d)\n", hash->size, size, hash->count, hash->removed ); if (hash->disable_debugging_alloc) elements = direct_calloc( size, sizeof(DirectHashElement) ); else elements = D_CALLOC( size, sizeof(DirectHashElement) ); if (!elements) { D_WARN( "out of memory" ); return DR_NOLOCALMEMORY; } for (i=0; i<hash->size; i++) { DirectHashElement *element = &hash->Elements[i]; DirectHashElement *insertElement; if (element->value && element->value != DIRECT_HASH_ELEMENT_REMOVED) { pos = element->key % size; insertElement = &elements[pos]; while (insertElement->value && insertElement->value != DIRECT_HASH_ELEMENT_REMOVED) { if (++pos == size) pos = 0; insertElement = &elements[pos]; } elements[pos] = *element; } } if (hash->disable_debugging_alloc) direct_free( hash->Elements ); else D_FREE( hash->Elements ); hash->size = size; hash->Elements = elements; hash->removed = 0; } pos = key % hash->size; D_DEBUG_AT( Direct_Hash, "Attempting to insert key 0x%08lx at position %d...\n", key, pos ); element = &hash->Elements[pos]; while (element->value && element->value != DIRECT_HASH_ELEMENT_REMOVED) { if (element->key == key) { D_BUG( "key already exists" ); return DR_BUG; } if (++pos == hash->size) pos = 0; element = &hash->Elements[pos]; } if (element->value == DIRECT_HASH_ELEMENT_REMOVED) hash->removed--; element->key = key; element->value = value; hash->count++; D_DEBUG_AT( Direct_Hash, "...inserted at %d, new count = %d, removed = %d, size = %d, key = 0x%08lx.\n", pos, hash->count, hash->removed, hash->size, key ); return DR_OK; }