diff options
author | antirez <antirez@gmail.com> | 2009-10-26 18:26:04 +0100 |
---|---|---|
committer | antirez <antirez@gmail.com> | 2009-10-26 18:26:04 +0100 |
commit | a7866db6cc5f68cd577bc9684d10bb048d63788f (patch) | |
tree | 858943db170e527d1fdb5d07f2af14af41391501 | |
parent | 2161a9652725971e2602901410b4a5df0307f57e (diff) | |
download | redis-a7866db6cc5f68cd577bc9684d10bb048d63788f.tar.gz |
double serialization routines implemented
-rw-r--r-- | Makefile | 3 | ||||
-rw-r--r-- | redis.c | 57 |
2 files changed, 59 insertions, 1 deletions
@@ -5,9 +5,10 @@ uname_S := $(shell sh -c 'uname -s 2>/dev/null || echo not') ifeq ($(uname_S),SunOS) CFLAGS?= -std=c99 -pedantic -O2 -Wall -W -D__EXTENSIONS__ -D_XPG6 - CCLINK?= -ldl -lnsl -lsocket + CCLINK?= -ldl -lnsl -lsocket -lm else CFLAGS?= -std=c99 -pedantic -O2 -Wall -W + CCLINK?= -lm endif CCOPT= $(CFLAGS) $(CCLINK) $(ARCH) DEBUG?= -g -rdynamic -ggdb @@ -57,6 +57,7 @@ #include <sys/time.h> #include <sys/resource.h> #include <limits.h> +#include <math.h> #include "redis.h" #include "ae.h" /* Event driven programming library */ @@ -338,6 +339,12 @@ struct sharedObjectsStruct { *select5, *select6, *select7, *select8, *select9; } shared; +/* Global vars that are actally used as constants. The following double + * values are used for double on-disk serialization, and are initialized + * at runtime to avoid strange compiler optimizations. */ + +static double R_Zero, R_PosInf, R_NegInf, R_Nan; + /*================================ Prototypes =============================== */ static void freeStringObject(robj *o); @@ -1021,6 +1028,12 @@ static void initServerConfig() { server.masterport = 6379; server.master = NULL; server.replstate = REDIS_REPL_NONE; + + /* Double constants initialization */ + R_Zero = 0.0; + R_PosInf = 1.0/R_Zero; + R_NegInf = -1.0/R_Zero; + R_Nan = R_Zero/R_Zero; } static void initServer() { @@ -2238,6 +2251,33 @@ static int rdbSaveStringObject(FILE *fp, robj *obj) { } } +/* Save a double value. Doubles are saved as strings prefixed by an unsigned + * 8 bit integer specifing the length of the representation. + * This 8 bit integer has special values in order to specify the following + * conditions: + * 253: not a number + * 254: + inf + * 255: - inf + */ +static int rdbSaveDoubleValue(FILE *fp, double val) { + unsigned char buf[128]; + int len; + + if (isnan(val)) { + buf[0] = 253; + len = 1; + } else if (!isfinite(val)) { + len = 1; + buf[0] = (val < 0) ? 255 : 254; + } else { + snprintf((char*)buf+1,sizeof(buf)-1,"%.16g",val); + buf[0] = strlen((char*)buf); + len = buf[0]+1; + } + if (fwrite(buf,len,1,fp) == 0) return -1; + return 0; +} + /* Save the DB on disk. Return REDIS_ERR on error, REDIS_OK on success */ static int rdbSave(char *filename) { dictIterator *di = NULL; @@ -2500,6 +2540,23 @@ static robj *rdbLoadStringObject(FILE*fp, int rdbver) { return tryObjectSharing(createObject(REDIS_STRING,val)); } +/* For information about double serialization check rdbSaveDoubleValue() */ +static int rdbLoadDoubleValue(FILE *fp, double *val) { + char buf[128]; + unsigned char len; + + if (fread(&len,1,1,fp) == 0) return -1; + switch(len) { + case 255: *val = R_NegInf; return 0; + case 254: *val = R_PosInf; return 0; + case 253: *val = R_Nan; return 0; + default: + if (fread(buf,len,1,fp) == 0) return -1; + sscanf(buf, "%lg", val); + return 0; + } +} + static int rdbLoad(char *filename) { FILE *fp; robj *keyobj = NULL; |