Example #1
0
/* Replace an entry from the hash table. The entry is returned, or NULL if it wasn't found */
void *ght_replace(ght_hash_table_t *p_ht,
		  void *p_entry_data,
		  unsigned int i_key_size, const void *p_key_data)
{
  ght_hash_entry_t *p_e;
  ght_hash_key_t key;
  ght_uint32_t l_key;
  void *p_old;

  DEBUG_ASSERT(p_ht);

  hk_fill(&key, i_key_size, p_key_data);

  l_key = get_hash_value(p_ht, &key) & p_ht->i_size_mask;

  /* Check that the first element in the list really is the first. */
  DEBUG_ASSERT( p_ht->pp_entries[l_key]?p_ht->pp_entries[l_key]->p_prev == NULL:1 );

  /* LOCK: p_ht->pp_entries[l_key] */
  p_e = search_in_bucket(p_ht, l_key, &key, (unsigned char)p_ht->i_heuristics);
  /* UNLOCK: p_ht->pp_entries[l_key] */

  if ( !p_e )
    return NULL;

  p_old = p_e->p_data;
  p_e->p_data = p_entry_data;

  return p_old;
}
Example #2
0
/* Remove an entry from the hash table. The removed entry, or NULL, is
   returned (and NOT free'd). */
void *ght_remove(ght_hash_table_t *p_ht,
		 unsigned int i_key_size, const void *p_key_data)
{
  ght_hash_entry_t *p_out;
  ght_hash_key_t key;
  ght_uint32_t l_key;
  void *p_ret=NULL;

  DEBUG_ASSERT(p_ht);

  hk_fill(&key, i_key_size, p_key_data);
  l_key = get_hash_value(p_ht, &key) & p_ht->i_size_mask;

  /* Check that the first element really is the first */
  DEBUG_ASSERT( (p_ht->pp_entries[l_key]?p_ht->pp_entries[l_key]->p_prev == NULL:1) );

  /* LOCK: p_ht->pp_entries[l_key] */
  p_out = search_in_bucket(p_ht, l_key, &key, 0);

  /* Link p_out out of the list. */
  if (p_out)
    {
      remove_from_chain(p_ht, l_key, p_out);

      /* This should ONLY be done for normal items (for now all items) */
      p_ht->i_items--;

      p_ht->p_nr[l_key]--;
      /* UNLOCK: p_ht->pp_entries[l_key] */
#if !defined(NDEBUG)
      p_out->p_next = NULL;
      p_out->p_prev = NULL;
#endif /* NDEBUG */

      p_ret = p_out->p_data;
      he_finalize(p_ht, p_out);
    }
  /* else: UNLOCK: p_ht->pp_entries[l_key] */

  return p_ret;
}
Example #3
0
/* Get an entry from the hash table. The entry is returned, or NULL if it wasn't found */
void *ght_get(ght_hash_table_t *p_ht,
	      unsigned int i_key_size, const void *p_key_data)
{
  ght_hash_entry_t *p_e;
  ght_hash_key_t key;
  ght_uint32_t l_key;

  assert(p_ht);

  hk_fill(&key, i_key_size, p_key_data);

  l_key = get_hash_value(p_ht, &key) & p_ht->i_size_mask;

  /* Check that the first element in the list really is the first. */
  assert( p_ht->pp_entries[l_key]?p_ht->pp_entries[l_key]->p_prev == NULL:1 );

  /* LOCK: p_ht->pp_entries[l_key] */
  p_e = search_in_bucket(p_ht, l_key, &key, p_ht->i_heuristics);
  /* UNLOCK: p_ht->pp_entries[l_key] */

  return (p_e?p_e->p_data:NULL);
}
Example #4
0
/* Insert an entry into the hash table */
int ght_insert(ght_hash_table_t *p_ht,
	       void *p_entry_data,
	       unsigned int i_key_size, const void *p_key_data)
{
  ght_hash_entry_t *p_entry;
  ght_uint32_t l_key;
  ght_hash_key_t key;

  DEBUG_ASSERT(p_ht);

  hk_fill(&key, i_key_size, p_key_data);
  l_key = get_hash_value(p_ht, &key) & p_ht->i_size_mask;
  if (search_in_bucket(p_ht, l_key, &key, 0))
    {
      /* Don't insert if the key is already present. */
      return -1;
    }
  p_entry = he_create(p_ht, p_entry_data, i_key_size, p_key_data);
  if (!(p_entry))
    {
      return -2;
    }

  /* Rehash if the number of items inserted is too high. */
  if (p_ht->i_automatic_rehash && p_ht->i_items > 2*p_ht->i_size)
    {
      ght_rehash(p_ht, 2*p_ht->i_size);
      /* Recalculate l_key after ght_rehash has updated i_size_mask */
      l_key = get_hash_value(p_ht, &key) & p_ht->i_size_mask;
    }

  /* Place the entry first in the list. */
  p_entry->p_next = p_ht->pp_entries[l_key];
  p_entry->p_prev = NULL;
  if (p_ht->pp_entries[l_key])
    {
      p_ht->pp_entries[l_key]->p_prev = p_entry;
    }
  p_ht->pp_entries[l_key] = p_entry;

  /* If this is a limited bucket hash table, potentially remove the last item */
  if (p_ht->bucket_limit != 0 &&
      p_ht->p_nr[l_key] >= p_ht->bucket_limit)
    {
      ght_hash_entry_t *p;

      /* Loop through entries until the last
       *
       * FIXME: Better with a pointer to the last entry
       */
      for (p = p_ht->pp_entries[l_key];
	   p->p_next != NULL;
	   p = p->p_next);

      DEBUG_ASSERT(p && p->p_next == NULL);

      remove_from_chain(p_ht, l_key, p); /* To allow it to be reinserted in fn_bucket_free */
      p_ht->fn_bucket_free(p->p_data, p->key.p_key);

      he_finalize(p_ht, p);
    }
  else
    {
      p_ht->p_nr[l_key]++;

      DEBUG_ASSERT( p_ht->pp_entries[l_key]?p_ht->pp_entries[l_key]->p_prev == NULL:1 );

      p_ht->i_items++;
    }

  if (p_ht->p_oldest == NULL)
    {
      p_ht->p_oldest = p_entry;
    }
  p_entry->p_older = p_ht->p_newest;

  if (p_ht->p_newest != NULL)
    {
      p_ht->p_newest->p_newer = p_entry;
    }

  p_ht->p_newest = p_entry;

  return 0;
}