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