//由于哈希值只能确定是在哈希表中的哪个桶(bucket),但一个桶里面是有一条冲突链的 //此时需要用到具体的键值遍历并一一比较冲突链上的所有节点。虽然key是以'\0'结尾 //的字符串,但调用strlen还是有点耗时(需要遍历键值字符串)。所以需要另外一个参数 //nkey指明这个key的长度 //reference:http://blog.csdn.net/luotuo44/article/details/42773231 item *assoc_find(const char *key, const size_t nkey, const uint32_t hv) { item *it; unsigned int oldbucket; // 得到相应的桶, bucket if (expanding && (oldbucket = (hv & hashmask(hashpower - 1))) >= expand_bucket) { it = old_hashtable[oldbucket]; } else { //由哈希值判断这个key是属于那个桶(bucket)的 it = primary_hashtable[hv & hashmask(hashpower)]; } // 在桶里遍历搜索目标 item *ret = NULL; int depth = 0; while (it) { //调用memcmp来进行比较 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; }
item *assoc_find(const char *key, const size_t nkey, const uint32_t hv) { 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) { // [branch 009b] Switch to safe memcmp if ((nkey == it->nkey) && (tm_memcmp(key, ITEM_key(it), nkey) == 0)) { ret = it; break; } it = it->h_next; ++depth; } MEMCACHED_ASSOC_FIND(key, nkey, depth); return ret; }
item *assoc_find(const char *key, const size_t nkey, const uint32_t hv) { item *it; unsigned int oldbucket; //哈希表处理迁移数据状态,且还没有迁移到该桶。(在还没有迁移到该桶时,assoc_insert保证哈希到该区间的键插入到旧表) if (expanding && (oldbucket = (hv & hashmask(hashpower - 1))) >= expand_bucket) { it = old_hashtable[oldbucket]; } else { //找到key所在桶 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; }
hash_item *assoc_find(struct default_engine *engine, uint32_t hash, const char *key, const size_t nkey) { hash_item *it; unsigned int oldbucket; if (engine->assoc.expanding && (oldbucket = (hash & hashmask(engine->assoc.hashpower - 1))) >= engine->assoc.expand_bucket) { it = engine->assoc.old_hashtable[oldbucket]; } else { it = engine->assoc.primary_hashtable[hash & hashmask(engine->assoc.hashpower)]; } hash_item *ret = NULL; int depth = 0; while (it) { if ((nkey == it->nkey) && (memcmp(key, item_get_key(it), nkey) == 0)) { ret = it; break; } it = it->h_next; ++depth; } MEMCACHED_ASSOC_FIND(key, nkey, depth); return ret; }
shadow_item *shadow_assoc_find(const char *key, const size_t nkey, const uint32_t hv) { shadow_item *it; unsigned int oldbucket; if (expanding && (oldbucket = (hv & hashmask(shadow_hashpower - 1))) >= expand_bucket) { it = old_hashtable[oldbucket]; } else { it = primary_hashtable[hv & hashmask(shadow_hashpower)]; } shadow_item *ret = NULL; int depth = 0; while (it) { if ((nkey == it->nkey) && (memcmp(key, it->key, nkey) == 0)) { ret = it; break; } it = it->h_next; ++depth; } MEMCACHED_ASSOC_FIND(key, nkey, depth); return ret; }
//由于哈希值只能确定是在哈希表中的哪个桶(bucket),但一个桶里面是有一条冲突链的 //此时需要用到具体的键值遍历并一一比较冲突链上的所有节点。虽然key是以'\0'结尾 //的字符串,但调用strlen还是有点耗时(需要遍历键值字符串)。所以需要另外一个参数 //nkey指明这个key的长度 item *assoc_find(const char *key, const size_t nkey, const uint32_t hv) { item *it; unsigned int oldbucket; if (expanding &&//正在扩展哈希表 (oldbucket = (hv & hashmask(hashpower - 1))) >= expand_bucket)//该item还在旧表里面 { it = old_hashtable[oldbucket]; } else { //由哈希值判断这个key是属于那个桶(bucket)的 it = primary_hashtable[hv & hashmask(hashpower)]; } //到这里,已经确定这个key是属于那个桶的。 遍历对应桶的冲突链即可 item *ret = NULL; int depth = 0; while (it) { //长度相同的情况下才调用memcmp比较,更高效 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; }
item *assoc_find(const char *key, const size_t nkey, const uint32_t hv) { item *it; unsigned int oldbucket; if (expanding && (oldbucket = (hv & hashmask(hashpower - 1))) >= expand_bucket) {//这个槽位位于当前正在迁移的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; }
item *assoc_find(const char *key, const size_t nkey, const uint32_t hv) { item *it; unsigned int oldbucket; /* 如果hashtable正在扩容阶段,所找item在老hashtable中,则在老hashtable中查询,否则从新表中查询 * 判断在哪个表中的思路: * 1. 定位key所在hashtable中桶的位置 * 2. 如果此位置大于等于从旧hashtable中移到新hashtable的数量,则所查找元素在旧hashtable中,否则在新hash表中 * * eg. * primary hashtable * [0] * [1] -> a -> b -> null * [2] * [3] -> x * * old hashtable * [0] * [1] * [2] * [3] * [4] -> y ->null * [5] -> p -> null <--- hash(key) * ... */ 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; }
hash_item *assoc_find(struct default_engine *engine, uint32_t hash, const char *key, const size_t nkey) { struct assoc *assoc = &engine->assoc; hash_item *it; int depth = 0; uint32_t bucket = GET_HASH_BUCKET(hash, assoc->hashmask); uint32_t tabidx = GET_HASH_TABIDX(hash, assoc->hashpower, hashmask(assoc->infotable[bucket].curpower)); it = assoc->roottable[tabidx].hashtable[bucket]; while (it) { if ((hash == it->khash) && (nkey == it->nkey) && (memcmp(key, item_get_key(it), nkey) == 0)) { break; /* found */ } it = it->h_next; ++depth; } MEMCACHED_ASSOC_FIND(key, nkey, depth); return it; }