Exemple #1
0
/**
 * 
 * HashTable_Del: Remove a (key,val) couple from the hashtable.
 *
 * Remove a (key,val) couple from the hashtable. The parameter buffkey contains the key which describes the object to be removed
 * from the hash table. 
 *
 * @param ht the hashtable to be used.
 * @param buffkey a pointeur to an object of type hash_buffer_t which describe the key location in memory.
 * @param pusedbuffkeydata the key data buffer that was associated with this entry. Not considered if equal to NULL.
 *
 * @return HASHTABLE_SUCCESS if successfull\n.
 * @return HASHTABLE_ERROR_NO_SUCH_KEY is the key was not found.
 *
 * @see HashTable_Set
 * @see HashTable_Init
 * @see HashTable_Get
 */
int HashTable_Del(hash_table_t * ht, hash_buffer_t * buffkey,
                  hash_buffer_t * p_usedbuffkey, hash_buffer_t * p_usedbuffdata)
{
  unsigned int hashval;
  struct rbt_node *pn;
  int rbt_value = 0;
  struct rbt_head *tete_rbt;
  hash_data_t *pdata = NULL;
  int rc = 0;

  /* Sanity check */
  if(ht == NULL || buffkey == NULL)
    return HASHTABLE_ERROR_INVALID_ARGUMENT;

  /* Find the RB Tree to be processed */
  hashval = (*(ht->parameter.hash_func_key)) (&ht->parameter, buffkey);

  /* Find the entry to be deleted */
  rbt_value = (*(ht->parameter.hash_func_rbt)) (&ht->parameter, buffkey);

  /* acquire mutex */
  P_w(&(ht->array_lock[hashval]));

  /* We didn't find anything */
  if((rc = Key_Locate(ht, buffkey, hashval, rbt_value, &pn)) != HASHTABLE_SUCCESS)
    {
      ht->stat_dynamic[hashval].notfound.nb_del += 1;
      V_w(&(ht->array_lock[hashval]));
      return rc;
    }

  pdata = (hash_data_t *) RBT_OPAQ(pn);

  /* Return the key buffer back to the end user if pusedbuffkey isn't NULL */
  if(p_usedbuffkey != NULL)
    *p_usedbuffkey = pdata->buffkey;

  if(p_usedbuffdata != NULL)
    *p_usedbuffdata = pdata->buffval;

  /* Key was found */
  tete_rbt = &(ht->array_rbt[hashval]);
  RBT_UNLINK(tete_rbt, pn);

  /* the key was located, the deletion is done */
  ht->stat_dynamic[hashval].nb_entries -= 1;

  /* put back the pdata buffer to pool */
  RELEASE_PREALLOC(pdata, ht->pdata_prealloc[hashval], next_alloc);

  /* Put the node back in the table of preallocated nodes (it could be reused) */
  RELEASE_PREALLOC(pn, ht->node_prealloc[hashval], next);

  ht->stat_dynamic[hashval].ok.nb_del += 1;

  /* release mutex */
  V_w(&(ht->array_lock[hashval]));

  return HASHTABLE_SUCCESS;
}                               /*  HashTable_Del */
Exemple #2
0
/**
 * @brief Remove and free all (key,val) couples from the hash store
 *
 * This function removes all (key,val) couples from the hashtable and
 * frees the stored data using the supplied function
 *
 * @param[in,out] ht        The hashtable to be cleared of all entries
 * @param[in]     free_func The function with which to free the contents
 *                          of each entry
 *
 * @return HASHTABLE_SUCCESS or errors
 */
hash_error_t
hashtable_delall(struct hash_table *ht,
		 int (*free_func)(struct gsh_buffdesc,
				  struct gsh_buffdesc))
{
	/* Successive partition numbers */
	uint32_t index = 0;

	for (index = 0; index < ht->parameter.index_size; index++) {
		/* The root of each successive partition */
		struct rbt_head *root = &ht->partitions[index].rbt;
		/* Pointer to node in tree for removal */
		struct rbt_node *cursor = NULL;

		PTHREAD_RWLOCK_wrlock(&ht->partitions[index].lock);

		/* Continue until there are no more entries in the red-black
		   tree */
		while ((cursor = RBT_LEFTMOST(root)) != NULL) {
			/* Pointer to the key and value descriptors
			   for each successive entry */
			struct hash_data *data = NULL;
			/* Aliased poitner to node, for freeing
			   buffers after removal from tree */
			struct rbt_node *holder = cursor;
			/* Buffer descriptor for key, as stored */
			struct gsh_buffdesc key;
			/* Buffer descriptor for value, as stored */
			struct gsh_buffdesc val;
			/* Return code from the free function.  Zero
			   on failure */
			int rc = 0;

			RBT_UNLINK(root, cursor);
			data = RBT_OPAQ(holder);

			key = data->key;
			val = data->val;

			pool_free(ht->data_pool, data);
			pool_free(ht->node_pool, holder);
			--ht->partitions[index].count;
			rc = free_func(key, val);

			if (rc == 0) {
				PTHREAD_RWLOCK_unlock(&ht->partitions[index].
						      lock);
				return HASHTABLE_ERROR_DELALL_FAIL;
			}
		}
		PTHREAD_RWLOCK_unlock(&ht->partitions[index].lock);
	}

	return HASHTABLE_SUCCESS;
}
Exemple #3
0
void hashtable_deletelatched(struct hash_table *ht,
			     const struct gsh_buffdesc *key,
			     struct hash_latch *latch,
			     struct gsh_buffdesc *stored_key,
			     struct gsh_buffdesc *stored_val)
{
	/* The pair of buffer descriptors comprising the stored entry */
	struct hash_data *data = NULL;
	/* Its partition */
	struct hash_partition *partition = &ht->partitions[latch->index];

	if (!latch->locator)
		return;

	data = RBT_OPAQ(latch->locator);

	if (isDebug(COMPONENT_HASHTABLE)
	    && isFullDebug(ht->parameter.ht_log_component)) {
		char dispkey[HASHTABLE_DISPLAY_STRLEN];
		char dispval[HASHTABLE_DISPLAY_STRLEN];

		if (ht->parameter.key_to_str != NULL)
			ht->parameter.key_to_str(&data->key, dispkey);
		else
			dispkey[0] = '\0';

		if (ht->parameter.val_to_str != NULL)
			ht->parameter.val_to_str(&data->val, dispval);
		else
			dispval[0] = '\0';

		LogFullDebug(ht->parameter.ht_log_component,
			     "Delete %s Key=%p {%s} Value=%p {%s} index=%"
			     PRIu32 " rbt_hash=%" PRIu64 " was removed",
			     ht->parameter.ht_name, data->key.addr, dispkey,
			     data->val.addr, dispval, latch->index,
			     latch->rbt_hash);
	}

	if (stored_key)
		*stored_key = data->key;

	if (stored_val)
		*stored_val = data->val;

	/* Clear cache */
	if (partition->cache) {
		uint32_t offset = cache_offsetof(ht, latch->rbt_hash);
		struct rbt_node *cnode = partition->cache[offset];

		if (cnode) {
#if COMPARE_BEFORE_CLEAR_CACHE
			struct hash_data *data1 = RBT_OPAQ(cnode);
			struct hash_data *data2 = RBT_OPAQ(latch->locator);

			if (ht->parameter.
			    compare_key(&(data1->key), &(data2->key))
			    == 0) {
				LogFullDebug(COMPONENT_HASHTABLE_CACHE,
					     "hash clear index %d slot %" PRIu64
					     latch->index, offset);
				partition->cache[offset] = NULL;
			}
#else
			LogFullDebug(COMPONENT_HASHTABLE_CACHE,
				     "hash clear slot %d", offset);
			partition->cache[offset] = NULL;
#endif
		}
	}

	/* Now remove the entry */
	RBT_UNLINK(&partition->rbt, latch->locator);
	pool_free(ht->data_pool, data);
	pool_free(ht->node_pool, latch->locator);
	--ht->partitions[latch->index].count;
}