undoed all the sds hacking that lead just to random bugs and no memory saving ;)

This commit is contained in:
antirez 2009-10-07 17:34:00 +02:00
parent e8a74421bb
commit f1017b3fb3
3 changed files with 40 additions and 110 deletions

12
redis.c
View File

@ -3623,9 +3623,8 @@ static robj *lookupKeyByPattern(redisDb *db, robj *pattern, robj *subst) {
int prefixlen, sublen, postfixlen; 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 */ /* Expoit the internal sds representation to create a sds string allocated on the stack in order to make this function faster */
struct { struct {
int len; long len;
unsigned short free; long free;
unsigned short _len; /* not used here */
char buf[REDIS_SORTKEY_MAX+1]; char buf[REDIS_SORTKEY_MAX+1];
} keyname; } keyname;
@ -3649,7 +3648,6 @@ static robj *lookupKeyByPattern(redisDb *db, robj *pattern, robj *subst) {
memcpy(keyname.buf+prefixlen+sublen,p+1,postfixlen); memcpy(keyname.buf+prefixlen+sublen,p+1,postfixlen);
keyname.buf[prefixlen+sublen+postfixlen] = '\0'; keyname.buf[prefixlen+sublen+postfixlen] = '\0';
keyname.len = prefixlen+sublen+postfixlen; keyname.len = prefixlen+sublen+postfixlen;
keyname._len = USHRT_MAX;
keyobj.refcount = 1; keyobj.refcount = 1;
keyobj.type = REDIS_STRING; keyobj.type = REDIS_STRING;
@ -3847,9 +3845,9 @@ static void sortCommand(redisClient *c) {
if (byval->encoding == REDIS_ENCODING_RAW) { if (byval->encoding == REDIS_ENCODING_RAW) {
vector[j].u.score = strtod(byval->ptr,NULL); vector[j].u.score = strtod(byval->ptr,NULL);
} else { } else {
if (byval->encoding == REDIS_ENCODING_INT) if (byval->encoding == REDIS_ENCODING_INT) {
vector[j].u.score = (long)byval->ptr; vector[j].u.score = (long)byval->ptr;
else } else
assert(1 != 1); assert(1 != 1);
} }
} }
@ -3936,6 +3934,7 @@ static void infoCommand(redisClient *c) {
info = sdscatprintf(sdsempty(), info = sdscatprintf(sdsempty(),
"redis_version:%s\r\n" "redis_version:%s\r\n"
"arch_bits:%s\r\n"
"uptime_in_seconds:%d\r\n" "uptime_in_seconds:%d\r\n"
"uptime_in_days:%d\r\n" "uptime_in_days:%d\r\n"
"connected_clients:%d\r\n" "connected_clients:%d\r\n"
@ -3948,6 +3947,7 @@ static void infoCommand(redisClient *c) {
"total_commands_processed:%lld\r\n" "total_commands_processed:%lld\r\n"
"role:%s\r\n" "role:%s\r\n"
,REDIS_VERSION, ,REDIS_VERSION,
(sizeof(long) == 8) ? "64" : "32",
uptime, uptime,
uptime/(3600*24), uptime/(3600*24),
listLength(server.clients)-listLength(server.slaves), listLength(server.clients)-listLength(server.slaves),

132
sds.c
View File

@ -28,8 +28,6 @@
* POSSIBILITY OF SUCH DAMAGE. * POSSIBILITY OF SUCH DAMAGE.
*/ */
/* TODO: check if it can happen that _len+free > USHRT_MAX */
#define SDS_ABORT_ON_OOM #define SDS_ABORT_ON_OOM
#include "sds.h" #include "sds.h"
@ -48,25 +46,13 @@ static void sdsOomAbort(void) {
sds sdsnewlen(const void *init, size_t initlen) { sds sdsnewlen(const void *init, size_t initlen) {
struct sdshdr *sh; struct sdshdr *sh;
if (initlen >= USHRT_MAX) { sh = zmalloc(sizeof(struct sdshdr)+initlen+1);
sh = zmalloc(sizeof(struct sdshdr)+initlen+1); #ifdef SDS_ABORT_ON_OOM
sh->len = initlen; if (sh == NULL) sdsOomAbort();
sh->_len = USHRT_MAX; #else
#ifdef SDS_ABORT_ON_OOM if (sh == NULL) return NULL;
if (sh == NULL) sdsOomAbort(); #endif
#else sh->len = initlen;
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; sh->free = 0;
if (initlen) { if (initlen) {
if (init) memcpy(sh->buf, init, initlen); if (init) memcpy(sh->buf, init, initlen);
@ -87,10 +73,7 @@ sds sdsnew(const char *init) {
size_t sdslen(const sds s) { size_t sdslen(const sds s) {
struct sdshdr *sh = (void*) (s-(sizeof(struct sdshdr))); struct sdshdr *sh = (void*) (s-(sizeof(struct sdshdr)));
if (sh->_len == USHRT_MAX) return sh->len;
return sh->len;
else
return sh->_len;
} }
sds sdsdup(const sds s) { sds sdsdup(const sds s) {
@ -98,14 +81,8 @@ sds sdsdup(const sds s) {
} }
void sdsfree(sds s) { void sdsfree(sds s) {
struct sdshdr *sh;
if (s == NULL) return; if (s == NULL) return;
sh = (void*) (s-(sizeof(struct sdshdr))); zfree(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) { size_t sdsavail(sds s) {
@ -116,73 +93,40 @@ size_t sdsavail(sds s) {
void sdsupdatelen(sds s) { void sdsupdatelen(sds s) {
struct sdshdr *sh = (void*) (s-(sizeof(struct sdshdr))); struct sdshdr *sh = (void*) (s-(sizeof(struct sdshdr)));
int reallen = strlen(s); int reallen = strlen(s);
sh->free += (sh->len-reallen);
if (sh->_len == USHRT_MAX) { sh->len = reallen;
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) { static sds sdsMakeRoomFor(sds s, size_t addlen) {
struct sdshdr *sh, *newsh; struct sdshdr *sh, *newsh;
size_t free = sdsavail(s); size_t free = sdsavail(s);
size_t len, newlen, newfree; size_t len, newlen;
if (free >= addlen) { if (free >= addlen) return s;
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); len = sdslen(s);
sh = (void*) (s-(sizeof(struct sdshdr))); sh = (void*) (s-(sizeof(struct sdshdr)));
newlen = (len+addlen); newlen = (len+addlen)*2;
newfree = ((addlen*2) > USHRT_MAX) ? USHRT_MAX : (addlen*2); newsh = zrealloc(sh, sizeof(struct sdshdr)+newlen+1);
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 #ifdef SDS_ABORT_ON_OOM
if (newsh == NULL) sdsOomAbort(); if (newsh == NULL) sdsOomAbort();
#else #else
if (newsh == NULL) return NULL; if (newsh == NULL) return NULL;
#endif #endif
newsh->_len = USHRT_MAX;
newsh->free = newfree; newsh->free = newlen - len;
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; return newsh->buf;
} }
sds sdscatlen(sds s, void *t, size_t len) { sds sdscatlen(sds s, void *t, size_t len) {
struct sdshdr *sh;
size_t curlen = sdslen(s); size_t curlen = sdslen(s);
s = sdsMakeRoomFor(s,len); s = sdsMakeRoomFor(s,len);
if (s == NULL) return NULL; if (s == NULL) return NULL;
sh = (void*) (s-(sizeof(struct sdshdr)));
memcpy(s+curlen, t, len); memcpy(s+curlen, t, len);
sh->len = curlen+len;
sh->free = sh->free-len;
s[curlen+len] = '\0'; s[curlen+len] = '\0';
return s; return s;
} }
@ -193,20 +137,18 @@ sds sdscat(sds s, char *t) {
sds sdscpylen(sds s, char *t, size_t len) { sds sdscpylen(sds s, char *t, size_t len) {
struct sdshdr *sh = (void*) (s-(sizeof(struct sdshdr))); struct sdshdr *sh = (void*) (s-(sizeof(struct sdshdr)));
size_t totlen; size_t totlen = sh->free+sh->len;
if (sh->_len == USHRT_MAX) {
totlen = sh->free+sh->len;
} else {
totlen = sh->free+sh->_len;
}
if (totlen < len) { if (totlen < len) {
s = sdsMakeRoomFor(s,len-totlen); s = sdsMakeRoomFor(s,len-totlen);
if (s == NULL) return NULL; if (s == NULL) return NULL;
sh = (void*) (s-(sizeof(struct sdshdr)));
totlen = sh->free+sh->len;
} }
memcpy(s, t, len); memcpy(s, t, len);
s[len] = '\0'; s[len] = '\0';
sh->len = len;
sh->free = totlen-len;
return s; return s;
} }
@ -254,13 +196,8 @@ sds sdstrim(sds s, const char *cset) {
len = (sp > ep) ? 0 : ((ep-sp)+1); len = (sp > ep) ? 0 : ((ep-sp)+1);
if (sh->buf != sp) memmove(sh->buf, sp, len); if (sh->buf != sp) memmove(sh->buf, sp, len);
sh->buf[len] = '\0'; sh->buf[len] = '\0';
if (sh->_len == USHRT_MAX) { sh->free = sh->free+(sh->len-len);
sh->free = sh->free+(sh->len-len); sh->len = len;
sh->len = len;
} else {
sh->free = sh->free+(sh->_len-len);
sh->_len = len;
}
return s; return s;
} }
@ -287,13 +224,8 @@ sds sdsrange(sds s, long start, long end) {
} }
if (start != 0) memmove(sh->buf, sh->buf+start, newlen); if (start != 0) memmove(sh->buf, sh->buf+start, newlen);
sh->buf[newlen] = 0; sh->buf[newlen] = 0;
if (sh->_len == USHRT_MAX) { sh->free = sh->free+(sh->len-newlen);
sh->free = sh->free+(sh->len-newlen); sh->len = newlen;
sh->len = newlen;
} else {
sh->free = sh->free+(sh->_len-newlen);
sh->_len = newlen;
}
return s; return s;
} }

6
sds.h
View File

@ -32,14 +32,12 @@
#define __SDS_H #define __SDS_H
#include <sys/types.h> #include <sys/types.h>
#include <limits.h>
typedef char *sds; typedef char *sds;
struct sdshdr { struct sdshdr {
int len; long len;
unsigned short free; long free;
unsigned short _len; /* USHRT_MAX if it is a "long" sds string */
char buf[]; char buf[];
}; };