From 0ea663ea01e6cf6b552e99e3416a38ccb56b0a5f Mon Sep 17 00:00:00 2001 From: antirez Date: Fri, 2 Oct 2009 10:23:25 +0200 Subject: [PATCH 1/1] Issue 69 fixed. Object integer encoding now works with replication and MONITORing again. --- Changelog | 5 +++ redis.c | 21 +++++++-- sds.c | 132 +++++++++++++++++++++++++++++++++++++++++------------- sds.h | 6 ++- 4 files changed, 127 insertions(+), 37 deletions(-) diff --git a/Changelog b/Changelog index 1ce4d118..fa9174cd 100644 --- a/Changelog +++ b/Changelog @@ -1,3 +1,8 @@ +2009-09-18 LREM fixed, used to crash since the new object integer encoding is on the stage +2009-09-17 maxmemory didn't worked in 64 systems for values > 4GB since it used to be an unsigned int. Fixed +2009-09-10 incremented version number to 1.001, AKA Redis edge is no longer stable... +2009-09-10 in-memory specialized object encoding (for now 32 signed integers only) +2009-09-03 Latest doc changes for 1.0 2009-09-03 Redis 1.0.0 release 2009-09-02 Redis version pushed to 1.0 2009-09-02 Ruby client lib updated to the latest git version diff --git a/redis.c b/redis.c index 78b53a9d..2edc186f 100644 --- a/redis.c +++ b/redis.c @@ -342,6 +342,7 @@ static void freeMemoryIfNeeded(void); static int processCommand(redisClient *c); static void setupSigSegvAction(void); static void rdbRemoveTempFile(pid_t childpid); +static size_t stringObjectLen(robj *o); static void authCommand(redisClient *c); static void pingCommand(redisClient *c); @@ -1412,7 +1413,8 @@ static void replicationFeedSlaves(list *slaves, struct redisCommand *cmd, int di robj *lenobj; lenobj = createObject(REDIS_STRING, - sdscatprintf(sdsempty(),"%d\r\n",sdslen(argv[j]->ptr))); + sdscatprintf(sdsempty(),"%d\r\n", + stringObjectLen(argv[j]))); lenobj->refcount = 0; outv[outc++] = lenobj; } @@ -1919,6 +1921,17 @@ static int compareStringObjects(robj *a, robj *b) { } } +static size_t stringObjectLen(robj *o) { + assert(o->type == REDIS_STRING); + if (o->encoding == REDIS_ENCODING_RAW) { + return sdslen(o->ptr); + } else { + char buf[32]; + + return snprintf(buf,32,"%ld",(long)o->ptr); + } +} + /*============================ DB saving/loading ============================ */ static int rdbSaveType(FILE *fp, unsigned char type) { @@ -3533,8 +3546,9 @@ static robj *lookupKeyByPattern(redisDb *db, robj *pattern, robj *subst) { int prefixlen, sublen, postfixlen; /* Expoit the internal sds representation to create a sds string allocated on the stack in order to make this function faster */ struct { - long len; - long free; + int len; + unsigned short free; + unsigned short _len; /* not used here */ char buf[REDIS_SORTKEY_MAX+1]; } keyname; @@ -3558,6 +3572,7 @@ static robj *lookupKeyByPattern(redisDb *db, robj *pattern, robj *subst) { memcpy(keyname.buf+prefixlen+sublen,p+1,postfixlen); keyname.buf[prefixlen+sublen+postfixlen] = '\0'; keyname.len = prefixlen+sublen+postfixlen; + keyname._len = USHRT_MAX; keyobj.refcount = 1; keyobj.type = REDIS_STRING; diff --git a/sds.c b/sds.c index 8e9fd96d..b63a4a76 100644 --- a/sds.c +++ b/sds.c @@ -28,6 +28,8 @@ * POSSIBILITY OF SUCH DAMAGE. */ + /* TODO: check if it can happen that _len+free > USHRT_MAX */ + #define SDS_ABORT_ON_OOM #include "sds.h" @@ -46,13 +48,25 @@ static void sdsOomAbort(void) { sds sdsnewlen(const void *init, size_t initlen) { struct sdshdr *sh; - sh = zmalloc(sizeof(struct sdshdr)+initlen+1); -#ifdef SDS_ABORT_ON_OOM - if (sh == NULL) sdsOomAbort(); -#else - if (sh == NULL) return NULL; -#endif - sh->len = initlen; + if (initlen >= USHRT_MAX) { + sh = zmalloc(sizeof(struct sdshdr)+initlen+1); + sh->len = initlen; + sh->_len = USHRT_MAX; + #ifdef SDS_ABORT_ON_OOM + if (sh == NULL) sdsOomAbort(); + #else + if (sh == NULL) return NULL; + #endif + } else { + sh = zmalloc(sizeof(int)+initlen+1); + sh = (struct sdshdr*) (((char*)sh)-sizeof(int)); + #ifdef SDS_ABORT_ON_OOM + if (sh == NULL) sdsOomAbort(); + #else + if (sh == NULL) return NULL; + #endif + sh->_len = initlen; + } sh->free = 0; if (initlen) { if (init) memcpy(sh->buf, init, initlen); @@ -73,7 +87,10 @@ sds sdsnew(const char *init) { size_t sdslen(const sds s) { struct sdshdr *sh = (void*) (s-(sizeof(struct sdshdr))); - return sh->len; + if (sh->_len == USHRT_MAX) + return sh->len; + else + return sh->_len; } sds sdsdup(const sds s) { @@ -81,8 +98,14 @@ sds sdsdup(const sds s) { } void sdsfree(sds s) { + struct sdshdr *sh; + if (s == NULL) return; - zfree(s-sizeof(struct sdshdr)); + sh = (void*) (s-(sizeof(struct sdshdr))); + if (sh->_len == USHRT_MAX) + zfree(s-sizeof(struct sdshdr)); + else + zfree(s-sizeof(struct sdshdr)+sizeof(int)); } size_t sdsavail(sds s) { @@ -93,40 +116,73 @@ size_t sdsavail(sds s) { void sdsupdatelen(sds s) { struct sdshdr *sh = (void*) (s-(sizeof(struct sdshdr))); int reallen = strlen(s); - sh->free += (sh->len-reallen); - sh->len = reallen; + + if (sh->_len == USHRT_MAX) { + sh->free += (sh->len-reallen); + sh->len = reallen; + } else { + sh->free += (sh->_len-reallen); + sh->_len = reallen; + } } static sds sdsMakeRoomFor(sds s, size_t addlen) { struct sdshdr *sh, *newsh; size_t free = sdsavail(s); - size_t len, newlen; + size_t len, newlen, newfree; - if (free >= addlen) return s; + if (free >= addlen) { + sh = (void*) (s-(sizeof(struct sdshdr))); + if (sh->_len == USHRT_MAX) { + sh->len += addlen; + } else { + sh->_len += addlen; + } + sh->free -= addlen; + return s; + } len = sdslen(s); sh = (void*) (s-(sizeof(struct sdshdr))); - newlen = (len+addlen)*2; - newsh = zrealloc(sh, sizeof(struct sdshdr)+newlen+1); + newlen = (len+addlen); + newfree = ((addlen*2) > USHRT_MAX) ? USHRT_MAX : (addlen*2); + if (newlen+newfree >= USHRT_MAX || sh->_len == USHRT_MAX) { + if (sh->_len == USHRT_MAX) { + newsh = zrealloc(sh, sizeof(struct sdshdr)+newlen+1+newfree); + } else { + newsh = zmalloc(sizeof(struct sdshdr)+newlen+1+newfree); + if (!newsh) return NULL; + memcpy(newsh->buf,sh->buf,len); + newsh->buf[len] = '\0'; + zfree(((char*)sh)+sizeof(int)); + } #ifdef SDS_ABORT_ON_OOM - if (newsh == NULL) sdsOomAbort(); + if (newsh == NULL) sdsOomAbort(); #else - if (newsh == NULL) return NULL; + if (newsh == NULL) return NULL; #endif - - newsh->free = newlen - len; + newsh->_len = USHRT_MAX; + newsh->free = newfree; + newsh->len = newlen; + } else { + newsh = zrealloc(((char*)sh)+sizeof(int), sizeof(int)+newlen+1+newfree); + newsh = (struct sdshdr*) (((char*)newsh)-sizeof(int)); +#ifdef SDS_ABORT_ON_OOM + if (newsh == NULL) sdsOomAbort(); +#else + if (newsh == NULL) return NULL; +#endif + newsh->_len = newlen; + newsh->free = newfree; + } return newsh->buf; } sds sdscatlen(sds s, void *t, size_t len) { - struct sdshdr *sh; size_t curlen = sdslen(s); s = sdsMakeRoomFor(s,len); if (s == NULL) return NULL; - sh = (void*) (s-(sizeof(struct sdshdr))); memcpy(s+curlen, t, len); - sh->len = curlen+len; - sh->free = sh->free-len; s[curlen+len] = '\0'; return s; } @@ -137,18 +193,20 @@ sds sdscat(sds s, char *t) { sds sdscpylen(sds s, char *t, size_t len) { struct sdshdr *sh = (void*) (s-(sizeof(struct sdshdr))); - size_t totlen = sh->free+sh->len; + size_t totlen; + + if (sh->_len == USHRT_MAX) { + totlen = sh->free+sh->len; + } else { + totlen = sh->free+sh->_len; + } if (totlen < len) { s = sdsMakeRoomFor(s,len-totlen); if (s == NULL) return NULL; - sh = (void*) (s-(sizeof(struct sdshdr))); - totlen = sh->free+sh->len; } memcpy(s, t, len); s[len] = '\0'; - sh->len = len; - sh->free = totlen-len; return s; } @@ -196,8 +254,13 @@ sds sdstrim(sds s, const char *cset) { len = (sp > ep) ? 0 : ((ep-sp)+1); if (sh->buf != sp) memmove(sh->buf, sp, len); sh->buf[len] = '\0'; - sh->free = sh->free+(sh->len-len); - sh->len = len; + if (sh->_len == USHRT_MAX) { + sh->free = sh->free+(sh->len-len); + sh->len = len; + } else { + sh->free = sh->free+(sh->_len-len); + sh->_len = len; + } return s; } @@ -224,8 +287,13 @@ sds sdsrange(sds s, long start, long end) { } if (start != 0) memmove(sh->buf, sh->buf+start, newlen); sh->buf[newlen] = 0; - sh->free = sh->free+(sh->len-newlen); - sh->len = newlen; + if (sh->_len == USHRT_MAX) { + sh->free = sh->free+(sh->len-newlen); + sh->len = newlen; + } else { + sh->free = sh->free+(sh->_len-newlen); + sh->_len = newlen; + } return s; } diff --git a/sds.h b/sds.h index 0fc2c928..582cb2f3 100644 --- a/sds.h +++ b/sds.h @@ -32,12 +32,14 @@ #define __SDS_H #include +#include typedef char *sds; struct sdshdr { - long len; - long free; + int len; + unsigned short free; + unsigned short _len; /* USHRT_MAX if it is a "long" sds string */ char buf[]; }; -- 2.45.2