Пример #1
0
void hash_table_insert(struct hash_table* ht, hash_key_t k, hash_val_t v)
{
    float load_factor = (float)ht->size / ht->capacity;
    if (load_factor >= HASH_TABLE_UPSIZE_LOAD_FACTOR) {
        size_t new_cap = ht->capacity * 2;
        hash_table_resize(ht, new_cap);
    }

    uint32_t hash = hash_key(ht, k);
    for (size_t i = 0; ; ++i) {
        size_t index         = index_from_hash((hash + i), ht->capacity);
        uint32_t cur_hash    = ht->hashes[index];
        struct hash_entry* e = ht->table + index;

        /* Found empty or deleted slot, insert */
        if (cur_hash == 0 || is_deleted(cur_hash)) {
            e->key = k;
            e->val = v;
            ht->hashes[index] = hash;
            ++ht->size;
            return;
        }

        /* Found occupied slot with same hash and key, replace value */
        if (hash == cur_hash && ht->eql_fn(e->key, k)) {
            e->val = v;
            return;
        }
    }
}
Пример #2
0
Файл: hash.c Проект: apiou/cogen
int
hash_table_remove(hash_table * hash_t, void *key, void **pdata)
{
	hash_node **node, *dest;

	node = hash_table_lookup_node(hash_t, key);
	if (*node)
	{
		if (pdata != NULL)
			*pdata = (*node)->value;
		dest = *node;
		*node = dest->next;
		if (pdata == NULL) {
			if (hash_t->hash_free)
				hash_t->hash_free(dest->value);
		}
		diag_free(dest);
		hash_t->nnodes--;
		hash_table_resize(hash_t);

		return 1;
	}

	return 0;
}
Пример #3
0
Файл: hash.c Проект: apiou/cogen
long
hash_table_replace(hash_table * hash_t, void *key, void *value)
{
	hash_node **node;
	hash_node *pnode;
	long hash_val;

	node = hash_table_lookup_node(hash_t, key);

	if (node)
		(*node)->value = value;
	else
	{
		*node = (hash_node *) diag_malloc(sizeof(hash_node));
		if (*node == NULL)
			diag_fatal("Unable to allocate memory\n");
		(*node)->key = key;
		(*node)->value = value;
		hash_val = (*hash_t->hash_func) ((*node)->key, hash_t->size);
		(*node)->next = hash_t->nodes[hash_val];
		hash_t->nodes[hash_val] = (*node);
		hash_t->nnodes++;
		pnode = *node;
		hash_table_resize(hash_t);
	}

	return (long) pnode;
}
Пример #4
0
/**
 * Function to remove an hash table element (for a given key) from a given hash table
 * @param table hash table from which element has to be removed
 * @param key pointer to the key which has to be removed
 * @param key_len size of the key in bytes
 * @returns 0 on sucess
 * @returns -1 when key is not found
 */
int _cdecl hash_table_remove(hash_table_t * table, void * key, size_t key_len)
{
	size_t hash;
	hash_table_element_t *temp, *prev;
    print_info("Deleting a key-value pair from the hash table\n");
    if ((table->key_num/ table->key_count) >= table->key_ratio)
    {
        print_info("Ratio(%d) reached the set limit %d\nContracting hash_table\n", (table->key_num / table->key_count), table->key_ratio);
        hash_table_resize(table, table->key_num/2);
        //exit(0);
    }
    hash = HASH(key, key_len);
    if (!table->store_house[hash])
    {
        print_info("Key Not Found -> No element at %d\n", (int)hash);
        return -1; // key not found
    }
    temp = table->store_house[hash];
    prev = temp;
    while(temp)
    {
        while(temp && temp->key_len!=key_len)
        {
            prev = temp;
            temp = temp->next;
        }
        if(temp)
        {
            if (!memcmp(temp->key, key, key_len))
            {
                if (prev == table->store_house[hash])
                {
                    table->store_house[hash] = temp->next;
                }
                else
                {
                    prev->next = temp->next;
                }
                hash_table_element_delete(table, temp);
                print_info("Deleted a key-value pair from the hash table\n");
                table->key_count--;                
                return 0;
            }
            prev=temp;
            temp=temp->next;
        }
    }
    print_info("Key Not Found\n");
    return -1; // key not found
}
Пример #5
0
int hash_add_or_set(struct hash_table_t *ht, 
        const char *key, unsigned int klen, 
        void *val, unsigned int vlen,
        hash_ops op)
{
    struct hash_bucket_t *p, **hlist_head;
    unsigned long h;
    unsigned int idx;

    h = ht->hash_func(key, klen); 

    idx = h & ht->hash_mask;

    p = ht->buckets[idx];

    for (; p; p = p->next) {
        if (p->hkey.klen == klen && !memcmp(p->hkey.key, key, klen)) {//Match       
            if (op == HASH_ADD) {
                return 0;
            }
            UPDATE_VAL(ht, p, val, vlen);
            return 1;
        }
    }
    
    p = lkmalloc(sizeof(struct hash_bucket_t)); 
    if (!p)
        return 0;
   
    hlist_head = &ht->buckets[idx];
     
    INIT_KV(p, key, klen, val, vlen);

    INSERT_INTO_HLIST(p, hlist_head);
    
    INSERT_INTO_TLIST(p, ht);

    ht->elements_count++;

    if (ht->elements_count > ht->table_size)
        hash_table_resize(ht);
    
    return 1;
}
Пример #6
0
void
hash_table_insert(struct hash_table *hash, void *data, size_t size)
{
	struct hash_element *element;

	element=(struct hash_element*)xmalloc(sizeof(*element));

	element->data=data;

	element->hash=hash->hash_fun(data,size);

	set_hash_element(hash,element);

	hash->used++;

	if (hash->resize_load > 0.0
	    && hash_table_get_load(hash) >= hash->resize_load)
		hash_table_resize(hash,hash->resize_load);
}
Пример #7
0
/*
 * Requires:
 *  "key" is not already in "ht".
 *  "value" is not NULL.
 *
 * Effects:
 *  Creates an association or mapping from the string "key" to the pointer
 *  "value" in the hash table "ht".  Returns 0 if the mapping was successfully
 *  created and -1 if it was not.
 */
int
hash_table_insert(struct hash_table *ht, int key, void *value)
{
    hash_table_mapping *elem;
    unsigned int index;

    assert(hash_table_lookup(ht, key) == NULL);
    assert(value != NULL);
    /*
     * Should the number of collision chains be increased?
     */
    if (ht->occupancy >= ht->load_factor * ht->size) {
        /*
         * Try to double the number of collision chains.
         */
        TracePrintf(1, "WARNING: hash table about to resize\n");
        if (hash_table_resize(ht, ht->size * 2) == -1)
            return (-1);
    }
    /*
     * Allocate memory for a new mapping and initialize it.
     */
    elem = malloc(sizeof (hash_table_mapping));
    if (elem == NULL)
        return (-1);
    elem->key = key;
    elem->value = value;
    /*
     * Compute the array index of the collision chain in which the mapping
     * should be inserted.
     */
    index = hash_value(key, ht) % ht->size;
    /*
     * Insert the new mapping into that collision chain.
     */
    elem->next = ht->head[index];
    ht->head[index] = elem;
    ht->occupancy++;
    return (0);
}
Пример #8
0
void hash_table_set(hash_table * t, char * key, void * item){

	int h = hash(t,key);
	element * e = (element *) malloc(sizeof(element));
	e->key = malloc(strlen(key) + 1);
	e->item = item;
	strcpy(e->key,key);
	e->next = t->buckets[h];
	t->buckets[h] = e;
	++(t->count);

	//see how deep the chain goes
	int chain = 0;
	while(e != NULL){
		e = e->next;
		chain++;
	}

	if(chain > MAX_CHAIN ){
		hash_table_resize(t);
	}

}
Пример #9
0
Файл: hash.c Проект: apiou/cogen
long
hash_table_insert(hash_table * hash_t, void *key, void *value)
{
	hash_node **node;
	hash_node *pnode;

	node = hash_table_lookup_node(hash_t, key);

	if (!*node)
	{

		*node = (hash_node *) diag_malloc(sizeof(hash_node));
		if (*node == NULL)
			diag_fatal("Unable to allocate memory\n");
		(*node)->key = key;
		(*node)->value = value;
		(*node)->next = NULL;
		hash_t->nnodes++;
		pnode = *node;
		hash_table_resize(hash_t);
	}

	return (long) pnode;
}
Пример #10
0
static struct hash_node *
hash_table_insert_node(struct hash_table *table, void *key, void *value,
		       bool check_existing)
{
	struct hash_node *node, *prev;
	unsigned int hash;

	i_assert(key != NULL);

	hash = table->hash_cb(key);

	if (check_existing && table->removed_count > 0) {
		/* there may be holes, have to check everything */
		node = hash_table_lookup_node(table, key, hash);
		if (node != NULL) {
			node->value = value;
			return node;
		}

                check_existing = FALSE;
	}

	/* a) primary node */
	node = &table->nodes[hash % table->size];
	if (node->key == NULL) {
		table->nodes_count++;

		node->key = key;
		node->value = value;
		return node;
	}

	if (check_existing) {
		if (table->key_compare_cb(node->key, key) == 0) {
			node->value = value;
			return node;
		}
	}

	/* b) collisions list */
	prev = node; node = node->next;
	while (node != NULL) {
		if (node->key == NULL)
			break;

		if (check_existing) {
			if (table->key_compare_cb(node->key, key) == 0) {
				node->value = value;
				return node;
			}
		}

		prev = node;
		node = node->next;
	}

	if (node == NULL) {
		if (table->frozen == 0 && hash_table_resize(table, TRUE)) {
			/* resized table, try again */
			return hash_table_insert_node(table, key, value, FALSE);
		}

		if (table->free_nodes == NULL)
			node = p_new(table->node_pool, struct hash_node, 1);
		else {
			node = table->free_nodes;
			table->free_nodes = node->next;
			node->next = NULL;
		}
		prev->next = node;
	}
Пример #11
0
int hash_table_remove(HashTable *hash_table, HashTableKey key, bool resize)
{
	HashTableEntry **rover;
	HashTableEntry *entry;
	unsigned long long int index;
	unsigned long long int result;
        
        /* If there are too few items in the table with respect to the table
	 * size, the table is taking up too much space. 
         * Shrink table to improve space efficiency. */

	if (resize && (hash_table->entries * 8) / hash_table->table_size <= 0) {
		
		/* Table is less than 1/8 full */

		if (!hash_table_resize(hash_table)) {

			/* Failed to enlarge the table */

			return 0;
		}
	}

	/* Generate the hash of the key and hence the index into the table */
	
	index = hash_table->hash_func(key) % hash_table->table_size;

	/* Rover points at the pointer which points at the current entry
	 * in the chain being inspected.  ie. the entry in the table, or
	 * the "next" pointer of the previous entry in the chain.  This
	 * allows us to unlink the entry when we find it. */

	result = 0;
	rover = &hash_table->table[index];

	while (*rover != NULL) {

		if (hash_table->equal_func(key, (*rover)->key) != 0) {

			/* This is the entry to remove */

			entry = *rover;

			/* Unlink from the list */

			*rover = entry->next;

			/* Destroy the entry structure */

			hash_table_free_entry(hash_table, entry);

			/* Track count of entries */

			--hash_table->entries;

			result = 1;

			break;
		}
		
		/* Advance to the next entry */

		rover = &((*rover)->next);
	}

	return result;
}
Пример #12
0
int hash_table_insert(HashTable *hash_table, HashTableKey key, HashTableValue value) 
{
	HashTableEntry *rover;
	HashTableEntry *newentry;
	unsigned long long int index;
	
	/* If there are too many items in the table with respect to the table
	 * size, the number of hash collisions increases and performance
	 * decreases. Enlarge the table size to prevent this happening */

	if ((hash_table->entries * 2) / hash_table->table_size > 0) {
		
		/* Table is more than 1/2 full */

		if (!hash_table_resize(hash_table)) {

			/* Failed to enlarge the table */

			return 0;
		}
	}

	/* Generate the hash of the key and hence the index into the table */

	index = hash_table->hash_func(key) % hash_table->table_size;

	/* Traverse the chain at this location and look for an existing
	 * entry with the same key */

	rover = hash_table->table[index];

	while (rover != NULL) {
		if (hash_table->equal_func(rover->key, key) != 0) {

			/* Same key: overwrite this entry with new data */

			/* If there is a value free function, free the old data
			 * before adding in the new data */

			if (hash_table->value_free_func != NULL) {
				hash_table->value_free_func(rover->value);
			}

			/* Same with the key: use the new key value and free 
			 * the old one */

			if (hash_table->key_free_func != NULL) {
				hash_table->key_free_func(rover->key);
			}

			rover->key = key;
			rover->value = value;

			/* Finished */
			
			return 1;
		}
		rover = rover->next;
	}
	
	/* Not in the hash table yet.  Create a new entry */

	newentry = (HashTableEntry *) malloc(sizeof(HashTableEntry));

	if (newentry == NULL) {
		return 0;
	}

	newentry->key = key;
	newentry->value = value;

	/* Link into the list */

	newentry->next = hash_table->table[index];
	hash_table->table[index] = newentry;

	/* Maintain the count of the number of entries */

	++hash_table->entries;

	/* Added successfully */

	return 1;
}
Пример #13
0
/**
 * Function to add a key - value pair to the hash table, use HT_ADD macro
 * @param table hash table to add element to
 * @param key pointer to the key for the hash table
 * @param key_len length of the key in bytes
 * @param value pointer to the value to be added against the key
 * @param value_len length of the value in bytes
 * @returns 0 on sucess
 * @returns -1 when no memory
 */
int _cdecl hash_table_add(hash_table_t * table, void * key, size_t key_len, void * value, size_t value_len)
{
	size_t hash;
	hash_table_element_t * element;

    if ((table->key_count / table->key_num) >= table->key_ratio)
    {
        print_info("Ratio(%d) reached the set limit %d\nExpanding hash_table\n", (table->key_count / table->key_num), table->key_ratio);
        hash_table_resize(table, table->key_num*2);
        //exit(0);
    }
    hash = HASH(key, key_len);
    element = hash_table_element_new();
    if (!element)
    {
        print_info("Cannot allocate memory for element\n");
        return -1; // No Memory
    }
    if (table->mode == MODE_COPY)
    {
        print_info("Adding a key-value pair to the hash table with hash -> %d, in COPY MODE\n", (int)hash);
        element->key = malloc(key_len);
        element->value = malloc(value_len);
        if (element->key && element->value)
        {
            memcpy(element->key, key, key_len);
            memcpy(element->value, value, value_len);
        }
        else
        {
            if (element->key)
            {
                free(element->key);
                print_info("Cannot allocate memory for value\n");
            }
            if (element->value)
            {
                free(element->value);
                print_info("Cannot allocate memory for key\n");
            }
            free(element);
            return -1; //No Memory
        }
    }
    else if (table->mode == MODE_VALUEREF)
    {
        print_info("Adding a key-value pair to the hash table with hash -> %d, in VALUEREF MODE\n", (int)hash);
        element->key = malloc(key_len);
        if (element->key)
        {
            memcpy(element->key, key, key_len);
        }
        else
        {
            print_info("Cannot allocate memory for key\n");
            free(element);
            return -1; //No Memory
        }
        element->value = value;
    }
    else if (table->mode == MODE_ALLREF)
    {
        print_info("Adding a key-value pair to the hash table with hash -> %d, in ALLREF MODE\n", (int)hash);
        element->key = key;
        element->value = value;
    }
    element->key_len = key_len;
    element->value_len = value_len;
    element->next = NULL;
    // find the key position for chaining
    if (!table->store_house[hash])
    {
        print_info("No Conflicts adding the first element at %d\n", (int)hash);
        table->store_house[hash] = element;
        table->key_count++;
    }
    else
    {
		hash_table_element_t * temp = table->store_house[hash];
        print_info("Conflicts adding element at %d\n", (int)hash);
  
        while(temp->next)
        {
            while(temp->next && temp->next->key_len!=key_len)
            {
                temp = temp->next;
            }
            if(temp->next)
            {
                if (!memcmp(temp->next->key, key, key_len))
                {
					hash_table_element_t *to_delete = temp->next;
                    print_info("Found Key at hash -> %d\n", (int)hash);
                    temp->next = element;
                    element->next = to_delete->next;
                    hash_table_element_delete(table, to_delete);
                    // since we are replacing values no need to change key_count
                    return 0;
                }
                else
                {
                    temp = temp->next;
                }
            }
        }
        temp->next = element;
        table->key_count++;
    }
    return 0;
}