382 lines
10 KiB
C
382 lines
10 KiB
C
/**
|
|
* Copyright (C) 2008 Happy Fish / YuQing
|
|
*
|
|
* FastDFS may be copied only under the terms of the GNU General
|
|
* Public License V3, which may be found in the FastDFS source kit.
|
|
* Please visit the FastDFS Home Page http://www.csource.org/ for more detail.
|
|
**/
|
|
|
|
#ifndef _HASH_H_
|
|
#define _HASH_H_
|
|
|
|
#include <sys/types.h>
|
|
#include <pthread.h>
|
|
#include "common_define.h"
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
#define CRC32_XINIT 0xFFFFFFFF /* initial value */
|
|
#define CRC32_XOROT 0xFFFFFFFF /* final xor value */
|
|
|
|
typedef int (*HashFunc) (const void *key, const int key_len);
|
|
|
|
#ifdef HASH_STORE_HASH_CODE
|
|
#define HASH_CODE(pHash, hash_data) hash_data->hash_code
|
|
#else
|
|
#define HASH_CODE(pHash, hash_data) ((unsigned int)pHash->hash_func( \
|
|
hash_data->key, hash_data->key_len))
|
|
#endif
|
|
|
|
#define CALC_NODE_MALLOC_BYTES(key_len, value_size) \
|
|
sizeof(HashData) + key_len + value_size
|
|
|
|
#define FREE_HASH_DATA(pHash, hash_data) \
|
|
pHash->item_count--; \
|
|
pHash->bytes_used -= CALC_NODE_MALLOC_BYTES(hash_data->key_len, \
|
|
hash_data->malloc_value_size); \
|
|
free(hash_data);
|
|
|
|
|
|
typedef struct tagHashData
|
|
{
|
|
int key_len;
|
|
int value_len;
|
|
int malloc_value_size;
|
|
|
|
#ifdef HASH_STORE_HASH_CODE
|
|
unsigned int hash_code;
|
|
#endif
|
|
|
|
char *value;
|
|
struct tagHashData *next;
|
|
char key[0];
|
|
} HashData;
|
|
|
|
typedef int64_t (*ConvertValueFunc)(const HashData *old_data, const int inc,
|
|
char *new_value, int *new_value_len, void *arg);
|
|
|
|
typedef struct tagHashArray
|
|
{
|
|
HashData **buckets;
|
|
HashFunc hash_func;
|
|
int item_count;
|
|
unsigned int *capacity;
|
|
double load_factor;
|
|
int64_t max_bytes;
|
|
int64_t bytes_used;
|
|
bool is_malloc_capacity;
|
|
bool is_malloc_value;
|
|
unsigned int lock_count;
|
|
pthread_mutex_t *locks;
|
|
} HashArray;
|
|
|
|
typedef struct tagHashStat
|
|
{
|
|
unsigned int capacity;
|
|
int item_count;
|
|
int bucket_used;
|
|
double bucket_avg_length;
|
|
int bucket_max_length;
|
|
} HashStat;
|
|
|
|
/**
|
|
* hash walk function
|
|
* parameters:
|
|
* index: item index based 0
|
|
* data: hash data, including key and value
|
|
* args: passed by hash_walk function
|
|
* return 0 for success, != 0 for error
|
|
*/
|
|
typedef int (*HashWalkFunc)(const int index, const HashData *data, void *args);
|
|
|
|
#define hash_init(pHash, hash_func, capacity, load_factor) \
|
|
hash_init_ex(pHash, hash_func, capacity, load_factor, 0, false)
|
|
|
|
#define hash_insert(pHash, key, key_len, value) \
|
|
hash_insert_ex(pHash, key, key_len, value, 0, true)
|
|
|
|
/**
|
|
* hash init function
|
|
* parameters:
|
|
* pHash: the hash table
|
|
* hash_func: hash function
|
|
* capacity: init capacity
|
|
* load_factor: hash load factor, such as 0.75
|
|
* max_bytes: max memory can be used (bytes)
|
|
* bMallocValue: if need malloc value buffer
|
|
* return 0 for success, != 0 for error
|
|
*/
|
|
int hash_init_ex(HashArray *pHash, HashFunc hash_func, \
|
|
const unsigned int capacity, const double load_factor, \
|
|
const int64_t max_bytes, const bool bMallocValue);
|
|
|
|
/**
|
|
* set hash locks function
|
|
* parameters:
|
|
* lock_count: the lock count
|
|
* return 0 for success, != 0 for error
|
|
*/
|
|
int hash_set_locks(HashArray *pHash, const int lock_count);
|
|
|
|
/**
|
|
* convert the value
|
|
* parameters:
|
|
* HashData: the old hash data
|
|
* inc: the increasement value
|
|
* new_value: return the new value
|
|
* new_value_len: return the length of the new value
|
|
* arg: the user data
|
|
* return the number after increasement
|
|
*/
|
|
int64_t hash_inc_value(const HashData *old_data, const int inc,
|
|
char *new_value, int *new_value_len, void *arg);
|
|
|
|
#define hash_inc(pHash, key, key_len, inc, value, value_len) \
|
|
hash_inc_ex(pHash, key, key_len, inc, value, value_len, \
|
|
hash_inc_value, NULL)
|
|
|
|
/**
|
|
* atomic increase value
|
|
* parameters:
|
|
* pHash: the hash table
|
|
* key: the key to insert
|
|
* key_len: length of th key
|
|
* inc: the increasement value
|
|
* value: return the new value
|
|
* value_len: return the length of the new value
|
|
* convert_func: the convert function
|
|
* arg: the arg to convert function
|
|
* return 0 for success, != 0 for error (errno)
|
|
*
|
|
*/
|
|
int hash_inc_ex(HashArray *pHash, const void *key, const int key_len,
|
|
const int inc, char *value, int *value_len,
|
|
ConvertValueFunc convert_func, void *arg);
|
|
|
|
/**
|
|
* hash destroy function
|
|
* parameters:
|
|
* pHash: the hash table
|
|
* return none
|
|
*/
|
|
void hash_destroy(HashArray *pHash);
|
|
|
|
/**
|
|
* hash insert key
|
|
* parameters:
|
|
* pHash: the hash table
|
|
* key: the key to insert
|
|
* key_len: length of th key
|
|
* value: the value
|
|
* value_len: length of the value
|
|
* needLock: if need lock
|
|
* return >= 0 for success, 0 for key already exist (update),
|
|
* 1 for new key (insert), < 0 for error
|
|
*/
|
|
int hash_insert_ex(HashArray *pHash, const void *key, const int key_len, \
|
|
void *value, const int value_len, const bool needLock);
|
|
|
|
/**
|
|
* hash find key
|
|
* parameters:
|
|
* pHash: the hash table
|
|
* key: the key to find
|
|
* key_len: length of th key
|
|
* return user data, return NULL when the key not exist
|
|
*/
|
|
void *hash_find(HashArray *pHash, const void *key, const int key_len);
|
|
|
|
/**
|
|
* hash find key
|
|
* parameters:
|
|
* pHash: the hash table
|
|
* key: the key to find
|
|
* key_len: length of th key
|
|
* return hash data, return NULL when the key not exist
|
|
*/
|
|
HashData *hash_find_ex(HashArray *pHash, const void *key, const int key_len);
|
|
|
|
|
|
/**
|
|
* hash get the value of the key
|
|
* parameters:
|
|
* pHash: the hash table
|
|
* key: the key to find
|
|
* key_len: length of th key
|
|
* value: store the value
|
|
* value_len: input for the max size of the value
|
|
* output for the length fo the value
|
|
* return 0 for success, != 0 fail (errno)
|
|
*/
|
|
int hash_get(HashArray *pHash, const void *key, const int key_len,
|
|
void *value, int *value_len);
|
|
|
|
|
|
/**
|
|
* hash partial set
|
|
* parameters:
|
|
* pHash: the hash table
|
|
* key: the key to insert
|
|
* key_len: length of th key
|
|
* value: the value
|
|
* offset: the offset of existed value
|
|
* value_len: length of the value
|
|
* return 0 for success, != 0 fail (errno)
|
|
*/
|
|
int hash_partial_set(HashArray *pHash, const void *key, const int key_len,
|
|
const char *value, const int offset, const int value_len);
|
|
|
|
/**
|
|
* hash delete key
|
|
* parameters:
|
|
* pHash: the hash table
|
|
* key: the key to delete
|
|
* key_len: length of th key
|
|
* return 0 for success, != 0 fail (errno)
|
|
*/
|
|
int hash_delete(HashArray *pHash, const void *key, const int key_len);
|
|
|
|
/**
|
|
* hash walk (iterator)
|
|
* parameters:
|
|
* pHash: the hash table
|
|
* walkFunc: walk (interator) function
|
|
* args: extra args which will be passed to walkFunc
|
|
* return 0 for success, != 0 fail (errno)
|
|
*/
|
|
int hash_walk(HashArray *pHash, HashWalkFunc walkFunc, void *args);
|
|
|
|
/**
|
|
* get hash item count
|
|
* parameters:
|
|
* pHash: the hash table
|
|
* return item count
|
|
*/
|
|
int hash_count(HashArray *pHash);
|
|
|
|
/**
|
|
* hash best optimize
|
|
* parameters:
|
|
* pHash: the hash table
|
|
* suggest_capacity: suggest init capacity for speed
|
|
* return >0 for success, < 0 fail (errno)
|
|
*/
|
|
int hash_best_op(HashArray *pHash, const int suggest_capacity);
|
|
|
|
/**
|
|
* hash stat
|
|
* parameters:
|
|
* pHash: the hash table
|
|
* pStat: return stat info
|
|
* stat_by_lens: return stats array by bucket length
|
|
* stat_by_lens[0] empty buckets count
|
|
* stat_by_lens[1] contain 1 key buckets count
|
|
* stat_by_lens[2] contain 2 key buckets count, etc
|
|
* stat_size: stats array size (contain max elments)
|
|
* return 0 for success, != 0 fail (errno)
|
|
*/
|
|
int hash_stat(HashArray *pHash, HashStat *pStat, \
|
|
int *stat_by_lens, const int stat_size);
|
|
|
|
/**
|
|
* print hash stat info
|
|
* parameters:
|
|
* pHash: the hash table
|
|
* return none
|
|
*/
|
|
void hash_stat_print(HashArray *pHash);
|
|
|
|
/**
|
|
* lock the bucket of hash table
|
|
* parameters:
|
|
* pHash: the hash table
|
|
* bucket_index: the index of bucket
|
|
* return 0 for success, != 0 fail (errno)
|
|
*/
|
|
int hash_bucket_lock(HashArray *pHash, const unsigned int bucket_index);
|
|
|
|
/**
|
|
* unlock the bucket of hash table
|
|
* parameters:
|
|
* pHash: the hash table
|
|
* bucket_index: the index of bucket
|
|
* return 0 for success, != 0 fail (errno)
|
|
*/
|
|
int hash_bucket_unlock(HashArray *pHash, const unsigned int bucket_index);
|
|
|
|
int RSHash(const void *key, const int key_len);
|
|
|
|
int JSHash(const void *key, const int key_len);
|
|
int JSHash_ex(const void *key, const int key_len, \
|
|
const int init_value);
|
|
|
|
int PJWHash(const void *key, const int key_len);
|
|
int PJWHash_ex(const void *key, const int key_len, \
|
|
const int init_value);
|
|
|
|
int ELFHash(const void *key, const int key_len);
|
|
int ELFHash_ex(const void *key, const int key_len, \
|
|
const int init_value);
|
|
|
|
int BKDRHash(const void *key, const int key_len);
|
|
int BKDRHash_ex(const void *key, const int key_len, \
|
|
const int init_value);
|
|
|
|
int SDBMHash(const void *key, const int key_len);
|
|
int SDBMHash_ex(const void *key, const int key_len, \
|
|
const int init_value);
|
|
|
|
int Time33Hash(const void *key, const int key_len);
|
|
int Time33Hash_ex(const void *key, const int key_len, \
|
|
const int init_value);
|
|
|
|
int DJBHash(const void *key, const int key_len);
|
|
int DJBHash_ex(const void *key, const int key_len, \
|
|
const int init_value);
|
|
|
|
int APHash(const void *key, const int key_len);
|
|
int APHash_ex(const void *key, const int key_len, \
|
|
const int init_value);
|
|
|
|
int calc_hashnr (const void* key, const int key_len);
|
|
|
|
int calc_hashnr1(const void* key, const int key_len);
|
|
int calc_hashnr1_ex(const void* key, const int key_len, \
|
|
const int init_value);
|
|
|
|
int simple_hash(const void* key, const int key_len);
|
|
int simple_hash_ex(const void* key, const int key_len, \
|
|
const int init_value);
|
|
|
|
int CRC32(void *key, const int key_len);
|
|
int CRC32_ex(void *key, const int key_len, \
|
|
const int init_value);
|
|
|
|
#define CRC32_FINAL(crc) (crc ^ CRC32_XOROT)
|
|
|
|
#define INIT_HASH_CODES4(hash_codes) \
|
|
hash_codes[0] = CRC32_XINIT; \
|
|
hash_codes[1] = 0; \
|
|
hash_codes[2] = 0; \
|
|
hash_codes[3] = 0; \
|
|
|
|
#define CALC_HASH_CODES4(buff, buff_len, hash_codes) \
|
|
hash_codes[0] = CRC32_ex(buff, buff_len, hash_codes[0]); \
|
|
hash_codes[1] = ELFHash_ex(buff, buff_len, hash_codes[1]); \
|
|
hash_codes[2] = simple_hash_ex(buff, buff_len, hash_codes[2]); \
|
|
hash_codes[3] = Time33Hash_ex(buff, buff_len, hash_codes[3]); \
|
|
|
|
|
|
#define FINISH_HASH_CODES4(hash_codes) \
|
|
hash_codes[0] = CRC32_FINAL(hash_codes[0]); \
|
|
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#endif
|
|
|