4 #include <sys/resource.h>
9 #include "lzf.h" /* LZF compression library */
11 static int rdbWriteRaw(rio
*rdb
, void *p
, size_t len
) {
12 if (rdb
&& rioWrite(rdb
,p
,len
) == 0)
17 int rdbSaveType(rio
*rdb
, unsigned char type
) {
18 return rdbWriteRaw(rdb
,&type
,1);
21 int rdbLoadType(rio
*rdb
) {
23 if (rioRead(rdb
,&type
,1) == 0) return -1;
27 int rdbSaveTime(rio
*rdb
, time_t t
) {
28 int32_t t32
= (int32_t) t
;
29 return rdbWriteRaw(rdb
,&t32
,4);
32 time_t rdbLoadTime(rio
*rdb
) {
34 if (rioRead(rdb
,&t32
,4) == 0) return -1;
38 /* Saves an encoded length. The first two bits in the first byte are used to
39 * hold the encoding type. See the REDIS_RDB_* definitions for more information
40 * on the types of encoding. */
41 int rdbSaveLen(rio
*rdb
, uint32_t len
) {
46 /* Save a 6 bit len */
47 buf
[0] = (len
&0xFF)|(REDIS_RDB_6BITLEN
<<6);
48 if (rdbWriteRaw(rdb
,buf
,1) == -1) return -1;
50 } else if (len
< (1<<14)) {
51 /* Save a 14 bit len */
52 buf
[0] = ((len
>>8)&0xFF)|(REDIS_RDB_14BITLEN
<<6);
54 if (rdbWriteRaw(rdb
,buf
,2) == -1) return -1;
57 /* Save a 32 bit len */
58 buf
[0] = (REDIS_RDB_32BITLEN
<<6);
59 if (rdbWriteRaw(rdb
,buf
,1) == -1) return -1;
61 if (rdbWriteRaw(rdb
,&len
,4) == -4) return -1;
67 /* Load an encoded length. The "isencoded" argument is set to 1 if the length
68 * is not actually a length but an "encoding type". See the REDIS_RDB_ENC_*
69 * definitions in rdb.h for more information. */
70 uint32_t rdbLoadLen(rio
*rdb
, int *isencoded
) {
75 if (isencoded
) *isencoded
= 0;
76 if (rioRead(rdb
,buf
,1) == 0) return REDIS_RDB_LENERR
;
77 type
= (buf
[0]&0xC0)>>6;
78 if (type
== REDIS_RDB_ENCVAL
) {
79 /* Read a 6 bit encoding type. */
80 if (isencoded
) *isencoded
= 1;
82 } else if (type
== REDIS_RDB_6BITLEN
) {
83 /* Read a 6 bit len. */
85 } else if (type
== REDIS_RDB_14BITLEN
) {
86 /* Read a 14 bit len. */
87 if (rioRead(rdb
,buf
+1,1) == 0) return REDIS_RDB_LENERR
;
88 return ((buf
[0]&0x3F)<<8)|buf
[1];
90 /* Read a 32 bit len. */
91 if (rioRead(rdb
,&len
,4) == 0) return REDIS_RDB_LENERR
;
96 /* Encodes the "value" argument as integer when it fits in the supported ranges
97 * for encoded types. If the function successfully encodes the integer, the
98 * representation is stored in the buffer pointer to by "enc" and the string
99 * length is returned. Otherwise 0 is returned. */
100 int rdbEncodeInteger(long long value
, unsigned char *enc
) {
101 if (value
>= -(1<<7) && value
<= (1<<7)-1) {
102 enc
[0] = (REDIS_RDB_ENCVAL
<<6)|REDIS_RDB_ENC_INT8
;
105 } else if (value
>= -(1<<15) && value
<= (1<<15)-1) {
106 enc
[0] = (REDIS_RDB_ENCVAL
<<6)|REDIS_RDB_ENC_INT16
;
108 enc
[2] = (value
>>8)&0xFF;
110 } else if (value
>= -((long long)1<<31) && value
<= ((long long)1<<31)-1) {
111 enc
[0] = (REDIS_RDB_ENCVAL
<<6)|REDIS_RDB_ENC_INT32
;
113 enc
[2] = (value
>>8)&0xFF;
114 enc
[3] = (value
>>16)&0xFF;
115 enc
[4] = (value
>>24)&0xFF;
122 /* Loads an integer-encoded object with the specified encoding type "enctype".
123 * If the "encode" argument is set the function may return an integer-encoded
124 * string object, otherwise it always returns a raw string object. */
125 robj
*rdbLoadIntegerObject(rio
*rdb
, int enctype
, int encode
) {
126 unsigned char enc
[4];
129 if (enctype
== REDIS_RDB_ENC_INT8
) {
130 if (rioRead(rdb
,enc
,1) == 0) return NULL
;
131 val
= (signed char)enc
[0];
132 } else if (enctype
== REDIS_RDB_ENC_INT16
) {
134 if (rioRead(rdb
,enc
,2) == 0) return NULL
;
135 v
= enc
[0]|(enc
[1]<<8);
137 } else if (enctype
== REDIS_RDB_ENC_INT32
) {
139 if (rioRead(rdb
,enc
,4) == 0) return NULL
;
140 v
= enc
[0]|(enc
[1]<<8)|(enc
[2]<<16)|(enc
[3]<<24);
143 val
= 0; /* anti-warning */
144 redisPanic("Unknown RDB integer encoding type");
147 return createStringObjectFromLongLong(val
);
149 return createObject(REDIS_STRING
,sdsfromlonglong(val
));
152 /* String objects in the form "2391" "-100" without any space and with a
153 * range of values that can fit in an 8, 16 or 32 bit signed value can be
154 * encoded as integers to save space */
155 int rdbTryIntegerEncoding(char *s
, size_t len
, unsigned char *enc
) {
157 char *endptr
, buf
[32];
159 /* Check if it's possible to encode this value as a number */
160 value
= strtoll(s
, &endptr
, 10);
161 if (endptr
[0] != '\0') return 0;
162 ll2string(buf
,32,value
);
164 /* If the number converted back into a string is not identical
165 * then it's not possible to encode the string as integer */
166 if (strlen(buf
) != len
|| memcmp(buf
,s
,len
)) return 0;
168 return rdbEncodeInteger(value
,enc
);
171 int rdbSaveLzfStringObject(rio
*rdb
, unsigned char *s
, size_t len
) {
172 size_t comprlen
, outlen
;
177 /* We require at least four bytes compression for this to be worth it */
178 if (len
<= 4) return 0;
180 if ((out
= zmalloc(outlen
+1)) == NULL
) return 0;
181 comprlen
= lzf_compress(s
, len
, out
, outlen
);
186 /* Data compressed! Let's save it on disk */
187 byte
= (REDIS_RDB_ENCVAL
<<6)|REDIS_RDB_ENC_LZF
;
188 if ((n
= rdbWriteRaw(rdb
,&byte
,1)) == -1) goto writeerr
;
191 if ((n
= rdbSaveLen(rdb
,comprlen
)) == -1) goto writeerr
;
194 if ((n
= rdbSaveLen(rdb
,len
)) == -1) goto writeerr
;
197 if ((n
= rdbWriteRaw(rdb
,out
,comprlen
)) == -1) goto writeerr
;
208 robj
*rdbLoadLzfStringObject(rio
*rdb
) {
209 unsigned int len
, clen
;
210 unsigned char *c
= NULL
;
213 if ((clen
= rdbLoadLen(rdb
,NULL
)) == REDIS_RDB_LENERR
) return NULL
;
214 if ((len
= rdbLoadLen(rdb
,NULL
)) == REDIS_RDB_LENERR
) return NULL
;
215 if ((c
= zmalloc(clen
)) == NULL
) goto err
;
216 if ((val
= sdsnewlen(NULL
,len
)) == NULL
) goto err
;
217 if (rioRead(rdb
,c
,clen
) == 0) goto err
;
218 if (lzf_decompress(c
,clen
,val
,len
) == 0) goto err
;
220 return createObject(REDIS_STRING
,val
);
227 /* Save a string objet as [len][data] on disk. If the object is a string
228 * representation of an integer value we try to save it in a special form */
229 int rdbSaveRawString(rio
*rdb
, unsigned char *s
, size_t len
) {
233 /* Try integer encoding */
235 unsigned char buf
[5];
236 if ((enclen
= rdbTryIntegerEncoding((char*)s
,len
,buf
)) > 0) {
237 if (rdbWriteRaw(rdb
,buf
,enclen
) == -1) return -1;
242 /* Try LZF compression - under 20 bytes it's unable to compress even
243 * aaaaaaaaaaaaaaaaaa so skip it */
244 if (server
.rdbcompression
&& len
> 20) {
245 n
= rdbSaveLzfStringObject(rdb
,s
,len
);
246 if (n
== -1) return -1;
248 /* Return value of 0 means data can't be compressed, save the old way */
252 if ((n
= rdbSaveLen(rdb
,len
)) == -1) return -1;
255 if (rdbWriteRaw(rdb
,s
,len
) == -1) return -1;
261 /* Save a long long value as either an encoded string or a string. */
262 int rdbSaveLongLongAsStringObject(rio
*rdb
, long long value
) {
263 unsigned char buf
[32];
265 int enclen
= rdbEncodeInteger(value
,buf
);
267 return rdbWriteRaw(rdb
,buf
,enclen
);
269 /* Encode as string */
270 enclen
= ll2string((char*)buf
,32,value
);
271 redisAssert(enclen
< 32);
272 if ((n
= rdbSaveLen(rdb
,enclen
)) == -1) return -1;
274 if ((n
= rdbWriteRaw(rdb
,buf
,enclen
)) == -1) return -1;
280 /* Like rdbSaveStringObjectRaw() but handle encoded objects */
281 int rdbSaveStringObject(rio
*rdb
, robj
*obj
) {
282 /* Avoid to decode the object, then encode it again, if the
283 * object is alrady integer encoded. */
284 if (obj
->encoding
== REDIS_ENCODING_INT
) {
285 return rdbSaveLongLongAsStringObject(rdb
,(long)obj
->ptr
);
287 redisAssert(obj
->encoding
== REDIS_ENCODING_RAW
);
288 return rdbSaveRawString(rdb
,obj
->ptr
,sdslen(obj
->ptr
));
292 robj
*rdbGenericLoadStringObject(rio
*rdb
, int encode
) {
297 len
= rdbLoadLen(rdb
,&isencoded
);
300 case REDIS_RDB_ENC_INT8
:
301 case REDIS_RDB_ENC_INT16
:
302 case REDIS_RDB_ENC_INT32
:
303 return rdbLoadIntegerObject(rdb
,len
,encode
);
304 case REDIS_RDB_ENC_LZF
:
305 return rdbLoadLzfStringObject(rdb
);
307 redisPanic("Unknown RDB encoding type");
311 if (len
== REDIS_RDB_LENERR
) return NULL
;
312 val
= sdsnewlen(NULL
,len
);
313 if (len
&& rioRead(rdb
,val
,len
) == 0) {
317 return createObject(REDIS_STRING
,val
);
320 robj
*rdbLoadStringObject(rio
*rdb
) {
321 return rdbGenericLoadStringObject(rdb
,0);
324 robj
*rdbLoadEncodedStringObject(rio
*rdb
) {
325 return rdbGenericLoadStringObject(rdb
,1);
328 /* Save a double value. Doubles are saved as strings prefixed by an unsigned
329 * 8 bit integer specifing the length of the representation.
330 * This 8 bit integer has special values in order to specify the following
336 int rdbSaveDoubleValue(rio
*rdb
, double val
) {
337 unsigned char buf
[128];
343 } else if (!isfinite(val
)) {
345 buf
[0] = (val
< 0) ? 255 : 254;
347 #if (DBL_MANT_DIG >= 52) && (LLONG_MAX == 0x7fffffffffffffffLL)
348 /* Check if the float is in a safe range to be casted into a
349 * long long. We are assuming that long long is 64 bit here.
350 * Also we are assuming that there are no implementations around where
351 * double has precision < 52 bit.
353 * Under this assumptions we test if a double is inside an interval
354 * where casting to long long is safe. Then using two castings we
355 * make sure the decimal part is zero. If all this is true we use
356 * integer printing function that is much faster. */
357 double min
= -4503599627370495; /* (2^52)-1 */
358 double max
= 4503599627370496; /* -(2^52) */
359 if (val
> min
&& val
< max
&& val
== ((double)((long long)val
)))
360 ll2string((char*)buf
+1,sizeof(buf
),(long long)val
);
363 snprintf((char*)buf
+1,sizeof(buf
)-1,"%.17g",val
);
364 buf
[0] = strlen((char*)buf
+1);
367 return rdbWriteRaw(rdb
,buf
,len
);
370 /* For information about double serialization check rdbSaveDoubleValue() */
371 int rdbLoadDoubleValue(rio
*rdb
, double *val
) {
375 if (rioRead(rdb
,&len
,1) == 0) return -1;
377 case 255: *val
= R_NegInf
; return 0;
378 case 254: *val
= R_PosInf
; return 0;
379 case 253: *val
= R_Nan
; return 0;
381 if (rioRead(rdb
,buf
,len
) == 0) return -1;
383 sscanf(buf
, "%lg", val
);
388 /* Save the object type of object "o". */
389 int rdbSaveObjectType(rio
*rdb
, robj
*o
) {
392 return rdbSaveType(rdb
,REDIS_RDB_TYPE_STRING
);
394 if (o
->encoding
== REDIS_ENCODING_ZIPLIST
)
395 return rdbSaveType(rdb
,REDIS_RDB_TYPE_LIST_ZIPLIST
);
396 else if (o
->encoding
== REDIS_ENCODING_LINKEDLIST
)
397 return rdbSaveType(rdb
,REDIS_RDB_TYPE_LIST
);
399 redisPanic("Unknown list encoding");
401 if (o
->encoding
== REDIS_ENCODING_INTSET
)
402 return rdbSaveType(rdb
,REDIS_RDB_TYPE_SET_INTSET
);
403 else if (o
->encoding
== REDIS_ENCODING_HT
)
404 return rdbSaveType(rdb
,REDIS_RDB_TYPE_SET
);
406 redisPanic("Unknown set encoding");
408 if (o
->encoding
== REDIS_ENCODING_ZIPLIST
)
409 return rdbSaveType(rdb
,REDIS_RDB_TYPE_ZSET_ZIPLIST
);
410 else if (o
->encoding
== REDIS_ENCODING_SKIPLIST
)
411 return rdbSaveType(rdb
,REDIS_RDB_TYPE_ZSET
);
413 redisPanic("Unknown sorted set encoding");
415 if (o
->encoding
== REDIS_ENCODING_ZIPMAP
)
416 return rdbSaveType(rdb
,REDIS_RDB_TYPE_HASH_ZIPMAP
);
417 else if (o
->encoding
== REDIS_ENCODING_HT
)
418 return rdbSaveType(rdb
,REDIS_RDB_TYPE_HASH
);
420 redisPanic("Unknown hash encoding");
422 redisPanic("Unknown object type");
424 return -1; /* avoid warning */
427 /* Load object type. Return -1 when the byte doesn't contain an object type. */
428 int rdbLoadObjectType(rio
*rdb
) {
430 if ((type
= rdbLoadType(rdb
)) == -1) return -1;
431 if (!rdbIsObjectType(type
)) return -1;
435 /* Save a Redis object. Returns -1 on error, 0 on success. */
436 int rdbSaveObject(rio
*rdb
, robj
*o
) {
439 if (o
->type
== REDIS_STRING
) {
440 /* Save a string value */
441 if ((n
= rdbSaveStringObject(rdb
,o
)) == -1) return -1;
443 } else if (o
->type
== REDIS_LIST
) {
444 /* Save a list value */
445 if (o
->encoding
== REDIS_ENCODING_ZIPLIST
) {
446 size_t l
= ziplistBlobLen((unsigned char*)o
->ptr
);
448 if ((n
= rdbSaveRawString(rdb
,o
->ptr
,l
)) == -1) return -1;
450 } else if (o
->encoding
== REDIS_ENCODING_LINKEDLIST
) {
455 if ((n
= rdbSaveLen(rdb
,listLength(list
))) == -1) return -1;
458 listRewind(list
,&li
);
459 while((ln
= listNext(&li
))) {
460 robj
*eleobj
= listNodeValue(ln
);
461 if ((n
= rdbSaveStringObject(rdb
,eleobj
)) == -1) return -1;
465 redisPanic("Unknown list encoding");
467 } else if (o
->type
== REDIS_SET
) {
468 /* Save a set value */
469 if (o
->encoding
== REDIS_ENCODING_HT
) {
471 dictIterator
*di
= dictGetIterator(set
);
474 if ((n
= rdbSaveLen(rdb
,dictSize(set
))) == -1) return -1;
477 while((de
= dictNext(di
)) != NULL
) {
478 robj
*eleobj
= dictGetEntryKey(de
);
479 if ((n
= rdbSaveStringObject(rdb
,eleobj
)) == -1) return -1;
482 dictReleaseIterator(di
);
483 } else if (o
->encoding
== REDIS_ENCODING_INTSET
) {
484 size_t l
= intsetBlobLen((intset
*)o
->ptr
);
486 if ((n
= rdbSaveRawString(rdb
,o
->ptr
,l
)) == -1) return -1;
489 redisPanic("Unknown set encoding");
491 } else if (o
->type
== REDIS_ZSET
) {
492 /* Save a sorted set value */
493 if (o
->encoding
== REDIS_ENCODING_ZIPLIST
) {
494 size_t l
= ziplistBlobLen((unsigned char*)o
->ptr
);
496 if ((n
= rdbSaveRawString(rdb
,o
->ptr
,l
)) == -1) return -1;
498 } else if (o
->encoding
== REDIS_ENCODING_SKIPLIST
) {
500 dictIterator
*di
= dictGetIterator(zs
->dict
);
503 if ((n
= rdbSaveLen(rdb
,dictSize(zs
->dict
))) == -1) return -1;
506 while((de
= dictNext(di
)) != NULL
) {
507 robj
*eleobj
= dictGetEntryKey(de
);
508 double *score
= dictGetEntryVal(de
);
510 if ((n
= rdbSaveStringObject(rdb
,eleobj
)) == -1) return -1;
512 if ((n
= rdbSaveDoubleValue(rdb
,*score
)) == -1) return -1;
515 dictReleaseIterator(di
);
517 redisPanic("Unknown sorted set encoding");
519 } else if (o
->type
== REDIS_HASH
) {
520 /* Save a hash value */
521 if (o
->encoding
== REDIS_ENCODING_ZIPMAP
) {
522 size_t l
= zipmapBlobLen((unsigned char*)o
->ptr
);
524 if ((n
= rdbSaveRawString(rdb
,o
->ptr
,l
)) == -1) return -1;
527 dictIterator
*di
= dictGetIterator(o
->ptr
);
530 if ((n
= rdbSaveLen(rdb
,dictSize((dict
*)o
->ptr
))) == -1) return -1;
533 while((de
= dictNext(di
)) != NULL
) {
534 robj
*key
= dictGetEntryKey(de
);
535 robj
*val
= dictGetEntryVal(de
);
537 if ((n
= rdbSaveStringObject(rdb
,key
)) == -1) return -1;
539 if ((n
= rdbSaveStringObject(rdb
,val
)) == -1) return -1;
542 dictReleaseIterator(di
);
545 redisPanic("Unknown object type");
550 /* Return the length the object will have on disk if saved with
551 * the rdbSaveObject() function. Currently we use a trick to get
552 * this length with very little changes to the code. In the future
553 * we could switch to a faster solution. */
554 off_t
rdbSavedObjectLen(robj
*o
) {
555 int len
= rdbSaveObject(NULL
,o
);
556 redisAssert(len
!= -1);
560 /* Save a key-value pair, with expire time, type, key, value.
561 * On error -1 is returned.
562 * On success if the key was actaully saved 1 is returned, otherwise 0
563 * is returned (the key was already expired). */
564 int rdbSaveKeyValuePair(rio
*rdb
, robj
*key
, robj
*val
,
565 time_t expiretime
, time_t now
)
567 /* Save the expire time */
568 if (expiretime
!= -1) {
569 /* If this key is already expired skip it */
570 if (expiretime
< now
) return 0;
571 if (rdbSaveType(rdb
,REDIS_RDB_OPCODE_EXPIRETIME
) == -1) return -1;
572 if (rdbSaveTime(rdb
,expiretime
) == -1) return -1;
575 /* Save type, key, value */
576 if (rdbSaveObjectType(rdb
,val
) == -1) return -1;
577 if (rdbSaveStringObject(rdb
,key
) == -1) return -1;
578 if (rdbSaveObject(rdb
,val
) == -1) return -1;
582 /* Save the DB on disk. Return REDIS_ERR on error, REDIS_OK on success */
583 int rdbSave(char *filename
) {
584 dictIterator
*di
= NULL
;
588 time_t now
= time(NULL
);
592 if (server
.ds_enabled
) {
593 cacheForcePointInTime();
594 return dsRdbSave(filename
);
597 snprintf(tmpfile
,256,"temp-%d.rdb", (int) getpid());
598 fp
= fopen(tmpfile
,"w");
600 redisLog(REDIS_WARNING
, "Failed opening .rdb for saving: %s",
605 rdb
= rioInitWithFile(fp
);
606 if (rdbWriteRaw(&rdb
,"REDIS0002",9) == -1) goto werr
;
608 for (j
= 0; j
< server
.dbnum
; j
++) {
609 redisDb
*db
= server
.db
+j
;
611 if (dictSize(d
) == 0) continue;
612 di
= dictGetIterator(d
);
618 /* Write the SELECT DB opcode */
619 if (rdbSaveType(&rdb
,REDIS_RDB_OPCODE_SELECTDB
) == -1) goto werr
;
620 if (rdbSaveLen(&rdb
,j
) == -1) goto werr
;
622 /* Iterate this DB writing every entry */
623 while((de
= dictNext(di
)) != NULL
) {
624 sds keystr
= dictGetEntryKey(de
);
625 robj key
, *o
= dictGetEntryVal(de
);
628 initStaticStringObject(key
,keystr
);
629 expire
= getExpire(db
,&key
);
630 if (rdbSaveKeyValuePair(&rdb
,&key
,o
,expire
,now
) == -1) goto werr
;
632 dictReleaseIterator(di
);
635 if (rdbSaveType(&rdb
,REDIS_RDB_OPCODE_EOF
) == -1) goto werr
;
637 /* Make sure data will not remain on the OS's output buffers */
642 /* Use RENAME to make sure the DB file is changed atomically only
643 * if the generate DB file is ok. */
644 if (rename(tmpfile
,filename
) == -1) {
645 redisLog(REDIS_WARNING
,"Error moving temp DB file on the final destination: %s", strerror(errno
));
649 redisLog(REDIS_NOTICE
,"DB saved on disk");
651 server
.lastsave
= time(NULL
);
657 redisLog(REDIS_WARNING
,"Write error saving DB on disk: %s", strerror(errno
));
658 if (di
) dictReleaseIterator(di
);
662 int rdbSaveBackground(char *filename
) {
665 if (server
.bgsavechildpid
!= -1 ||
666 server
.bgsavethread
!= (pthread_t
) -1) return REDIS_ERR
;
668 server
.dirty_before_bgsave
= server
.dirty
;
670 if (server
.ds_enabled
) {
671 cacheForcePointInTime();
672 return dsRdbSaveBackground(filename
);
675 if ((childpid
= fork()) == 0) {
679 if (server
.ipfd
> 0) close(server
.ipfd
);
680 if (server
.sofd
> 0) close(server
.sofd
);
681 retval
= rdbSave(filename
);
682 _exit((retval
== REDIS_OK
) ? 0 : 1);
685 if (childpid
== -1) {
686 redisLog(REDIS_WARNING
,"Can't save in background: fork: %s",
690 redisLog(REDIS_NOTICE
,"Background saving started by pid %d",childpid
);
691 server
.bgsavechildpid
= childpid
;
692 updateDictResizePolicy();
695 return REDIS_OK
; /* unreached */
698 void rdbRemoveTempFile(pid_t childpid
) {
701 snprintf(tmpfile
,256,"temp-%d.rdb", (int) childpid
);
705 /* Load a Redis object of the specified type from the specified file.
706 * On success a newly allocated object is returned, otherwise NULL. */
707 robj
*rdbLoadObject(int rdbtype
, rio
*rdb
) {
712 redisLog(REDIS_DEBUG
,"LOADING OBJECT %d (at %d)\n",rdbtype
,rdb
->tell(rdb
));
713 if (rdbtype
== REDIS_RDB_TYPE_STRING
) {
714 /* Read string value */
715 if ((o
= rdbLoadEncodedStringObject(rdb
)) == NULL
) return NULL
;
716 o
= tryObjectEncoding(o
);
717 } else if (rdbtype
== REDIS_RDB_TYPE_LIST
) {
718 /* Read list value */
719 if ((len
= rdbLoadLen(rdb
,NULL
)) == REDIS_RDB_LENERR
) return NULL
;
721 /* Use a real list when there are too many entries */
722 if (len
> server
.list_max_ziplist_entries
) {
723 o
= createListObject();
725 o
= createZiplistObject();
728 /* Load every single element of the list */
730 if ((ele
= rdbLoadEncodedStringObject(rdb
)) == NULL
) return NULL
;
732 /* If we are using a ziplist and the value is too big, convert
733 * the object to a real list. */
734 if (o
->encoding
== REDIS_ENCODING_ZIPLIST
&&
735 ele
->encoding
== REDIS_ENCODING_RAW
&&
736 sdslen(ele
->ptr
) > server
.list_max_ziplist_value
)
737 listTypeConvert(o
,REDIS_ENCODING_LINKEDLIST
);
739 if (o
->encoding
== REDIS_ENCODING_ZIPLIST
) {
740 dec
= getDecodedObject(ele
);
741 o
->ptr
= ziplistPush(o
->ptr
,dec
->ptr
,sdslen(dec
->ptr
),REDIS_TAIL
);
745 ele
= tryObjectEncoding(ele
);
746 listAddNodeTail(o
->ptr
,ele
);
749 } else if (rdbtype
== REDIS_RDB_TYPE_SET
) {
750 /* Read list/set value */
751 if ((len
= rdbLoadLen(rdb
,NULL
)) == REDIS_RDB_LENERR
) return NULL
;
753 /* Use a regular set when there are too many entries. */
754 if (len
> server
.set_max_intset_entries
) {
755 o
= createSetObject();
756 /* It's faster to expand the dict to the right size asap in order
757 * to avoid rehashing */
758 if (len
> DICT_HT_INITIAL_SIZE
)
759 dictExpand(o
->ptr
,len
);
761 o
= createIntsetObject();
764 /* Load every single element of the list/set */
765 for (i
= 0; i
< len
; i
++) {
767 if ((ele
= rdbLoadEncodedStringObject(rdb
)) == NULL
) return NULL
;
768 ele
= tryObjectEncoding(ele
);
770 if (o
->encoding
== REDIS_ENCODING_INTSET
) {
771 /* Fetch integer value from element */
772 if (isObjectRepresentableAsLongLong(ele
,&llval
) == REDIS_OK
) {
773 o
->ptr
= intsetAdd(o
->ptr
,llval
,NULL
);
775 setTypeConvert(o
,REDIS_ENCODING_HT
);
776 dictExpand(o
->ptr
,len
);
780 /* This will also be called when the set was just converted
781 * to regular hashtable encoded set */
782 if (o
->encoding
== REDIS_ENCODING_HT
) {
783 dictAdd((dict
*)o
->ptr
,ele
,NULL
);
788 } else if (rdbtype
== REDIS_RDB_TYPE_ZSET
) {
789 /* Read list/set value */
791 size_t maxelelen
= 0;
794 if ((zsetlen
= rdbLoadLen(rdb
,NULL
)) == REDIS_RDB_LENERR
) return NULL
;
795 o
= createZsetObject();
798 /* Load every single element of the list/set */
802 zskiplistNode
*znode
;
804 if ((ele
= rdbLoadEncodedStringObject(rdb
)) == NULL
) return NULL
;
805 ele
= tryObjectEncoding(ele
);
806 if (rdbLoadDoubleValue(rdb
,&score
) == -1) return NULL
;
808 /* Don't care about integer-encoded strings. */
809 if (ele
->encoding
== REDIS_ENCODING_RAW
&&
810 sdslen(ele
->ptr
) > maxelelen
)
811 maxelelen
= sdslen(ele
->ptr
);
813 znode
= zslInsert(zs
->zsl
,score
,ele
);
814 dictAdd(zs
->dict
,ele
,&znode
->score
);
815 incrRefCount(ele
); /* added to skiplist */
818 /* Convert *after* loading, since sorted sets are not stored ordered. */
819 if (zsetLength(o
) <= server
.zset_max_ziplist_entries
&&
820 maxelelen
<= server
.zset_max_ziplist_value
)
821 zsetConvert(o
,REDIS_ENCODING_ZIPLIST
);
822 } else if (rdbtype
== REDIS_RDB_TYPE_HASH
) {
825 if ((hashlen
= rdbLoadLen(rdb
,NULL
)) == REDIS_RDB_LENERR
) return NULL
;
826 o
= createHashObject();
827 /* Too many entries? Use an hash table. */
828 if (hashlen
> server
.hash_max_zipmap_entries
)
829 convertToRealHash(o
);
830 /* Load every key/value, then set it into the zipmap or hash
831 * table, as needed. */
835 if ((key
= rdbLoadEncodedStringObject(rdb
)) == NULL
) return NULL
;
836 if ((val
= rdbLoadEncodedStringObject(rdb
)) == NULL
) return NULL
;
837 /* If we are using a zipmap and there are too big values
838 * the object is converted to real hash table encoding. */
839 if (o
->encoding
!= REDIS_ENCODING_HT
&&
840 ((key
->encoding
== REDIS_ENCODING_RAW
&&
841 sdslen(key
->ptr
) > server
.hash_max_zipmap_value
) ||
842 (val
->encoding
== REDIS_ENCODING_RAW
&&
843 sdslen(val
->ptr
) > server
.hash_max_zipmap_value
)))
845 convertToRealHash(o
);
848 if (o
->encoding
== REDIS_ENCODING_ZIPMAP
) {
849 unsigned char *zm
= o
->ptr
;
850 robj
*deckey
, *decval
;
852 /* We need raw string objects to add them to the zipmap */
853 deckey
= getDecodedObject(key
);
854 decval
= getDecodedObject(val
);
855 zm
= zipmapSet(zm
,deckey
->ptr
,sdslen(deckey
->ptr
),
856 decval
->ptr
,sdslen(decval
->ptr
),NULL
);
858 decrRefCount(deckey
);
859 decrRefCount(decval
);
863 key
= tryObjectEncoding(key
);
864 val
= tryObjectEncoding(val
);
865 dictAdd((dict
*)o
->ptr
,key
,val
);
868 } else if (rdbtype
== REDIS_RDB_TYPE_HASH_ZIPMAP
||
869 rdbtype
== REDIS_RDB_TYPE_LIST_ZIPLIST
||
870 rdbtype
== REDIS_RDB_TYPE_SET_INTSET
||
871 rdbtype
== REDIS_RDB_TYPE_ZSET_ZIPLIST
)
873 robj
*aux
= rdbLoadStringObject(rdb
);
875 if (aux
== NULL
) return NULL
;
876 o
= createObject(REDIS_STRING
,NULL
); /* string is just placeholder */
877 o
->ptr
= zmalloc(sdslen(aux
->ptr
));
878 memcpy(o
->ptr
,aux
->ptr
,sdslen(aux
->ptr
));
881 /* Fix the object encoding, and make sure to convert the encoded
882 * data type into the base type if accordingly to the current
883 * configuration there are too many elements in the encoded data
884 * type. Note that we only check the length and not max element
885 * size as this is an O(N) scan. Eventually everything will get
888 case REDIS_RDB_TYPE_HASH_ZIPMAP
:
889 o
->type
= REDIS_HASH
;
890 o
->encoding
= REDIS_ENCODING_ZIPMAP
;
891 if (zipmapLen(o
->ptr
) > server
.hash_max_zipmap_entries
)
892 convertToRealHash(o
);
894 case REDIS_RDB_TYPE_LIST_ZIPLIST
:
895 o
->type
= REDIS_LIST
;
896 o
->encoding
= REDIS_ENCODING_ZIPLIST
;
897 if (ziplistLen(o
->ptr
) > server
.list_max_ziplist_entries
)
898 listTypeConvert(o
,REDIS_ENCODING_LINKEDLIST
);
900 case REDIS_RDB_TYPE_SET_INTSET
:
902 o
->encoding
= REDIS_ENCODING_INTSET
;
903 if (intsetLen(o
->ptr
) > server
.set_max_intset_entries
)
904 setTypeConvert(o
,REDIS_ENCODING_HT
);
906 case REDIS_RDB_TYPE_ZSET_ZIPLIST
:
907 o
->type
= REDIS_ZSET
;
908 o
->encoding
= REDIS_ENCODING_ZIPLIST
;
909 if (zsetLength(o
) > server
.zset_max_ziplist_entries
)
910 zsetConvert(o
,REDIS_ENCODING_SKIPLIST
);
913 redisPanic("Unknown encoding");
917 redisPanic("Unknown object type");
922 /* Mark that we are loading in the global state and setup the fields
923 * needed to provide loading stats. */
924 void startLoading(FILE *fp
) {
929 server
.loading_start_time
= time(NULL
);
930 if (fstat(fileno(fp
), &sb
) == -1) {
931 server
.loading_total_bytes
= 1; /* just to avoid division by zero */
933 server
.loading_total_bytes
= sb
.st_size
;
937 /* Refresh the loading progress info */
938 void loadingProgress(off_t pos
) {
939 server
.loading_loaded_bytes
= pos
;
942 /* Loading finished */
943 void stopLoading(void) {
947 int rdbLoad(char *filename
) {
949 int type
, retval
, rdbver
;
950 redisDb
*db
= server
.db
+0;
952 time_t expiretime
, now
= time(NULL
);
957 fp
= fopen(filename
,"r");
958 if (!fp
) return REDIS_ERR
;
959 rdb
= rioInitWithFile(fp
);
960 if (rioRead(&rdb
,buf
,9) == 0) goto eoferr
;
962 if (memcmp(buf
,"REDIS",5) != 0) {
964 redisLog(REDIS_WARNING
,"Wrong signature trying to load DB from file");
967 rdbver
= atoi(buf
+5);
968 if (rdbver
< 1 || rdbver
> 2) {
970 redisLog(REDIS_WARNING
,"Can't handle RDB format version %d",rdbver
);
979 /* Serve the clients from time to time */
980 if (!(loops
++ % 1000)) {
981 loadingProgress(rdb
.tell(&rdb
));
982 aeProcessEvents(server
.el
, AE_FILE_EVENTS
|AE_DONT_WAIT
);
986 if ((type
= rdbLoadType(&rdb
)) == -1) goto eoferr
;
987 if (type
== REDIS_RDB_OPCODE_EXPIRETIME
) {
988 if ((expiretime
= rdbLoadTime(&rdb
)) == -1) goto eoferr
;
989 /* We read the time so we need to read the object type again. */
990 if ((type
= rdbLoadType(&rdb
)) == -1) goto eoferr
;
993 if (type
== REDIS_RDB_OPCODE_EOF
)
996 /* Handle SELECT DB opcode as a special case */
997 if (type
== REDIS_RDB_OPCODE_SELECTDB
) {
998 if ((dbid
= rdbLoadLen(&rdb
,NULL
)) == REDIS_RDB_LENERR
)
1000 if (dbid
>= (unsigned)server
.dbnum
) {
1001 redisLog(REDIS_WARNING
,"FATAL: Data file was created with a Redis server configured to handle more than %d databases. Exiting\n", server
.dbnum
);
1004 db
= server
.db
+dbid
;
1008 if ((key
= rdbLoadStringObject(&rdb
)) == NULL
) goto eoferr
;
1010 if ((val
= rdbLoadObject(type
,&rdb
)) == NULL
) goto eoferr
;
1011 /* Check if the key already expired */
1012 if (expiretime
!= -1 && expiretime
< now
) {
1017 /* Add the new object in the hash table */
1018 retval
= dbAdd(db
,key
,val
);
1019 if (retval
== REDIS_ERR
) {
1020 redisLog(REDIS_WARNING
,"Loading DB, duplicated key (%s) found! Unrecoverable error, exiting now.", key
->ptr
);
1023 /* Set the expire time if needed */
1024 if (expiretime
!= -1) setExpire(db
,key
,expiretime
);
1032 eoferr
: /* unexpected end of file is handled here with a fatal exit */
1033 redisLog(REDIS_WARNING
,"Short read or OOM loading DB. Unrecoverable error, aborting now.");
1035 return REDIS_ERR
; /* Just to avoid warning */
1038 /* A background saving child (BGSAVE) terminated its work. Handle this. */
1039 void backgroundSaveDoneHandler(int exitcode
, int bysignal
) {
1040 if (!bysignal
&& exitcode
== 0) {
1041 redisLog(REDIS_NOTICE
,
1042 "Background saving terminated with success");
1043 server
.dirty
= server
.dirty
- server
.dirty_before_bgsave
;
1044 server
.lastsave
= time(NULL
);
1045 } else if (!bysignal
&& exitcode
!= 0) {
1046 redisLog(REDIS_WARNING
, "Background saving error");
1048 redisLog(REDIS_WARNING
,
1049 "Background saving terminated by signal %d", bysignal
);
1050 rdbRemoveTempFile(server
.bgsavechildpid
);
1052 server
.bgsavechildpid
= -1;
1053 server
.bgsavethread
= (pthread_t
) -1;
1054 server
.bgsavethread_state
= REDIS_BGSAVE_THREAD_UNACTIVE
;
1055 /* Possibly there are slaves waiting for a BGSAVE in order to be served
1056 * (the first stage of SYNC is a bulk transfer of dump.rdb) */
1057 updateSlavesWaitingBgsave(exitcode
== 0 ? REDIS_OK
: REDIS_ERR
);
1060 void saveCommand(redisClient
*c
) {
1061 if (server
.bgsavechildpid
!= -1 || server
.bgsavethread
!= (pthread_t
)-1) {
1062 addReplyError(c
,"Background save already in progress");
1065 if (rdbSave(server
.dbfilename
) == REDIS_OK
) {
1066 addReply(c
,shared
.ok
);
1068 addReply(c
,shared
.err
);
1072 void bgsaveCommand(redisClient
*c
) {
1073 if (server
.bgsavechildpid
!= -1 || server
.bgsavethread
!= (pthread_t
)-1) {
1074 addReplyError(c
,"Background save already in progress");
1077 if (rdbSaveBackground(server
.dbfilename
) == REDIS_OK
) {
1078 addReplyStatus(c
,"Background saving started");
1080 addReply(c
,shared
.err
);