Exemplo n.º 1
0
hash_error_t
hashtable_setlatched(struct hash_table *ht,
		     struct gsh_buffdesc *key,
		     struct gsh_buffdesc *val,
		     struct hash_latch *latch, int overwrite,
		     struct gsh_buffdesc *stored_key,
		     struct gsh_buffdesc *stored_val)
{
	/* Stored error return */
	hash_error_t rc = HASHTABLE_SUCCESS;
	/* The pair of buffer descriptors locating both key and value
	   for this object, what actually gets stored. */
	struct hash_data *descriptors = NULL;
	/* Node giving the location to insert new node */
	struct rbt_node *locator = NULL;
	/* New node for the case of non-overwrite */
	struct rbt_node *mutator = NULL;

	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(key, dispkey);
		else
			dispkey[0] = '\0';

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

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

	/* In the case of collision */
	if (latch->locator) {
		if (!overwrite) {
			rc = HASHTABLE_ERROR_KEY_ALREADY_EXISTS;
			goto out;
		}

		descriptors = 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(&descriptors->key,
							 dispkey);
			else
				dispkey[0] = '\0';

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

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

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

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

		descriptors->key = *key;
		descriptors->val = *val;
		rc = HASHTABLE_OVERWRITTEN;
		goto out;
	}

	/* We have no collision, so go about creating and inserting a new
	   node. */

	RBT_FIND(&ht->partitions[latch->index].rbt, locator, latch->rbt_hash);

	mutator = pool_alloc(ht->node_pool);

	descriptors = pool_alloc(ht->data_pool);

	RBT_OPAQ(mutator) = descriptors;
	RBT_VALUE(mutator) = latch->rbt_hash;
	RBT_INSERT(&ht->partitions[latch->index].rbt, mutator, locator);

	descriptors->key.addr = key->addr;
	descriptors->key.len = key->len;

	descriptors->val.addr = val->addr;
	descriptors->val.len = val->len;

	/* Only in the non-overwrite case */
	++ht->partitions[latch->index].count;

	rc = HASHTABLE_SUCCESS;

 out:
	hashtable_releaselatched(ht, latch);

	if (rc != HASHTABLE_SUCCESS && isDebug(COMPONENT_HASHTABLE)
	    && isFullDebug(ht->parameter.ht_log_component))
		LogFullDebug(ht->parameter.ht_log_component,
			     "Set %s returning failure %s",
			     ht->parameter.ht_name, hash_table_err_to_str(rc));

	return rc;
}
Exemplo n.º 2
0
/**
 * 
 * HashTable_Test_And_Set: set a pair (key,value) into the Hash Table.
 *
 * Set a (key,val) couple in the hashtable .
 *
 * @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 buffval a pointeur to an object of type hash_buffer_t which describe the value location in memory.
 * @param how a switch to tell if the entry is to be tested or overwritten or not
 *
 * @return HASHTABLE_SUCCESS if successfull\n.
 * @return HASHTABLE_INSERT_MALLOC_ERROR if an error occured during the insertion process.
 *
 * @see HashTable_Get
 * @see HashTable_Init
 * @see HashTable_Del
 */
int HashTable_Test_And_Set(hash_table_t * ht, hash_buffer_t * buffkey,
                           hash_buffer_t * buffval, hashtable_set_how_t how)
{
  unsigned int hashval = 0;
  int rbt_value = 0;
  struct rbt_head *tete_rbt = NULL;
  struct rbt_node *qn = NULL;
  struct rbt_node *pn = NULL;
  hash_data_t *pdata = NULL;

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

  /* Find the RB Tree to be used */
  hashval = (*(ht->parameter.hash_func_key)) (&ht->parameter, buffkey);
  tete_rbt = &(ht->array_rbt[hashval]);
  rbt_value = (*(ht->parameter.hash_func_rbt)) (&ht->parameter, buffkey);

  LogFullDebug(COMPONENT_HASHTABLE,"Key = %p   Value = %p  hashval = %u  rbt_value = %x\n", buffkey->pdata,
         buffval->pdata, hashval, rbt_value);

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

  if(Key_Locate(ht, buffkey, hashval, rbt_value, &pn) == HASHTABLE_SUCCESS)
    {
      /* An entry of that key already exists */
      if(how == HASHTABLE_SET_HOW_TEST_ONLY)
        {
          ht->stat_dynamic[hashval].ok.nb_test += 1;
          V_w(&(ht->array_lock[hashval]));
          return HASHTABLE_SUCCESS;
        }

      if(how == HASHTABLE_SET_HOW_SET_NO_OVERWRITE)
        {
          ht->stat_dynamic[hashval].err.nb_test += 1;
          V_w(&(ht->array_lock[hashval]));
          return HASHTABLE_ERROR_KEY_ALREADY_EXISTS;
        }
      qn = pn;
      pdata = RBT_OPAQ(qn);

      LogFullDebug(COMPONENT_HASHTABLE,"Ecrasement d'une ancienne entree (k=%p,v=%p)\n", buffkey->pdata,
             buffval->pdata);

    }
  else
    {
      /* No entry of that key, add it to the trees */
      if(how == HASHTABLE_SET_HOW_TEST_ONLY)
        {
          ht->stat_dynamic[hashval].notfound.nb_test += 1;
          V_w(&(ht->array_lock[hashval]));
          return HASHTABLE_ERROR_NO_SUCH_KEY;
        }

      /* Insert a new node in the table */
      RBT_FIND(tete_rbt, pn, rbt_value);

#ifdef _DEBUG_MEMLEAKS
      /* For debugging memory leaks */
      BuddySetDebugLabel("rbt_node_t");
#endif
      /* This entry does not exist, create it */
      /* First get a new entry in the preallocated node array */
      GET_PREALLOC(qn, ht->node_prealloc[hashval], ht->parameter.nb_node_prealloc,
                   rbt_node_t, next);
      if(qn == NULL)
        {
          ht->stat_dynamic[hashval].err.nb_set += 1;
          V_w(&(ht->array_lock[hashval]));
          return HASHTABLE_INSERT_MALLOC_ERROR;
        }
#ifdef _DEBUG_MEMLEAKS
      /* For debugging memory leaks */
      BuddySetDebugLabel("hash_data_t");
#endif
      GET_PREALLOC(pdata, ht->pdata_prealloc[hashval], ht->parameter.nb_node_prealloc,
                   hash_data_t, next_alloc);
      if(pdata == NULL)
        {
          ht->stat_dynamic[hashval].err.nb_set += 1;
          V_w(&(ht->array_lock[hashval]));
          return HASHTABLE_INSERT_MALLOC_ERROR;
        }
#ifdef _DEBUG_MEMLEAKS
      /* For debugging memory leaks */
      BuddySetDebugLabel("N/A");
#endif
      RBT_OPAQ(qn) = pdata;
      RBT_VALUE(qn) = rbt_value;
      RBT_INSERT(tete_rbt, qn, pn);

      LogFullDebug(COMPONENT_HASHTABLE,"Creation d'une nouvelle entree (k=%p,v=%p), qn=%p, pdata=%p\n",
             buffkey->pdata, buffval->pdata, qn, RBT_OPAQ(qn));
    }

  pdata->buffval.pdata = buffval->pdata;
  pdata->buffval.len = buffval->len;

  pdata->buffkey.pdata = buffkey->pdata;
  pdata->buffkey.len = buffkey->len;

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

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

  return HASHTABLE_SUCCESS;
}                               /* HashTable_Set */