From 3dffb8e21ed9066caebb6a95d1ac0a58157887c7 Mon Sep 17 00:00:00 2001 From: antirez Date: Mon, 28 Feb 2011 10:01:04 +0100 Subject: [PATCH] save zipmap encoded hashes as blobs. Work in progress. --- src/rdb.c | 32 ++++++++++++++++++-------------- src/redis.h | 2 ++ src/zipmap.c | 10 +++++++--- src/zipmap.h | 3 ++- 4 files changed, 29 insertions(+), 18 deletions(-) diff --git a/src/rdb.c b/src/rdb.c index a9e4b1a0..3d187948 100644 --- a/src/rdb.c +++ b/src/rdb.c @@ -139,7 +139,7 @@ writeerr: } /* Save a string objet as [len][data] on disk. If the object is a string - * representation of an integer value we try to safe it in a special form */ + * representation of an integer value we try to save it in a special form */ int rdbSaveRawString(FILE *fp, unsigned char *s, size_t len) { int enclen; int n, nwritten = 0; @@ -385,20 +385,10 @@ int rdbSaveObject(FILE *fp, robj *o) { } else if (o->type == REDIS_HASH) { /* Save a hash value */ if (o->encoding == REDIS_ENCODING_ZIPMAP) { - unsigned char *p = zipmapRewind(o->ptr); - unsigned int count = zipmapLen(o->ptr); - unsigned char *key, *val; - unsigned int klen, vlen; + size_t l = zipmapBlobLen((unsigned char*)o->ptr); - if ((n = rdbSaveLen(fp,count)) == -1) return -1; + if ((n = rdbSaveRawString(fp,o->ptr,l)) == -1) return -1; nwritten += n; - - while((p = zipmapNext(p,&key,&klen,&val,&vlen)) != NULL) { - if ((n = rdbSaveRawString(fp,key,klen)) == -1) return -1; - nwritten += n; - if ((n = rdbSaveRawString(fp,val,vlen)) == -1) return -1; - nwritten += n; - } } else { dictIterator *di = dictGetIterator(o->ptr); dictEntry *de; @@ -495,8 +485,12 @@ int rdbSave(char *filename) { * handling if the value is swapped out. */ if (!server.vm_enabled || o->storage == REDIS_VM_MEMORY || o->storage == REDIS_VM_SWAPPING) { + int otype = o->type; + + if (otype == REDIS_HASH && o->encoding == REDIS_ENCODING_ZIPMAP) + otype = REDIS_HASH_ZIPMAP; /* Save type, key, value */ - if (rdbSaveType(fp,o->type) == -1) goto werr; + if (rdbSaveType(fp,otype) == -1) goto werr; if (rdbSaveStringObject(fp,&key) == -1) goto werr; if (rdbSaveObject(fp,o) == -1) goto werr; } else { @@ -890,6 +884,16 @@ robj *rdbLoadObject(int type, FILE *fp) { dictAdd((dict*)o->ptr,key,val); } } + } else if (type == REDIS_HASH_ZIPMAP) { + robj *aux = rdbLoadStringObject(fp); + + if (aux == NULL) return NULL; + o = createHashObject(); + o->encoding = REDIS_ENCODING_ZIPMAP; + o->ptr = zmalloc(sdslen(aux->ptr)); + memcpy(o->ptr,aux->ptr,sdslen(aux->ptr)); + decrRefCount(aux); + /* FIXME: conver the object if needed */ } else { redisPanic("Unknown object type"); } diff --git a/src/redis.h b/src/redis.h index 5940bb90..6b03d626 100644 --- a/src/redis.h +++ b/src/redis.h @@ -70,6 +70,8 @@ #define REDIS_ZSET 3 #define REDIS_HASH 4 #define REDIS_VMPOINTER 8 +/* Object types only used for persistence in .rdb files */ +#define REDIS_HASH_ZIPMAP 9 /* Objects encoding. Some kind of objects like Strings and Hashes can be * internally represented in multiple ways. The 'encoding' field of the object diff --git a/src/zipmap.c b/src/zipmap.c index cc7586cf..9f0fc718 100644 --- a/src/zipmap.c +++ b/src/zipmap.c @@ -80,6 +80,7 @@ #include #include #include "zmalloc.h" +#include "endian.h" #define ZIPMAP_BIGLEN 254 #define ZIPMAP_END 255 @@ -108,6 +109,7 @@ static unsigned int zipmapDecodeLength(unsigned char *p) { if (len < ZIPMAP_BIGLEN) return len; memcpy(&len,p+1,sizeof(unsigned int)); + memrev32ifbe(&len); return len; } @@ -123,6 +125,7 @@ static unsigned int zipmapEncodeLength(unsigned char *p, unsigned int len) { } else { p[0] = ZIPMAP_BIGLEN; memcpy(p+1,&len,sizeof(len)); + memrev32ifbe(p+1); return 1+sizeof(len); } } @@ -360,15 +363,16 @@ unsigned int zipmapLen(unsigned char *zm) { return len; } -/* Return zipmap size in bytes. */ -size_t zipmapSize(unsigned char *zm) { +/* Return the raw size in bytes of a zipmap, so that we can serialize + * the zipmap on disk (or everywhere is needed) just writing the returned + * amount of bytes of the C array starting at the zipmap pointer. */ +size_t zipmapBlobLen(unsigned char *zm) { unsigned int totlen; zipmapLookupRaw(zm,NULL,0,&totlen); return totlen; } #ifdef ZIPMAP_TEST_MAIN - void zipmapRepr(unsigned char *p) { unsigned int l; diff --git a/src/zipmap.h b/src/zipmap.h index ae800030..acb25d67 100644 --- a/src/zipmap.h +++ b/src/zipmap.h @@ -43,6 +43,7 @@ unsigned char *zipmapNext(unsigned char *zm, unsigned char **key, unsigned int * int zipmapGet(unsigned char *zm, unsigned char *key, unsigned int klen, unsigned char **value, unsigned int *vlen); int zipmapExists(unsigned char *zm, unsigned char *key, unsigned int klen); unsigned int zipmapLen(unsigned char *zm); -size_t zipmapSize(unsigned char *zm); +size_t zipmapBlobLen(unsigned char *zm); +void zipmapRepr(unsigned char *p); #endif