summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorantirez <antirez@gmail.com>2009-10-26 18:26:04 +0100
committerantirez <antirez@gmail.com>2009-10-26 18:26:04 +0100
commita7866db6cc5f68cd577bc9684d10bb048d63788f (patch)
tree858943db170e527d1fdb5d07f2af14af41391501
parent2161a9652725971e2602901410b4a5df0307f57e (diff)
downloadredis-a7866db6cc5f68cd577bc9684d10bb048d63788f.tar.gz
double serialization routines implemented
-rw-r--r--Makefile3
-rw-r--r--redis.c57
2 files changed, 59 insertions, 1 deletions
diff --git a/Makefile b/Makefile
index 43d273237..330df7502 100644
--- a/Makefile
+++ b/Makefile
@@ -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
diff --git a/redis.c b/redis.c
index 6ec243017..e27a364b5 100644
--- a/redis.c
+++ b/redis.c
@@ -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;