Example #1
0
struct hash_table *
hashtable_init(struct hash_param *hparam)
{
	/* The hash table being constructed */
	struct hash_table *ht = NULL;
	/* The index for initializing each partition */
	uint32_t index = 0;
	/* Read-Write Lock attributes, to prevent write starvation under
	   GLIBC */
	pthread_rwlockattr_t rwlockattr;
	/* Hash partition */
	struct hash_partition *partition = NULL;
	/* The number of fully initialized partitions */
	uint32_t completed = 0;

	if (pthread_rwlockattr_init(&rwlockattr) != 0)
		return NULL;

	/* At some point factor this out into the OS directory.  it is
	   necessary to prevent writer starvation under GLIBC. */
#ifdef GLIBC
	if ((pthread_rwlockattr_setkind_np
	     (&rwlockattrs,
	      PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP)) != 0) {
		LogCrit(COMPONENT_HASHTABLE,
			"Unable to set writer-preference on lock attribute.");
		goto deconstruct;
	}
#endif				/* GLIBC */

	ht = gsh_calloc(1, sizeof(struct hash_table) +
			(sizeof(struct hash_partition) *
			 hparam->index_size));

	/* Fixup entry size */
	if (hparam->flags & HT_FLAG_CACHE) {
		if (!hparam->cache_entry_count)
			/* works fine with a good hash algo */
			hparam->cache_entry_count = 32767;
	}

	/* We need to save copy of the parameters in the table. */
	ht->parameter = *hparam;
	for (index = 0; index < hparam->index_size; ++index) {
		partition = (&ht->partitions[index]);
		RBT_HEAD_INIT(&(partition->rbt));

		if (pthread_rwlock_init(&partition->lock, &rwlockattr) != 0) {
			LogCrit(COMPONENT_HASHTABLE,
				"Unable to initialize lock in hash table.");
			goto deconstruct;
		}

		/* Allocate a cache if requested */
		if (hparam->flags & HT_FLAG_CACHE)
			partition->cache = gsh_calloc(1, cache_page_size(ht));

		completed++;
	}

	ht->node_pool = pool_basic_init(NULL, sizeof(rbt_node_t));
	ht->data_pool = pool_basic_init(NULL, sizeof(struct hash_data));

	pthread_rwlockattr_destroy(&rwlockattr);
	return ht;

 deconstruct:

	while (completed != 0) {
		if (hparam->flags & HT_FLAG_CACHE)
			gsh_free(ht->partitions[completed - 1].cache);

		PTHREAD_RWLOCK_destroy(&(ht->partitions[completed - 1].lock));
		completed--;
	}
	if (ht->node_pool)
		pool_destroy(ht->node_pool);
	if (ht->data_pool)
		pool_destroy(ht->data_pool);

	gsh_free(ht);
	return ht = NULL;
}
Example #2
0
hash_table_t *HashTable_Init(hash_parameter_t hparam)
{
  hash_table_t *ht;
  unsigned int i = 0;

  pthread_mutexattr_t mutexattr;

  /* Sanity check */
  if((ht = (hash_table_t *) Mem_Alloc(sizeof(hash_table_t))) == NULL)
    return NULL;

  /* we have to keep the discriminant values */
  ht->parameter = hparam;

  if(pthread_mutexattr_init(&mutexattr) != 0)
    return NULL;

  /* Initialization of the node array */
  if((ht->array_rbt =
      (struct rbt_head *)Mem_Alloc(sizeof(struct rbt_head) * hparam.index_size)) == NULL)
    return NULL;

  /* Initialization of the stat array */
  if((ht->stat_dynamic =
      (hash_stat_dynamic_t *) Mem_Alloc(sizeof(hash_stat_dynamic_t) *
                                        hparam.index_size)) == NULL)
    return NULL;

  /* Init the stats */
  memset((char *)ht->stat_dynamic, 0, sizeof(hash_stat_dynamic_t) * hparam.index_size);

  /* Initialization of the semaphores array */
  if((ht->array_lock =
      (rw_lock_t *) Mem_Alloc(sizeof(rw_lock_t) * hparam.index_size)) == NULL)
    return NULL;

  /* Initialize the array of pre-allocated node */
  if((ht->node_prealloc =
      (struct rbt_node **)Mem_Alloc(sizeof(struct rbt_node *) * hparam.index_size)) ==
     NULL)
    return NULL;

  if((ht->pdata_prealloc =
      (hash_data_t **) Mem_Alloc(sizeof(hash_data_t *) * hparam.index_size)) == NULL)
    return NULL;

  for(i = 0; i < hparam.index_size; i++)
    {
#ifndef _NO_BLOCK_PREALLOC
      if((ht->node_prealloc[i] = PreAllocNode(hparam.nb_node_prealloc)) == NULL)
        return NULL;

      if((ht->pdata_prealloc[i] = PreAllocPdata(hparam.nb_node_prealloc)) == NULL)
        return NULL;
#else
      ht->node_prealloc[i] = PreAllocNode(hparam.nb_node_prealloc);
      ht->pdata_prealloc[i] = PreAllocPdata(hparam.nb_node_prealloc);
#endif
    }

  /* Initialize each of the RB-Tree, mutexes and stats */
  for(i = 0; i < hparam.index_size; i++)
    {
      /* RBT Init */
      RBT_HEAD_INIT(&(ht->array_rbt[i]));

      /* Mutex Init */
      if(rw_lock_init(&(ht->array_lock[i])) != 0)
        return NULL;

      /* Initialization of the stats structure */
      ht->stat_dynamic[i].nb_entries = 0;

      ht->stat_dynamic[i].ok.nb_set = 0;
      ht->stat_dynamic[i].ok.nb_get = 0;
      ht->stat_dynamic[i].ok.nb_del = 0;
      ht->stat_dynamic[i].ok.nb_test = 0;

      ht->stat_dynamic[i].err.nb_set = 0;
      ht->stat_dynamic[i].err.nb_get = 0;
      ht->stat_dynamic[i].err.nb_del = 0;
      ht->stat_dynamic[i].err.nb_test = 0;

      ht->stat_dynamic[i].notfound.nb_set = 0;
      ht->stat_dynamic[i].notfound.nb_get = 0;
      ht->stat_dynamic[i].notfound.nb_del = 0;
      ht->stat_dynamic[i].notfound.nb_test = 0;
    }

  /* final return, if we arrive here, then everything is alright */
  return ht;
}                               /* HashTable_Init */