예제 #1
0
파일: hash.c 프로젝트: maxupunk/DIR685
/* 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;
}
예제 #2
0
/*
 * 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;
}
예제 #3
0
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;
}