天天看點

tokyo cabinet源代碼分析(3)

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++;

繼續閱讀