在redis源码中,hash的思想无处不在,这不,又见到了:
/* This is a helper function for the COPY command.
* Duplicate a hash object, with the guarantee that the returned object
* has the same encoding as the original one.
*
* The resulting object always has refcount set to 1 */
robj *hashTypeDup(robj *o) {
robj *hobj;
hashTypeIterator *hi;
serverAssert(o->type == OBJ_HASH);
if(o->encoding == OBJ_ENCODING_ZIPLIST){
unsigned char *zl = o->ptr;
size_t sz = ziplistBlobLen(zl);
unsigned char *new_zl = zmalloc(sz);
memcpy(new_zl, zl, sz);
hobj = createObject(OBJ_HASH, new_zl);
hobj->encoding = OBJ_ENCODING_ZIPLIST;
} else if(o->encoding == OBJ_ENCODING_HT){
dict *d = dictCreate(&hashDictType, NULL);
dictExpand(d, dictSize((const dict*)o->ptr));
hi = hashTypeInitIterator(o);
while (hashTypeNext(hi) != C_ERR) {
sds field, value;
sds newfield, newvalue;
/* Extract a field-value pair from an original hash object.*/
field = hashTypeCurrentFromHashTable(hi, OBJ_HASH_KEY);
value = hashTypeCurrentFromHashTable(hi, OBJ_HASH_VALUE);
newfield = sdsdup(field);
newvalue = sdsdup(value);
/* Add a field-value pair to a new hash object. */
dictAdd(d,newfield,newvalue);
}
hashTypeReleaseIterator(hi);
hobj = createObject(OBJ_HASH, d);
hobj->encoding = OBJ_ENCODING_HT;
} else {
serverPanic("Unknown hash encoding");
}
return hobj;
}
/* callback for to check the ziplist doesn't have duplicate recoreds */
static int _hashZiplistEntryValidation(unsigned char *p, void *userdata) {
struct {
long count;
dict *fields;
} *data = userdata;
/* Odd records are field names, add to dict and check that's not a dup */
if (((data->count) & 1) == 0) {
unsigned char *str;
unsigned int slen;
long long vll;
if (!ziplistGet(p, &str, &slen, &vll))
return 0;
sds field = str? sdsnewlen(str, slen): sdsfromlonglong(vll);;
if (dictAdd(data->fields, field, NULL) != DICT_OK) {
/* Duplicate, return an error */
sdsfree(field);
return 0;
}
}
(data->count)++;
return 1;
}