/**
* Structure for storing items within memcached.
*/
typedef struct _stritem {
struct _stritem *next;
struct _stritem *prev;
struct _stritem *h_next; /* hash chain next */
rel_time_t time; /* least recent access */
rel_time_t exptime; /* expire time */
int nbytes; /* size of data */
unsigned short refcount;
uint8_t nsuffix; /* length of flags-and-length string */
uint8_t it_flags; /* ITEM_* above */
uint8_t slabs_clsid;/* which slab class we're in */
uint8_t nkey; /* key length, w/terminating null and padding */
void * end[];
/* if it_flags & ITEM_CAS we have 8 bytes CAS */
/* then null-terminated key */
/* then " flags length/r/n" (no terminating null) */
/* then data with terminating /r/n (no terminating null; it's binary!) */
} item;
这个结构体就是存储cache的结构,每一项被缓存的结构全存在这个结构体中,HASH值相同的通过_stritem->h_next构成一个链表
/* Main hash table. This is where we look except during expansion. */
static item** primary_hashtable = 0;
/*
* Previous hash table. During expansion, we look here for keys that haven't
* been moved over to the primary yet.
*/
static item** old_hashtable = 0;
这两个全局变量存储了HASH的头元素,每一个代表HAH值相同的第一个元素,之后通过_stritem->h_next遍历。
primary_hashtable 代表正在使用的,当要扩展时,把原来的放到old_hashtable 里面,之后在primary_hashtable按2的指数倍重新分配,同时有一个线程负责把old_hashtable 移动到primary_hashtable里面去
没有任务的封锁,所以只适用于单线程
查找函数:
item *assoc_find(const char *key, const size_t nkey) {
uint32_t hv = hash(key, nkey, 0);
item *it;
unsigned int oldbucket;
if (expanding &&
(oldbucket = (hv & hashmask(hashpower - 1))) >= expand_bucket)
{
it = old_hashtable[oldbucket];
} else {
it = primary_hashtable[hv & hashmask(hashpower)];
}
item *ret = NULL;
int depth = 0;
while (it) {
if ((nkey == it->nkey) && (memcmp(key, ITEM_key(it), nkey) == 0)) {
ret = it;
break;
}
it = it->h_next;
++depth;
}
MEMCACHED_ASSOC_FIND(key, nkey, depth);
return ret;
}