在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;
- }