tokyo cabinet源代码分析(5)

2.4数据记录的查找

   在前面的部分对于记录的插入进行了阐述。本节对通过key查找value方法进行了分析。

2.4.1TCMAP数组查找

  先映射到MAP数组的一个元素,然后基于该元素对于hash buckets数组进行访问。

通过tcmdbget进行查找 /* Retrieve a record in an on-memory hash database. */ void *tcmdbget(TCMDB *mdb, const void *kbuf, int ksiz, int *sp){ assert(mdb && kbuf && ksiz >= 0 && sp); unsigned int mi; /*将key映射到map数组的一个元素上*/ TCMDBHASH(mi, kbuf, ksiz); /*通过mutex锁唯一访问*/ if(pthread_rwlock_rdlock((pthread_rwlock_t *)mdb->mmtxs + mi) != 0) return NULL; int vsiz; const char *vbuf = tcmapget(mdb->maps[mi], kbuf, ksiz, &vsiz); char *rv; if(vbuf){ TCMEMDUP(rv, vbuf, vsiz); *sp = vsiz; } else { rv = NULL; } pthread_rwlock_unlock((pthread_rwlock_t *)mdb->mmtxs + mi); return rv; }

2.4.2 hash buckets二叉树查找

  查找二叉树结构,获得value对象,返回的是分配好的内存地址,所以查找使用以后,

需要进行释放。

/*通过tcmapget遍历二叉搜索树,查找value*/ /* Retrieve a record in a map object. */ const void *tcmapget(const TCMAP *map, const void *kbuf, int ksiz, int *sp){ assert(map && kbuf && ksiz >= 0 && sp); if(ksiz > TCMAPKMAXSIZ) ksiz = TCMAPKMAXSIZ; uint32_t hash; TCMAPHASH1(hash, kbuf, ksiz); /*先定位到bucket一个元素上*/ TCMAPREC *rec = map->buckets[hash%map->bnum]; TCMAPHASH2(hash, kbuf, ksiz); hash &= ~TCMAPKMAXSIZ; /*遍历二叉树 *hash值相同,然后比较key值 */ while(rec){ uint32_t rhash = rec->ksiz & ~TCMAPKMAXSIZ; uint32_t rksiz = rec->ksiz & TCMAPKMAXSIZ; if(hash > rhash){ rec = rec->left; } else if(hash < rhash){ rec = rec->right; } else { /*dbuf的结构是rec结构体之后存放了key *TCKEYCMP先比较了两个的keybuffer的大小, *然后再比较值*/ char *dbuf = (char *)rec + sizeof(*rec); int kcmp = TCKEYCMP(kbuf, ksiz, dbuf, rksiz); if(kcmp < 0){ rec = rec->left; } else if(kcmp > 0){ rec = rec->right; } else { *sp = rec->vsiz; /*找到之后,翻译value所在buffer的地址 *通过TCMEMDUP复制内存, *所在在使用完了Value以后,应该释放*/ return dbuf + rksiz + TCALIGNPAD(rksiz); } } }

 

 

你可能感兴趣的:(tokyo cabinet源代码分析(5))