summaryrefslogtreecommitdiff
path: root/src/t_hash.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/t_hash.c')
-rw-r--r--src/t_hash.c278
1 files changed, 165 insertions, 113 deletions
diff --git a/src/t_hash.c b/src/t_hash.c
index 68d304c50..26089fa72 100644
--- a/src/t_hash.c
+++ b/src/t_hash.c
@@ -35,16 +35,16 @@
*----------------------------------------------------------------------------*/
/* Check the length of a number of objects to see if we need to convert a
- * ziplist to a real hash. Note that we only check string encoded objects
+ * listpack to a real hash. Note that we only check string encoded objects
* as their string length can be queried in constant time. */
void hashTypeTryConversion(robj *o, robj **argv, int start, int end) {
int i;
- if (o->encoding != OBJ_ENCODING_ZIPLIST) return;
+ if (o->encoding != OBJ_ENCODING_LISTPACK) return;
for (i = start; i <= end; i++) {
if (sdsEncodedObject(argv[i]) &&
- sdslen(argv[i]->ptr) > server.hash_max_ziplist_value)
+ sdslen(argv[i]->ptr) > server.hash_max_listpack_value)
{
hashTypeConvert(o, OBJ_ENCODING_HT);
break;
@@ -52,32 +52,30 @@ void hashTypeTryConversion(robj *o, robj **argv, int start, int end) {
}
}
-/* Get the value from a ziplist encoded hash, identified by field.
+/* Get the value from a listpack encoded hash, identified by field.
* Returns -1 when the field cannot be found. */
-int hashTypeGetFromZiplist(robj *o, sds field,
- unsigned char **vstr,
- unsigned int *vlen,
- long long *vll)
+int hashTypeGetFromListpack(robj *o, sds field,
+ unsigned char **vstr,
+ unsigned int *vlen,
+ long long *vll)
{
unsigned char *zl, *fptr = NULL, *vptr = NULL;
- int ret;
- serverAssert(o->encoding == OBJ_ENCODING_ZIPLIST);
+ serverAssert(o->encoding == OBJ_ENCODING_LISTPACK);
zl = o->ptr;
- fptr = ziplistIndex(zl, ZIPLIST_HEAD);
+ fptr = lpFirst(zl);
if (fptr != NULL) {
- fptr = ziplistFind(zl, fptr, (unsigned char*)field, sdslen(field), 1);
+ fptr = lpFind(zl, fptr, (unsigned char*)field, sdslen(field), 1);
if (fptr != NULL) {
/* Grab pointer to the value (fptr points to the field) */
- vptr = ziplistNext(zl, fptr);
+ vptr = lpNext(zl, fptr);
serverAssert(vptr != NULL);
}
}
if (vptr != NULL) {
- ret = ziplistGet(vptr, vstr, vlen, vll);
- serverAssert(ret);
+ *vstr = lpGetValue(vptr, vlen, vll);
return 0;
}
@@ -107,9 +105,9 @@ sds hashTypeGetFromHashTable(robj *o, sds field) {
* can always check the function return by checking the return value
* for C_OK and checking if vll (or vstr) is NULL. */
int hashTypeGetValue(robj *o, sds field, unsigned char **vstr, unsigned int *vlen, long long *vll) {
- if (o->encoding == OBJ_ENCODING_ZIPLIST) {
+ if (o->encoding == OBJ_ENCODING_LISTPACK) {
*vstr = NULL;
- if (hashTypeGetFromZiplist(o, field, vstr, vlen, vll) == 0)
+ if (hashTypeGetFromListpack(o, field, vstr, vlen, vll) == 0)
return C_OK;
} else if (o->encoding == OBJ_ENCODING_HT) {
sds value;
@@ -143,12 +141,12 @@ robj *hashTypeGetValueObject(robj *o, sds field) {
* exist. */
size_t hashTypeGetValueLength(robj *o, sds field) {
size_t len = 0;
- if (o->encoding == OBJ_ENCODING_ZIPLIST) {
+ if (o->encoding == OBJ_ENCODING_LISTPACK) {
unsigned char *vstr = NULL;
unsigned int vlen = UINT_MAX;
long long vll = LLONG_MAX;
- if (hashTypeGetFromZiplist(o, field, &vstr, &vlen, &vll) == 0)
+ if (hashTypeGetFromListpack(o, field, &vstr, &vlen, &vll) == 0)
len = vstr ? vlen : sdigits10(vll);
} else if (o->encoding == OBJ_ENCODING_HT) {
sds aux;
@@ -164,12 +162,12 @@ size_t hashTypeGetValueLength(robj *o, sds field) {
/* Test if the specified field exists in the given hash. Returns 1 if the field
* exists, and 0 when it doesn't. */
int hashTypeExists(robj *o, sds field) {
- if (o->encoding == OBJ_ENCODING_ZIPLIST) {
+ if (o->encoding == OBJ_ENCODING_LISTPACK) {
unsigned char *vstr = NULL;
unsigned int vlen = UINT_MAX;
long long vll = LLONG_MAX;
- if (hashTypeGetFromZiplist(o, field, &vstr, &vlen, &vll) == 0) return 1;
+ if (hashTypeGetFromListpack(o, field, &vstr, &vlen, &vll) == 0) return 1;
} else if (o->encoding == OBJ_ENCODING_HT) {
if (hashTypeGetFromHashTable(o, field) != NULL) return 1;
} else {
@@ -202,36 +200,33 @@ int hashTypeExists(robj *o, sds field) {
int hashTypeSet(robj *o, sds field, sds value, int flags) {
int update = 0;
- if (o->encoding == OBJ_ENCODING_ZIPLIST) {
+ if (o->encoding == OBJ_ENCODING_LISTPACK) {
unsigned char *zl, *fptr, *vptr;
zl = o->ptr;
- fptr = ziplistIndex(zl, ZIPLIST_HEAD);
+ fptr = lpFirst(zl);
if (fptr != NULL) {
- fptr = ziplistFind(zl, fptr, (unsigned char*)field, sdslen(field), 1);
+ fptr = lpFind(zl, fptr, (unsigned char*)field, sdslen(field), 1);
if (fptr != NULL) {
/* Grab pointer to the value (fptr points to the field) */
- vptr = ziplistNext(zl, fptr);
+ vptr = lpNext(zl, fptr);
serverAssert(vptr != NULL);
update = 1;
/* Replace value */
- zl = ziplistReplace(zl, vptr, (unsigned char*)value,
- sdslen(value));
+ zl = lpReplace(zl, &vptr, (unsigned char*)value, sdslen(value));
}
}
if (!update) {
- /* Push new field/value pair onto the tail of the ziplist */
- zl = ziplistPush(zl, (unsigned char*)field, sdslen(field),
- ZIPLIST_TAIL);
- zl = ziplistPush(zl, (unsigned char*)value, sdslen(value),
- ZIPLIST_TAIL);
+ /* Push new field/value pair onto the tail of the listpack */
+ zl = lpAppend(zl, (unsigned char*)field, sdslen(field));
+ zl = lpAppend(zl, (unsigned char*)value, sdslen(value));
}
o->ptr = zl;
- /* Check if the ziplist needs to be converted to a hash table */
- if (hashTypeLength(o) > server.hash_max_ziplist_entries)
+ /* Check if the listpack needs to be converted to a hash table */
+ if (hashTypeLength(o) > server.hash_max_listpack_entries)
hashTypeConvert(o, OBJ_ENCODING_HT);
} else if (o->encoding == OBJ_ENCODING_HT) {
dictEntry *de = dictFind(o->ptr,field);
@@ -276,16 +271,16 @@ int hashTypeSet(robj *o, sds field, sds value, int flags) {
int hashTypeDelete(robj *o, sds field) {
int deleted = 0;
- if (o->encoding == OBJ_ENCODING_ZIPLIST) {
+ if (o->encoding == OBJ_ENCODING_LISTPACK) {
unsigned char *zl, *fptr;
zl = o->ptr;
- fptr = ziplistIndex(zl, ZIPLIST_HEAD);
+ fptr = lpFirst(zl);
if (fptr != NULL) {
- fptr = ziplistFind(zl, fptr, (unsigned char*)field, sdslen(field), 1);
+ fptr = lpFind(zl, fptr, (unsigned char*)field, sdslen(field), 1);
if (fptr != NULL) {
- zl = ziplistDelete(zl,&fptr); /* Delete the key. */
- zl = ziplistDelete(zl,&fptr); /* Delete the value. */
+ zl = lpDelete(zl,fptr,&fptr); /* Delete the key. */
+ zl = lpDelete(zl,fptr,&fptr); /* Delete the value. */
o->ptr = zl;
deleted = 1;
}
@@ -308,8 +303,8 @@ int hashTypeDelete(robj *o, sds field) {
unsigned long hashTypeLength(const robj *o) {
unsigned long length = ULONG_MAX;
- if (o->encoding == OBJ_ENCODING_ZIPLIST) {
- length = ziplistLen(o->ptr) / 2;
+ if (o->encoding == OBJ_ENCODING_LISTPACK) {
+ length = lpLength(o->ptr) / 2;
} else if (o->encoding == OBJ_ENCODING_HT) {
length = dictSize((const dict*)o->ptr);
} else {
@@ -323,7 +318,7 @@ hashTypeIterator *hashTypeInitIterator(robj *subject) {
hi->subject = subject;
hi->encoding = subject->encoding;
- if (hi->encoding == OBJ_ENCODING_ZIPLIST) {
+ if (hi->encoding == OBJ_ENCODING_LISTPACK) {
hi->fptr = NULL;
hi->vptr = NULL;
} else if (hi->encoding == OBJ_ENCODING_HT) {
@@ -343,7 +338,7 @@ void hashTypeReleaseIterator(hashTypeIterator *hi) {
/* Move to the next entry in the hash. Return C_OK when the next entry
* could be found and C_ERR when the iterator reaches the end. */
int hashTypeNext(hashTypeIterator *hi) {
- if (hi->encoding == OBJ_ENCODING_ZIPLIST) {
+ if (hi->encoding == OBJ_ENCODING_LISTPACK) {
unsigned char *zl;
unsigned char *fptr, *vptr;
@@ -354,16 +349,16 @@ int hashTypeNext(hashTypeIterator *hi) {
if (fptr == NULL) {
/* Initialize cursor */
serverAssert(vptr == NULL);
- fptr = ziplistIndex(zl, 0);
+ fptr = lpFirst(zl);
} else {
/* Advance cursor */
serverAssert(vptr != NULL);
- fptr = ziplistNext(zl, vptr);
+ fptr = lpNext(zl, vptr);
}
if (fptr == NULL) return C_ERR;
/* Grab pointer to the value (fptr points to the field) */
- vptr = ziplistNext(zl, fptr);
+ vptr = lpNext(zl, fptr);
serverAssert(vptr != NULL);
/* fptr, vptr now point to the first or next pair */
@@ -378,22 +373,18 @@ int hashTypeNext(hashTypeIterator *hi) {
}
/* Get the field or value at iterator cursor, for an iterator on a hash value
- * encoded as a ziplist. Prototype is similar to `hashTypeGetFromZiplist`. */
-void hashTypeCurrentFromZiplist(hashTypeIterator *hi, int what,
- unsigned char **vstr,
- unsigned int *vlen,
- long long *vll)
+ * encoded as a listpack. Prototype is similar to `hashTypeGetFromListpack`. */
+void hashTypeCurrentFromListpack(hashTypeIterator *hi, int what,
+ unsigned char **vstr,
+ unsigned int *vlen,
+ long long *vll)
{
- int ret;
-
- serverAssert(hi->encoding == OBJ_ENCODING_ZIPLIST);
+ serverAssert(hi->encoding == OBJ_ENCODING_LISTPACK);
if (what & OBJ_HASH_KEY) {
- ret = ziplistGet(hi->fptr, vstr, vlen, vll);
- serverAssert(ret);
+ *vstr = lpGetValue(hi->fptr, vlen, vll);
} else {
- ret = ziplistGet(hi->vptr, vstr, vlen, vll);
- serverAssert(ret);
+ *vstr = lpGetValue(hi->vptr, vlen, vll);
}
}
@@ -421,9 +412,9 @@ sds hashTypeCurrentFromHashTable(hashTypeIterator *hi, int what) {
* can always check the function return by checking the return value
* type checking if vstr == NULL. */
void hashTypeCurrentObject(hashTypeIterator *hi, int what, unsigned char **vstr, unsigned int *vlen, long long *vll) {
- if (hi->encoding == OBJ_ENCODING_ZIPLIST) {
+ if (hi->encoding == OBJ_ENCODING_LISTPACK) {
*vstr = NULL;
- hashTypeCurrentFromZiplist(hi, what, vstr, vlen, vll);
+ hashTypeCurrentFromListpack(hi, what, vstr, vlen, vll);
} else if (hi->encoding == OBJ_ENCODING_HT) {
sds ele = hashTypeCurrentFromHashTable(hi, what);
*vstr = (unsigned char*) ele;
@@ -456,10 +447,11 @@ robj *hashTypeLookupWriteOrCreate(client *c, robj *key) {
return o;
}
-void hashTypeConvertZiplist(robj *o, int enc) {
- serverAssert(o->encoding == OBJ_ENCODING_ZIPLIST);
- if (enc == OBJ_ENCODING_ZIPLIST) {
+void hashTypeConvertListpack(robj *o, int enc) {
+ serverAssert(o->encoding == OBJ_ENCODING_LISTPACK);
+
+ if (enc == OBJ_ENCODING_LISTPACK) {
/* Nothing to do... */
} else if (enc == OBJ_ENCODING_HT) {
@@ -480,9 +472,9 @@ void hashTypeConvertZiplist(robj *o, int enc) {
value = hashTypeCurrentObjectNewSds(hi,OBJ_HASH_VALUE);
ret = dictAdd(dict, key, value);
if (ret != DICT_OK) {
- serverLogHexDump(LL_WARNING,"ziplist with dup elements dump",
- o->ptr,ziplistBlobLen(o->ptr));
- serverPanic("Ziplist corruption detected");
+ serverLogHexDump(LL_WARNING,"listpack with dup elements dump",
+ o->ptr,lpBytes(o->ptr));
+ serverPanic("Listpack corruption detected");
}
}
hashTypeReleaseIterator(hi);
@@ -495,8 +487,8 @@ void hashTypeConvertZiplist(robj *o, int enc) {
}
void hashTypeConvert(robj *o, int enc) {
- if (o->encoding == OBJ_ENCODING_ZIPLIST) {
- hashTypeConvertZiplist(o, enc);
+ if (o->encoding == OBJ_ENCODING_LISTPACK) {
+ hashTypeConvertListpack(o, enc);
} else if (o->encoding == OBJ_ENCODING_HT) {
serverPanic("Not implemented");
} else {
@@ -515,13 +507,13 @@ robj *hashTypeDup(robj *o) {
serverAssert(o->type == OBJ_HASH);
- if(o->encoding == OBJ_ENCODING_ZIPLIST){
+ if(o->encoding == OBJ_ENCODING_LISTPACK) {
unsigned char *zl = o->ptr;
- size_t sz = ziplistBlobLen(zl);
+ size_t sz = lpBytes(zl);
unsigned char *new_zl = zmalloc(sz);
memcpy(new_zl, zl, sz);
hobj = createObject(OBJ_HASH, new_zl);
- hobj->encoding = OBJ_ENCODING_ZIPLIST;
+ hobj->encoding = OBJ_ENCODING_LISTPACK;
} else if(o->encoding == OBJ_ENCODING_HT){
dict *d = dictCreate(&hashDictType);
dictExpand(d, dictSize((const dict*)o->ptr));
@@ -549,20 +541,25 @@ robj *hashTypeDup(robj *o) {
return hobj;
}
-/* callback for to check the ziplist doesn't have duplicate records */
-static int _hashZiplistEntryValidation(unsigned char *p, void *userdata) {
+/* callback for hashZiplistConvertAndValidateIntegrity.
+ * Check that the ziplist doesn't have duplicate hash field names.
+ * The ziplist element pointed by 'p' will be converted and stored into listpack. */
+static int _hashZiplistEntryConvertAndValidation(unsigned char *p, void *userdata) {
+ unsigned char *str;
+ unsigned int slen;
+ long long vll;
+
struct {
long count;
dict *fields;
+ unsigned char **lp;
} *data = userdata;
+ if (!ziplistGet(p, &str, &slen, &vll))
+ return 0;
+
/* Even 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 */
@@ -571,16 +568,70 @@ static int _hashZiplistEntryValidation(unsigned char *p, void *userdata) {
}
}
+ if (str) {
+ *(data->lp) = lpAppend(*(data->lp), (unsigned char*)str, slen);
+ } else {
+ *(data->lp) = lpAppendInteger(*(data->lp), vll);
+ }
+
+ (data->count)++;
+ return 1;
+}
+
+/* callback for to check the listpack doesn't have duplicate records */
+static int _hashListpackEntryValidation(unsigned char *p, void *userdata) {
+ struct {
+ long count;
+ dict *fields;
+ } *data = userdata;
+
+ /* Even records are field names, add to dict and check that's not a dup */
+ if (((data->count) & 1) == 0) {
+ unsigned char *str;
+ int64_t slen;
+ unsigned char buf[LP_INTBUF_SIZE];
+
+ str = lpGet(p, &slen, buf);
+ sds field = sdsnewlen(str, slen);
+ if (dictAdd(data->fields, field, NULL) != DICT_OK) {
+ /* Duplicate, return an error */
+ sdsfree(field);
+ return 0;
+ }
+ }
+
(data->count)++;
return 1;
}
-/* Validate the integrity of the data structure.
+/* Validate the integrity of the data structure while converting it to
+ * listpack and storing it at 'lp'.
+ * The function is safe to call on non-validated ziplists, it returns 0
+ * when encounter an integrity validation issue. */
+int hashZiplistConvertAndValidateIntegrity(unsigned char *zl, size_t size, unsigned char **lp) {
+ /* Keep track of the field names to locate duplicate ones */
+ struct {
+ long count;
+ dict *fields;
+ unsigned char **lp;
+ } data = {0, dictCreate(&hashDictType), lp};
+
+ int ret = ziplistValidateIntegrity(zl, size, 1, _hashZiplistEntryConvertAndValidation, &data);
+
+ /* make sure we have an even number of records. */
+ if (data.count & 1)
+ ret = 0;
+
+ dictRelease(data.fields);
+ return ret;
+}
+
+/* Validate the integrity of the listpack structure.
* when `deep` is 0, only the integrity of the header is validated.
* when `deep` is 1, we scan all the entries one by one. */
-int hashZiplistValidateIntegrity(unsigned char *zl, size_t size, int deep) {
+int hashListpackValidateIntegrity(unsigned char *lp, size_t size, int deep) {
if (!deep)
- return ziplistValidateIntegrity(zl, size, 0, NULL, NULL);
+ return lpValidateIntegrity(lp, size, 0, NULL, NULL);
/* Keep track of the field names to locate duplicate ones */
struct {
@@ -588,7 +639,7 @@ int hashZiplistValidateIntegrity(unsigned char *zl, size_t size, int deep) {
dict *fields;
} data = {0, dictCreate(&hashDictType)};
- int ret = ziplistValidateIntegrity(zl, size, 1, _hashZiplistEntryValidation, &data);
+ int ret = lpValidateIntegrity(lp, size, 1, _hashListpackEntryValidation, &data);
/* make sure we have an even number of records. */
if (data.count & 1)
@@ -598,13 +649,13 @@ int hashZiplistValidateIntegrity(unsigned char *zl, size_t size, int deep) {
return ret;
}
-/* Create a new sds string from the ziplist entry. */
-sds hashSdsFromZiplistEntry(ziplistEntry *e) {
+/* Create a new sds string from the listpack entry. */
+sds hashSdsFromListpackEntry(listpackEntry *e) {
return e->sval ? sdsnewlen(e->sval, e->slen) : sdsfromlonglong(e->lval);
}
-/* Reply with bulk string from the ziplist entry. */
-void hashReplyFromZiplistEntry(client *c, ziplistEntry *e) {
+/* Reply with bulk string from the listpack entry. */
+void hashReplyFromListpackEntry(client *c, listpackEntry *e) {
if (e->sval)
addReplyBulkCBuffer(c, e->sval, e->slen);
else
@@ -615,7 +666,7 @@ void hashReplyFromZiplistEntry(client *c, ziplistEntry *e) {
* 'key' and 'val' will be set to hold the element.
* The memory in them is not to be freed or modified by the caller.
* 'val' can be NULL in which case it's not extracted. */
-void hashTypeRandomElement(robj *hashobj, unsigned long hashsize, ziplistEntry *key, ziplistEntry *val) {
+void hashTypeRandomElement(robj *hashobj, unsigned long hashsize, listpackEntry *key, listpackEntry *val) {
if (hashobj->encoding == OBJ_ENCODING_HT) {
dictEntry *de = dictGetFairRandomKey(hashobj->ptr);
sds s = dictGetKey(de);
@@ -626,8 +677,8 @@ void hashTypeRandomElement(robj *hashobj, unsigned long hashsize, ziplistEntry *
val->sval = (unsigned char*)s;
val->slen = sdslen(s);
}
- } else if (hashobj->encoding == OBJ_ENCODING_ZIPLIST) {
- ziplistRandomPair(hashobj->ptr, hashsize, key, val);
+ } else if (hashobj->encoding == OBJ_ENCODING_LISTPACK) {
+ lpRandomPair(hashobj->ptr, hashsize, key, val);
} else {
serverPanic("Unknown hash encoding");
}
@@ -774,12 +825,12 @@ static void addHashFieldToReply(client *c, robj *o, sds field) {
return;
}
- if (o->encoding == OBJ_ENCODING_ZIPLIST) {
+ if (o->encoding == OBJ_ENCODING_LISTPACK) {
unsigned char *vstr = NULL;
unsigned int vlen = UINT_MAX;
long long vll = LLONG_MAX;
- ret = hashTypeGetFromZiplist(o, field, &vstr, &vlen, &vll);
+ ret = hashTypeGetFromListpack(o, field, &vstr, &vlen, &vll);
if (ret < 0) {
addReplyNull(c);
} else {
@@ -871,12 +922,12 @@ void hstrlenCommand(client *c) {
}
static void addHashIteratorCursorToReply(client *c, hashTypeIterator *hi, int what) {
- if (hi->encoding == OBJ_ENCODING_ZIPLIST) {
+ if (hi->encoding == OBJ_ENCODING_LISTPACK) {
unsigned char *vstr = NULL;
unsigned int vlen = UINT_MAX;
long long vll = LLONG_MAX;
- hashTypeCurrentFromZiplist(hi, what, &vstr, &vlen, &vll);
+ hashTypeCurrentFromListpack(hi, what, &vstr, &vlen, &vll);
if (vstr)
addReplyBulkCBuffer(c, vstr, vlen);
else
@@ -957,7 +1008,7 @@ void hscanCommand(client *c) {
scanGenericCommand(c,o,cursor);
}
-static void harndfieldReplyWithZiplist(client *c, unsigned int count, ziplistEntry *keys, ziplistEntry *vals) {
+static void harndfieldReplyWithListpack(client *c, unsigned int count, listpackEntry *keys, listpackEntry *vals) {
for (unsigned long i = 0; i < count; i++) {
if (vals && c->resp > 2)
addReplyArrayLen(c,2);
@@ -1028,18 +1079,19 @@ void hrandfieldWithCountCommand(client *c, long l, int withvalues) {
if (withvalues)
addReplyBulkCBuffer(c, value, sdslen(value));
}
- } else if (hash->encoding == OBJ_ENCODING_ZIPLIST) {
- ziplistEntry *keys, *vals = NULL;
+ } else if (hash->encoding == OBJ_ENCODING_LISTPACK) {
+ listpackEntry *keys, *vals = NULL;
unsigned long limit, sample_count;
+
limit = count > HRANDFIELD_RANDOM_SAMPLE_LIMIT ? HRANDFIELD_RANDOM_SAMPLE_LIMIT : count;
- keys = zmalloc(sizeof(ziplistEntry)*limit);
+ keys = zmalloc(sizeof(listpackEntry)*limit);
if (withvalues)
- vals = zmalloc(sizeof(ziplistEntry)*limit);
+ vals = zmalloc(sizeof(listpackEntry)*limit);
while (count) {
sample_count = count > limit ? limit : count;
count -= sample_count;
- ziplistRandomPairs(hash->ptr, sample_count, keys, vals);
- harndfieldReplyWithZiplist(c, sample_count, keys, vals);
+ lpRandomPairs(hash->ptr, sample_count, keys, vals);
+ harndfieldReplyWithListpack(c, sample_count, keys, vals);
}
zfree(keys);
zfree(vals);
@@ -1133,15 +1185,15 @@ void hrandfieldWithCountCommand(client *c, long l, int withvalues) {
* to the temporary hash, trying to eventually get enough unique elements
* to reach the specified count. */
else {
- if (hash->encoding == OBJ_ENCODING_ZIPLIST) {
+ if (hash->encoding == OBJ_ENCODING_LISTPACK) {
/* it is inefficient to repeatedly pick one random element from a
- * ziplist. so we use this instead: */
- ziplistEntry *keys, *vals = NULL;
- keys = zmalloc(sizeof(ziplistEntry)*count);
+ * listpack. so we use this instead: */
+ listpackEntry *keys, *vals = NULL;
+ keys = zmalloc(sizeof(listpackEntry)*count);
if (withvalues)
- vals = zmalloc(sizeof(ziplistEntry)*count);
- serverAssert(ziplistRandomPairsUnique(hash->ptr, count, keys, vals) == count);
- harndfieldReplyWithZiplist(c, count, keys, vals);
+ vals = zmalloc(sizeof(listpackEntry)*count);
+ serverAssert(lpRandomPairsUnique(hash->ptr, count, keys, vals) == count);
+ harndfieldReplyWithListpack(c, count, keys, vals);
zfree(keys);
zfree(vals);
return;
@@ -1149,7 +1201,7 @@ void hrandfieldWithCountCommand(client *c, long l, int withvalues) {
/* Hashtable encoding (generic implementation) */
unsigned long added = 0;
- ziplistEntry key, value;
+ listpackEntry key, value;
dict *d = dictCreate(&hashDictType);
dictExpand(d, count);
while(added < count) {
@@ -1158,7 +1210,7 @@ void hrandfieldWithCountCommand(client *c, long l, int withvalues) {
/* Try to add the object to the dictionary. If it already exists
* free it, otherwise increment the number of objects we have
* in the result dictionary. */
- sds skey = hashSdsFromZiplistEntry(&key);
+ sds skey = hashSdsFromListpackEntry(&key);
if (dictAdd(d,skey,NULL) != DICT_OK) {
sdsfree(skey);
continue;
@@ -1168,9 +1220,9 @@ void hrandfieldWithCountCommand(client *c, long l, int withvalues) {
/* We can reply right away, so that we don't need to store the value in the dict. */
if (withvalues && c->resp > 2)
addReplyArrayLen(c,2);
- hashReplyFromZiplistEntry(c, &key);
+ hashReplyFromListpackEntry(c, &key);
if (withvalues)
- hashReplyFromZiplistEntry(c, &value);
+ hashReplyFromListpackEntry(c, &value);
}
/* Release memory */
@@ -1183,7 +1235,7 @@ void hrandfieldCommand(client *c) {
long l;
int withvalues = 0;
robj *hash;
- ziplistEntry ele;
+ listpackEntry ele;
if (c->argc >= 3) {
if (getLongFromObjectOrReply(c,c->argv[2],&l,NULL) != C_OK) return;
@@ -1203,5 +1255,5 @@ void hrandfieldCommand(client *c) {
}
hashTypeRandomElement(hash,hashTypeLength(hash),&ele,NULL);
- hashReplyFromZiplistEntry(c, &ele);
+ hashReplyFromListpackEntry(c, &ele);
}