Skip to content

Commit a7866db

Browse files
committed
double serialization routines implemented
1 parent 2161a96 commit a7866db

File tree

2 files changed

+59
-1
lines changed

2 files changed

+59
-1
lines changed

Makefile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,10 @@
55
uname_S := $(shell sh -c 'uname -s 2>/dev/null || echo not')
66
ifeq ($(uname_S),SunOS)
77
CFLAGS?= -std=c99 -pedantic -O2 -Wall -W -D__EXTENSIONS__ -D_XPG6
8-
CCLINK?= -ldl -lnsl -lsocket
8+
CCLINK?= -ldl -lnsl -lsocket -lm
99
else
1010
CFLAGS?= -std=c99 -pedantic -O2 -Wall -W
11+
CCLINK?= -lm
1112
endif
1213
CCOPT= $(CFLAGS) $(CCLINK) $(ARCH)
1314
DEBUG?= -g -rdynamic -ggdb

redis.c

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@
5757
#include <sys/time.h>
5858
#include <sys/resource.h>
5959
#include <limits.h>
60+
#include <math.h>
6061

6162
#include "redis.h"
6263
#include "ae.h" /* Event driven programming library */
@@ -338,6 +339,12 @@ struct sharedObjectsStruct {
338339
*select5, *select6, *select7, *select8, *select9;
339340
} shared;
340341

342+
/* Global vars that are actally used as constants. The following double
343+
* values are used for double on-disk serialization, and are initialized
344+
* at runtime to avoid strange compiler optimizations. */
345+
346+
static double R_Zero, R_PosInf, R_NegInf, R_Nan;
347+
341348
/*================================ Prototypes =============================== */
342349

343350
static void freeStringObject(robj *o);
@@ -1021,6 +1028,12 @@ static void initServerConfig() {
10211028
server.masterport = 6379;
10221029
server.master = NULL;
10231030
server.replstate = REDIS_REPL_NONE;
1031+
1032+
/* Double constants initialization */
1033+
R_Zero = 0.0;
1034+
R_PosInf = 1.0/R_Zero;
1035+
R_NegInf = -1.0/R_Zero;
1036+
R_Nan = R_Zero/R_Zero;
10241037
}
10251038

10261039
static void initServer() {
@@ -2238,6 +2251,33 @@ static int rdbSaveStringObject(FILE *fp, robj *obj) {
22382251
}
22392252
}
22402253

2254+
/* Save a double value. Doubles are saved as strings prefixed by an unsigned
2255+
* 8 bit integer specifing the length of the representation.
2256+
* This 8 bit integer has special values in order to specify the following
2257+
* conditions:
2258+
* 253: not a number
2259+
* 254: + inf
2260+
* 255: - inf
2261+
*/
2262+
static int rdbSaveDoubleValue(FILE *fp, double val) {
2263+
unsigned char buf[128];
2264+
int len;
2265+
2266+
if (isnan(val)) {
2267+
buf[0] = 253;
2268+
len = 1;
2269+
} else if (!isfinite(val)) {
2270+
len = 1;
2271+
buf[0] = (val < 0) ? 255 : 254;
2272+
} else {
2273+
snprintf((char*)buf+1,sizeof(buf)-1,"%.16g",val);
2274+
buf[0] = strlen((char*)buf);
2275+
len = buf[0]+1;
2276+
}
2277+
if (fwrite(buf,len,1,fp) == 0) return -1;
2278+
return 0;
2279+
}
2280+
22412281
/* Save the DB on disk. Return REDIS_ERR on error, REDIS_OK on success */
22422282
static int rdbSave(char *filename) {
22432283
dictIterator *di = NULL;
@@ -2500,6 +2540,23 @@ static robj *rdbLoadStringObject(FILE*fp, int rdbver) {
25002540
return tryObjectSharing(createObject(REDIS_STRING,val));
25012541
}
25022542

2543+
/* For information about double serialization check rdbSaveDoubleValue() */
2544+
static int rdbLoadDoubleValue(FILE *fp, double *val) {
2545+
char buf[128];
2546+
unsigned char len;
2547+
2548+
if (fread(&len,1,1,fp) == 0) return -1;
2549+
switch(len) {
2550+
case 255: *val = R_NegInf; return 0;
2551+
case 254: *val = R_PosInf; return 0;
2552+
case 253: *val = R_Nan; return 0;
2553+
default:
2554+
if (fread(buf,len,1,fp) == 0) return -1;
2555+
sscanf(buf, "%lg", val);
2556+
return 0;
2557+
}
2558+
}
2559+
25032560
static int rdbLoad(char *filename) {
25042561
FILE *fp;
25052562
robj *keyobj = NULL;

0 commit comments

Comments
 (0)