Exemplo n.º 1
0
/**
 * 
 * Key_Locate: Locate a buffer key in the hash table, as a rbt node.
 * 
 * This function is for internal use only 
 *
 * @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 hashval hash value associated with the key (in order to avoid computing it a second time)
 * @param rbt_value rbt value associated with the key (in order to avoid computing it a second time)
 * @param ppnode if successfull,will point to the pointer to the rbt node to be used 
 *
 * @return HASHTABLE_SUCCESS if successfull\n.
 * @return HASHTABLE_NO_SUCH_KEY if key was not found 
 *
 */
static int Key_Locate(hash_table_t * ht, hash_buffer_t * buffkey, unsigned int hashval,
                      int rbt_value, struct rbt_node **ppnode)
{
  struct rbt_head *tete_rbt;
  hash_data_t *pdata = NULL;
  struct rbt_node *pn;
  int found = 0;

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

  /* Find the head of the rbt */
  tete_rbt = &(ht->array_rbt[hashval]);

  /* I get the node with this value that is located on the left (first with this value in the rbtree) */
  RBT_FIND_LEFT(tete_rbt, pn, rbt_value);

  /* Find was successfull ? */
  if(pn == NULL)
    return HASHTABLE_ERROR_NO_SUCH_KEY;

  /* For each entry with this value, compare the key value */
  while((pn != 0) && (RBT_VALUE(pn) == rbt_value))
    {
      pdata = (hash_data_t *) RBT_OPAQ(pn);
      /* Verify the key value : this function returns 0 if key are indentical */
      if(!ht->parameter.compare_key(buffkey, &(pdata->buffkey)))
        {
          found = 1;
          break;                /* exit the while loop */
        }
      RBT_INCREMENT(pn);
    }                           /* while */

  /* We didn't find anything */
  if(!found)
    return HASHTABLE_ERROR_NO_SUCH_KEY;

  /* Key was found */
  *ppnode = pn;

  return HASHTABLE_SUCCESS;
}                               /* Key_Locate */
Exemplo n.º 2
0
/**
 * @brief Locate a key within a partition
 *
 * This function traverses the red-black tree within a hash table
 * partition and returns, if one exists, a pointer to a node matching
 * the supplied key.
 *
 * @param[in]  ht      The hashtable to be used
 * @param[in]  key     The key to look up
 * @param[in]  index   Index into RBT array
 * @param[in]  rbthash Hash in red-black tree
 * @param[out] node    On success, the found node, NULL otherwise
 *
 * @retval HASHTABLE_SUCCESS if successfull
 * @retval HASHTABLE_NO_SUCH_KEY if key was not found
 */
static hash_error_t
key_locate(struct hash_table *ht, const struct gsh_buffdesc *key,
	   uint32_t index, uint64_t rbthash, struct rbt_node **node)
{
	/* The current partition */
	struct hash_partition *partition = &(ht->partitions[index]);

	/* The root of the red black tree matching this index */
	struct rbt_head *root = NULL;

	/* A pair of buffer descriptors locating key and value for this
	   entry */
	struct hash_data *data = NULL;

	/* The node in the red-black tree currently being traversed */
	struct rbt_node *cursor = NULL;

	/* true if we have located the key */
	int found = false;

	*node = NULL;

	if (partition->cache) {
		void **cache_slot = (void **)
		    &(partition->cache[cache_offsetof(ht, rbthash)]);
		cursor = atomic_fetch_voidptr(cache_slot);
		LogFullDebug(COMPONENT_HASHTABLE_CACHE,
			     "hash %s index %" PRIu32 " slot %d",
			     (cursor) ? "hit" : "miss", index,
			     cache_offsetof(ht, rbthash));
		if (cursor) {
			data = RBT_OPAQ(cursor);
			if (ht->parameter.
			    compare_key((struct gsh_buffdesc *)key,
					&(data->key)) == 0) {
				goto out;
			}
		}
	}

	root = &(ht->partitions[index].rbt);

	/* The lefmost occurrence of the value is the one from which we
	   may start iteration to visit all nodes containing a value. */
	RBT_FIND_LEFT(root, cursor, rbthash);

	if (cursor == NULL) {
		if (isFullDebug(COMPONENT_HASHTABLE)
		    && isFullDebug(ht->parameter.ht_log_component))
			LogFullDebug(ht->parameter.ht_log_component,
				     "Key not found: rbthash = %" PRIu64,
				     rbthash);
		return HASHTABLE_ERROR_NO_SUCH_KEY;
	}

	while ((cursor != NULL) && (RBT_VALUE(cursor) == rbthash)) {
		data = RBT_OPAQ(cursor);
		if (ht->parameter.
		    compare_key((struct gsh_buffdesc *)key,
				&(data->key)) == 0) {
			if (partition->cache) {
				void **cache_slot = (void **)
				    &(partition->
				      cache[cache_offsetof(ht, rbthash)]);
				atomic_store_voidptr(cache_slot, cursor);
			}
			found = true;
			break;
		}
		RBT_INCREMENT(cursor);
	}

	if (!found) {
		if (isFullDebug(COMPONENT_HASHTABLE)
		    && isFullDebug(ht->parameter.ht_log_component))
			LogFullDebug(ht->parameter.ht_log_component,
				     "Matching hash found, but no matching key.");
		return HASHTABLE_ERROR_NO_SUCH_KEY;
	}

 out:
	*node = cursor;

	return HASHTABLE_SUCCESS;
}