2.3資料記錄的寫入
在前面的2節對于記憶體hash memory的基本資料結構進行了分析。通過tcmdbput将key,value結構寫入到記憶體中。
/*通過tcmdbput進行存儲
*先通過key映射到某個map上面
*然後在map上面進行bucket的操作*/
/* Store a record into an on-memory hash database. */
void tcmdbput(TCMDB *mdb, const void *kbuf, int ksiz, const void *vbuf, int vsiz){
assert(mdb && kbuf && ksiz >= 0 && vbuf && vsiz >= 0);
unsigned int mi;
TCMDBHASH(mi, kbuf, ksiz);
if(pthread_rwlock_wrlock((pthread_rwlock_t *)mdb->mmtxs + mi) != 0) return;
tcmapput(mdb->maps[mi], kbuf, ksiz, vbuf, vsiz);
pthread_rwlock_unlock((pthread_rwlock_t *)mdb->mmtxs + mi);
}
2.3.1 Hash算法映射
先通過hash算法,映射到maps資料的元素上。
/*将一個對象存儲在map object中*/
/* Store a record into a map object. */
void tcmapput(TCMAP *map, const void *kbuf, int ksiz, const void *vbuf, int vsiz){
assert(map && kbuf && ksiz >= 0 && vbuf && vsiz >= 0);
if(ksiz > TCMAPKMAXSIZ) ksiz = TCMAPKMAXSIZ;
uint32_t hash;
/*第一次HASH映射到map數組上*/
TCMAPHASH1(hash, kbuf, ksiz);
int bidx = hash % map->bnum;
TCMAPREC *rec = map->buckets[bidx];
/*entp儲存父節點位址*/
TCMAPREC **entp = map->buckets + bidx;
/*第二次HASH映射到特定map的bucket上*/
TCMAPHASH2(hash, kbuf, ksiz);
hash &= ~TCMAPKMAXSIZ;
再通過hash算法,映射到特定maps元素的buckets數組中。即:先找個MAP,再找buckets。
2.3.2記錄初次插入二叉樹
我們先讨論初次加入二叉樹結構的方法。
/*如果為首次加入,則直接放入到buckets中*/
/*計算需要pad的位元組大小*?
int psiz = TCALIGNPAD(ksiz);
map->msiz += ksiz + vsiz;
/*配置設定key,value,pad大小,末尾'/0'
*rec表示了左右子樹,父節點*/
TCMALLOC(rec, sizeof(*rec) + ksiz + psiz + vsiz + 1);
char *dbuf = (char *)rec + sizeof(*rec);
/*在TCMAPREC結構體之後,存放key的内容*/
memcpy(dbuf, kbuf, ksiz);
/*key值通過在末尾增加'/0'分割*/
dbuf[ksiz] = '/0';
rec->ksiz = ksiz | hash;
/*value值的拷貝*/
memcpy(dbuf + ksiz + psiz, vbuf, vsiz);
dbuf[ksiz+psiz+vsiz] = '/0';
/*修改rec記錄的大小*/
rec->vsiz = vsiz;
rec->left = NULL;
rec->right = NULL;
/*record的prev節點指向原先的最後一個節點
*構成雙向連結清單結構,并通過Map的first和last
*節點進行連接配接*/
rec->prev = map->last;
rec->next = NULL;
/*加入到樹中*/
*entp = rec;
/*如果該buckets數組為初次插入節點,則first頭節點指向該記錄*/
if(!map->first) map->first = rec;
/*如果last節點不為空,(已經有插入節點),則将原先節點的next節點
*指向該記錄,然後last節點指向新的記錄,即:将原先的節點都連接配接起來*/
if(map->last) map->last->next = rec;
map->last = rec;
/*record記錄數增加*/
map->rnum++;