/* Get the value from a ziplist encoded hash, identified by field. * Returns -1 when the field cannot be found. */ int hashTypeGetFromZiplist(robj *o, robj *field, unsigned char **vstr, unsigned int *vlen, long long *vll) { unsigned char *zl, *fptr = NULL, *vptr = NULL; int ret; logicErrorExpr(o->encoding == REDIS_ENCODING_ZIPLIST, "Never happend"); field = getDecodedObject(field); zl = o->ptr; fptr = ziplistIndex(zl, ZIPLIST_HEAD); if (fptr != NULL) { fptr = ziplistFind(fptr, field->ptr, sdslen(field->ptr), 1); if (fptr != NULL) { /* Grab pointer to the value (fptr points to the field) */ vptr = ziplistNext(zl, fptr); logicErrorExpr(vptr != NULL, "Never happend"); } } decrRefCount(field); if (vptr != NULL) { ret = ziplistGet(vptr, vstr, vlen, vll); logicErrorExpr(ret, "Never happend"); return 0; } return -1; }
void test_add_delete_and_find_node_wtih_ziplist(void) { unsigned char *zl = ziplistNew(); // add first node zl = ziplistPush(zl, (unsigned char*)"hello", 5, ZIPLIST_TAIL); assert( ziplistLen(zl) == 1 ); assert( ziplistFind(zl, (unsigned char*)"hello", 5, 0) != NULL) ; // add second node zl = ziplistPush(zl, (unsigned char*)"moto", 4, ZIPLIST_TAIL); assert( ziplistLen(zl) == 2 ); assert( ziplistFind(zl, (unsigned char*)"moto", 4, 0) != NULL); // delete first node unsigned char* node_p = ziplistFind(zl, (unsigned char*)"hello", 5, 0); zl = ziplistDelete(zl, &node_p); assert( ziplistFind(zl, (unsigned char*)"hello", 5, 0) == NULL ); assert( ziplistLen(zl) == 1 ); // release memory zfree(zl); }
/* Add an element, discard the old if the key already exists. * Return 0 on insert and 1 on update. * This function will take care of incrementing the reference count of the * retained fields and value objects. */ int hashTypeSet(robj *o, robj *field, robj *value) { int update = 0; if (o->encoding == REDIS_ENCODING_ZIPLIST) { unsigned char *zl, *fptr, *vptr; field = getDecodedObject(field); value = getDecodedObject(value); zl = o->ptr; fptr = ziplistIndex(zl, ZIPLIST_HEAD); if (fptr != NULL) { fptr = ziplistFind(fptr, field->ptr, sdslen(field->ptr), 1); if (fptr != NULL) { /* Grab pointer to the value (fptr points to the field) */ vptr = ziplistNext(zl, fptr); logicErrorExpr(vptr != NULL, "Never happend"); update = 1; /* Delete value */ zl = ziplistDelete(zl, &vptr); /* Insert new value */ zl = ziplistInsert(zl, vptr, value->ptr, sdslen(value->ptr)); } } if (!update) { /* Push new field/value pair onto the tail of the ziplist */ zl = ziplistPush(zl, field->ptr, sdslen(field->ptr), ZIPLIST_TAIL); zl = ziplistPush(zl, value->ptr, sdslen(value->ptr), ZIPLIST_TAIL); } o->ptr = zl; decrRefCount(field); decrRefCount(value); /* Check if the ziplist needs to be converted to a hash table */ if (hashTypeLength(o) > server.hash_max_ziplist_entries) hashTypeConvert(o, REDIS_ENCODING_HT); } else if (o->encoding == REDIS_ENCODING_HT) { if (dictReplace(o->ptr, field, value)) { /* Insert */ incrRefCount(field); } else { /* Update */ update = 1; } incrRefCount(value); } else { logicError("Unknown hash encoding"); } return update; }
/* Get the value from a ziplist encoded hash, identified by field. * Returns -1 when the field cannot be found. */ int hashTypeGetFromZiplist(robj *o, robj *field, unsigned char **vstr, unsigned int *vlen, PORT_LONGLONG *vll) { unsigned char *zl, *fptr = NULL, *vptr = NULL; int ret; redisAssert(o->encoding == REDIS_ENCODING_ZIPLIST); field = getDecodedObject(field); zl = o->ptr; fptr = ziplistIndex(zl, ZIPLIST_HEAD); if (fptr != NULL) { fptr = ziplistFind(fptr, field->ptr, (unsigned int)sdslen(field->ptr), 1); WIN_PORT_FIX /* cast (unsigned int) */ if (fptr != NULL) { /* Grab pointer to the value (fptr points to the field) */ vptr = ziplistNext(zl, fptr); redisAssert(vptr != NULL); } }
/* Delete an element from a hash. * Return 1 on deleted and 0 on not found. */ int hashTypeDelete(robj *o, robj *field) { int deleted = 0; if (o->encoding == REDIS_ENCODING_ZIPLIST) { unsigned char *zl, *fptr; field = getDecodedObject(field); zl = o->ptr; fptr = ziplistIndex(zl, ZIPLIST_HEAD); if (fptr != NULL) { fptr = ziplistFind(fptr, field->ptr, sdslen(field->ptr), 1); if (fptr != NULL) { zl = ziplistDelete(zl,&fptr); zl = ziplistDelete(zl,&fptr); o->ptr = zl; deleted = 1; } } decrRefCount(field); } else if (o->encoding == REDIS_ENCODING_HT) { if (dictDelete((dict*)o->ptr, field) == REDIS_OK) { deleted = 1; /* Always check if the dictionary needs a resize after a delete. */ if (htNeedsResize(o->ptr)) dictResize(o->ptr); } } else { logicError("Unknown hash encoding"); } return deleted; }