]> git.saurik.com Git - redis.git/commitdiff
double serialization routines implemented
authorantirez <antirez@gmail.com>
Mon, 26 Oct 2009 17:26:04 +0000 (18:26 +0100)
committerantirez <antirez@gmail.com>
Mon, 26 Oct 2009 17:26:04 +0000 (18:26 +0100)
Makefile
redis.c

index 43d273237e50493cced8687c62bb7626e60650c1..330df7502965cdba7adbf147381b03f8f4e0bf3a 100644 (file)
--- 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 6ec2430179865e494fe48b1ec93fb15f784fbfc7..e27a364b5c6fb6e51e3e3512bc4aa8334044b01e 100644 (file)
--- 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;