2 #include "lzf.h" /* LZF compression library */
7 #include <sys/resource.h>
12 static int rdbWriteRaw(rio
*rdb
, void *p
, size_t len
) {
13 if (rdb
&& rioWrite(rdb
,p
,len
) == 0)
18 int rdbSaveType(rio
*rdb
, unsigned char type
) {
19 return rdbWriteRaw(rdb
,&type
,1);
22 int rdbLoadType(rio
*rdb
) {
24 if (rioRead(rdb
,&type
,1) == 0) return -1;
28 int rdbSaveTime(rio
*rdb
, time_t t
) {
29 int32_t t32
= (int32_t) t
;
30 return rdbWriteRaw(rdb
,&t32
,4);
33 time_t rdbLoadTime(rio
*rdb
) {
35 if (rioRead(rdb
,&t32
,4) == 0) return -1;
39 /* Saves an encoded length. The first two bits in the first byte are used to
40 * hold the encoding type. See the REDIS_RDB_* definitions for more information
41 * on the types of encoding. */
42 int rdbSaveLen(rio
*rdb
, uint32_t len
) {
47 /* Save a 6 bit len */
48 buf
[0] = (len
&0xFF)|(REDIS_RDB_6BITLEN
<<6);
49 if (rdbWriteRaw(rdb
,buf
,1) == -1) return -1;
51 } else if (len
< (1<<14)) {
52 /* Save a 14 bit len */
53 buf
[0] = ((len
>>8)&0xFF)|(REDIS_RDB_14BITLEN
<<6);
55 if (rdbWriteRaw(rdb
,buf
,2) == -1) return -1;
58 /* Save a 32 bit len */
59 buf
[0] = (REDIS_RDB_32BITLEN
<<6);
60 if (rdbWriteRaw(rdb
,buf
,1) == -1) return -1;
62 if (rdbWriteRaw(rdb
,&len
,4) == -4) return -1;
68 /* Load an encoded length. The "isencoded" argument is set to 1 if the length
69 * is not actually a length but an "encoding type". See the REDIS_RDB_ENC_*
70 * definitions in rdb.h for more information. */
71 uint32_t rdbLoadLen(rio
*rdb
, int *isencoded
) {
76 if (isencoded
) *isencoded
= 0;
77 if (rioRead(rdb
,buf
,1) == 0) return REDIS_RDB_LENERR
;
78 type
= (buf
[0]&0xC0)>>6;
79 if (type
== REDIS_RDB_ENCVAL
) {
80 /* Read a 6 bit encoding type. */
81 if (isencoded
) *isencoded
= 1;
83 } else if (type
== REDIS_RDB_6BITLEN
) {
84 /* Read a 6 bit len. */
86 } else if (type
== REDIS_RDB_14BITLEN
) {
87 /* Read a 14 bit len. */
88 if (rioRead(rdb
,buf
+1,1) == 0) return REDIS_RDB_LENERR
;
89 return ((buf
[0]&0x3F)<<8)|buf
[1];
91 /* Read a 32 bit len. */
92 if (rioRead(rdb
,&len
,4) == 0) return REDIS_RDB_LENERR
;
97 /* Encodes the "value" argument as integer when it fits in the supported ranges
98 * for encoded types. If the function successfully encodes the integer, the
99 * representation is stored in the buffer pointer to by "enc" and the string
100 * length is returned. Otherwise 0 is returned. */
101 int rdbEncodeInteger(long long value
, unsigned char *enc
) {
102 if (value
>= -(1<<7) && value
<= (1<<7)-1) {
103 enc
[0] = (REDIS_RDB_ENCVAL
<<6)|REDIS_RDB_ENC_INT8
;
106 } else if (value
>= -(1<<15) && value
<= (1<<15)-1) {
107 enc
[0] = (REDIS_RDB_ENCVAL
<<6)|REDIS_RDB_ENC_INT16
;
109 enc
[2] = (value
>>8)&0xFF;
111 } else if (value
>= -((long long)1<<31) && value
<= ((long long)1<<31)-1) {
112 enc
[0] = (REDIS_RDB_ENCVAL
<<6)|REDIS_RDB_ENC_INT32
;
114 enc
[2] = (value
>>8)&0xFF;
115 enc
[3] = (value
>>16)&0xFF;
116 enc
[4] = (value
>>24)&0xFF;
123 /* Loads an integer-encoded object with the specified encoding type "enctype".
124 * If the "encode" argument is set the function may return an integer-encoded
125 * string object, otherwise it always returns a raw string object. */
126 robj
*rdbLoadIntegerObject(rio
*rdb
, int enctype
, int encode
) {
127 unsigned char enc
[4];
130 if (enctype
== REDIS_RDB_ENC_INT8
) {
131 if (rioRead(rdb
,enc
,1) == 0) return NULL
;
132 val
= (signed char)enc
[0];
133 } else if (enctype
== REDIS_RDB_ENC_INT16
) {
135 if (rioRead(rdb
,enc
,2) == 0) return NULL
;
136 v
= enc
[0]|(enc
[1]<<8);
138 } else if (enctype
== REDIS_RDB_ENC_INT32
) {
140 if (rioRead(rdb
,enc
,4) == 0) return NULL
;
141 v
= enc
[0]|(enc
[1]<<8)|(enc
[2]<<16)|(enc
[3]<<24);
144 val
= 0; /* anti-warning */
145 redisPanic("Unknown RDB integer encoding type");
148 return createStringObjectFromLongLong(val
);
150 return createObject(REDIS_STRING
,sdsfromlonglong(val
));
153 /* String objects in the form "2391" "-100" without any space and with a
154 * range of values that can fit in an 8, 16 or 32 bit signed value can be
155 * encoded as integers to save space */
156 int rdbTryIntegerEncoding(char *s
, size_t len
, unsigned char *enc
) {
158 char *endptr
, buf
[32];
160 /* Check if it's possible to encode this value as a number */
161 value
= strtoll(s
, &endptr
, 10);
162 if (endptr
[0] != '\0') return 0;
163 ll2string(buf
,32,value
);
165 /* If the number converted back into a string is not identical
166 * then it's not possible to encode the string as integer */
167 if (strlen(buf
) != len
|| memcmp(buf
,s
,len
)) return 0;
169 return rdbEncodeInteger(value
,enc
);
172 int rdbSaveLzfStringObject(rio
*rdb
, unsigned char *s
, size_t len
) {
173 size_t comprlen
, outlen
;
178 /* We require at least four bytes compression for this to be worth it */
179 if (len
<= 4) return 0;
181 if ((out
= zmalloc(outlen
+1)) == NULL
) return 0;
182 comprlen
= lzf_compress(s
, len
, out
, outlen
);
187 /* Data compressed! Let's save it on disk */
188 byte
= (REDIS_RDB_ENCVAL
<<6)|REDIS_RDB_ENC_LZF
;
189 if ((n
= rdbWriteRaw(rdb
,&byte
,1)) == -1) goto writeerr
;
192 if ((n
= rdbSaveLen(rdb
,comprlen
)) == -1) goto writeerr
;
195 if ((n
= rdbSaveLen(rdb
,len
)) == -1) goto writeerr
;
198 if ((n
= rdbWriteRaw(rdb
,out
,comprlen
)) == -1) goto writeerr
;
209 robj
*rdbLoadLzfStringObject(rio
*rdb
) {
210 unsigned int len
, clen
;
211 unsigned char *c
= NULL
;
214 if ((clen
= rdbLoadLen(rdb
,NULL
)) == REDIS_RDB_LENERR
) return NULL
;
215 if ((len
= rdbLoadLen(rdb
,NULL
)) == REDIS_RDB_LENERR
) return NULL
;
216 if ((c
= zmalloc(clen
)) == NULL
) goto err
;
217 if ((val
= sdsnewlen(NULL
,len
)) == NULL
) goto err
;
218 if (rioRead(rdb
,c
,clen
) == 0) goto err
;
219 if (lzf_decompress(c
,clen
,val
,len
) == 0) goto err
;
221 return createObject(REDIS_STRING
,val
);
228 /* Save a string objet as [len][data] on disk. If the object is a string
229 * representation of an integer value we try to save it in a special form */
230 int rdbSaveRawString(rio
*rdb
, unsigned char *s
, size_t len
) {
234 /* Try integer encoding */
236 unsigned char buf
[5];
237 if ((enclen
= rdbTryIntegerEncoding((char*)s
,len
,buf
)) > 0) {
238 if (rdbWriteRaw(rdb
,buf
,enclen
) == -1) return -1;
243 /* Try LZF compression - under 20 bytes it's unable to compress even
244 * aaaaaaaaaaaaaaaaaa so skip it */
245 if (server
.rdbcompression
&& len
> 20) {
246 n
= rdbSaveLzfStringObject(rdb
,s
,len
);
247 if (n
== -1) return -1;
249 /* Return value of 0 means data can't be compressed, save the old way */
253 if ((n
= rdbSaveLen(rdb
,len
)) == -1) return -1;
256 if (rdbWriteRaw(rdb
,s
,len
) == -1) return -1;
262 /* Save a long long value as either an encoded string or a string. */
263 int rdbSaveLongLongAsStringObject(rio
*rdb
, long long value
) {
264 unsigned char buf
[32];
266 int enclen
= rdbEncodeInteger(value
,buf
);
268 return rdbWriteRaw(rdb
,buf
,enclen
);
270 /* Encode as string */
271 enclen
= ll2string((char*)buf
,32,value
);
272 redisAssert(enclen
< 32);
273 if ((n
= rdbSaveLen(rdb
,enclen
)) == -1) return -1;
275 if ((n
= rdbWriteRaw(rdb
,buf
,enclen
)) == -1) return -1;
281 /* Like rdbSaveStringObjectRaw() but handle encoded objects */
282 int rdbSaveStringObject(rio
*rdb
, robj
*obj
) {
283 /* Avoid to decode the object, then encode it again, if the
284 * object is alrady integer encoded. */
285 if (obj
->encoding
== REDIS_ENCODING_INT
) {
286 return rdbSaveLongLongAsStringObject(rdb
,(long)obj
->ptr
);
288 redisAssertWithInfo(NULL
,obj
,obj
->encoding
== REDIS_ENCODING_RAW
);
289 return rdbSaveRawString(rdb
,obj
->ptr
,sdslen(obj
->ptr
));
293 robj
*rdbGenericLoadStringObject(rio
*rdb
, int encode
) {
298 len
= rdbLoadLen(rdb
,&isencoded
);
301 case REDIS_RDB_ENC_INT8
:
302 case REDIS_RDB_ENC_INT16
:
303 case REDIS_RDB_ENC_INT32
:
304 return rdbLoadIntegerObject(rdb
,len
,encode
);
305 case REDIS_RDB_ENC_LZF
:
306 return rdbLoadLzfStringObject(rdb
);
308 redisPanic("Unknown RDB encoding type");
312 if (len
== REDIS_RDB_LENERR
) return NULL
;
313 val
= sdsnewlen(NULL
,len
);
314 if (len
&& rioRead(rdb
,val
,len
) == 0) {
318 return createObject(REDIS_STRING
,val
);
321 robj
*rdbLoadStringObject(rio
*rdb
) {
322 return rdbGenericLoadStringObject(rdb
,0);
325 robj
*rdbLoadEncodedStringObject(rio
*rdb
) {
326 return rdbGenericLoadStringObject(rdb
,1);
329 /* Save a double value. Doubles are saved as strings prefixed by an unsigned
330 * 8 bit integer specifing the length of the representation.
331 * This 8 bit integer has special values in order to specify the following
337 int rdbSaveDoubleValue(rio
*rdb
, double val
) {
338 unsigned char buf
[128];
344 } else if (!isfinite(val
)) {
346 buf
[0] = (val
< 0) ? 255 : 254;
348 #if (DBL_MANT_DIG >= 52) && (LLONG_MAX == 0x7fffffffffffffffLL)
349 /* Check if the float is in a safe range to be casted into a
350 * long long. We are assuming that long long is 64 bit here.
351 * Also we are assuming that there are no implementations around where
352 * double has precision < 52 bit.
354 * Under this assumptions we test if a double is inside an interval
355 * where casting to long long is safe. Then using two castings we
356 * make sure the decimal part is zero. If all this is true we use
357 * integer printing function that is much faster. */
358 double min
= -4503599627370495; /* (2^52)-1 */
359 double max
= 4503599627370496; /* -(2^52) */
360 if (val
> min
&& val
< max
&& val
== ((double)((long long)val
)))
361 ll2string((char*)buf
+1,sizeof(buf
),(long long)val
);
364 snprintf((char*)buf
+1,sizeof(buf
)-1,"%.17g",val
);
365 buf
[0] = strlen((char*)buf
+1);
368 return rdbWriteRaw(rdb
,buf
,len
);
371 /* For information about double serialization check rdbSaveDoubleValue() */
372 int rdbLoadDoubleValue(rio
*rdb
, double *val
) {
376 if (rioRead(rdb
,&len
,1) == 0) return -1;
378 case 255: *val
= R_NegInf
; return 0;
379 case 254: *val
= R_PosInf
; return 0;
380 case 253: *val
= R_Nan
; return 0;
382 if (rioRead(rdb
,buf
,len
) == 0) return -1;
384 sscanf(buf
, "%lg", val
);
389 /* Save the object type of object "o". */
390 int rdbSaveObjectType(rio
*rdb
, robj
*o
) {
393 return rdbSaveType(rdb
,REDIS_RDB_TYPE_STRING
);
395 if (o
->encoding
== REDIS_ENCODING_ZIPLIST
)
396 return rdbSaveType(rdb
,REDIS_RDB_TYPE_LIST_ZIPLIST
);
397 else if (o
->encoding
== REDIS_ENCODING_LINKEDLIST
)
398 return rdbSaveType(rdb
,REDIS_RDB_TYPE_LIST
);
400 redisPanic("Unknown list encoding");
402 if (o
->encoding
== REDIS_ENCODING_INTSET
)
403 return rdbSaveType(rdb
,REDIS_RDB_TYPE_SET_INTSET
);
404 else if (o
->encoding
== REDIS_ENCODING_HT
)
405 return rdbSaveType(rdb
,REDIS_RDB_TYPE_SET
);
407 redisPanic("Unknown set encoding");
409 if (o
->encoding
== REDIS_ENCODING_ZIPLIST
)
410 return rdbSaveType(rdb
,REDIS_RDB_TYPE_ZSET_ZIPLIST
);
411 else if (o
->encoding
== REDIS_ENCODING_SKIPLIST
)
412 return rdbSaveType(rdb
,REDIS_RDB_TYPE_ZSET
);
414 redisPanic("Unknown sorted set encoding");
416 if (o
->encoding
== REDIS_ENCODING_ZIPMAP
)
417 return rdbSaveType(rdb
,REDIS_RDB_TYPE_HASH_ZIPMAP
);
418 else if (o
->encoding
== REDIS_ENCODING_HT
)
419 return rdbSaveType(rdb
,REDIS_RDB_TYPE_HASH
);
421 redisPanic("Unknown hash encoding");
423 redisPanic("Unknown object type");
425 return -1; /* avoid warning */
428 /* Load object type. Return -1 when the byte doesn't contain an object type. */
429 int rdbLoadObjectType(rio
*rdb
) {
431 if ((type
= rdbLoadType(rdb
)) == -1) return -1;
432 if (!rdbIsObjectType(type
)) return -1;
436 /* Save a Redis object. Returns -1 on error, 0 on success. */
437 int rdbSaveObject(rio
*rdb
, robj
*o
) {
440 if (o
->type
== REDIS_STRING
) {
441 /* Save a string value */
442 if ((n
= rdbSaveStringObject(rdb
,o
)) == -1) return -1;
444 } else if (o
->type
== REDIS_LIST
) {
445 /* Save a list value */
446 if (o
->encoding
== REDIS_ENCODING_ZIPLIST
) {
447 size_t l
= ziplistBlobLen((unsigned char*)o
->ptr
);
449 if ((n
= rdbSaveRawString(rdb
,o
->ptr
,l
)) == -1) return -1;
451 } else if (o
->encoding
== REDIS_ENCODING_LINKEDLIST
) {
456 if ((n
= rdbSaveLen(rdb
,listLength(list
))) == -1) return -1;
459 listRewind(list
,&li
);
460 while((ln
= listNext(&li
))) {
461 robj
*eleobj
= listNodeValue(ln
);
462 if ((n
= rdbSaveStringObject(rdb
,eleobj
)) == -1) return -1;
466 redisPanic("Unknown list encoding");
468 } else if (o
->type
== REDIS_SET
) {
469 /* Save a set value */
470 if (o
->encoding
== REDIS_ENCODING_HT
) {
472 dictIterator
*di
= dictGetIterator(set
);
475 if ((n
= rdbSaveLen(rdb
,dictSize(set
))) == -1) return -1;
478 while((de
= dictNext(di
)) != NULL
) {
479 robj
*eleobj
= dictGetEntryKey(de
);
480 if ((n
= rdbSaveStringObject(rdb
,eleobj
)) == -1) return -1;
483 dictReleaseIterator(di
);
484 } else if (o
->encoding
== REDIS_ENCODING_INTSET
) {
485 size_t l
= intsetBlobLen((intset
*)o
->ptr
);
487 if ((n
= rdbSaveRawString(rdb
,o
->ptr
,l
)) == -1) return -1;
490 redisPanic("Unknown set encoding");
492 } else if (o
->type
== REDIS_ZSET
) {
493 /* Save a sorted set value */
494 if (o
->encoding
== REDIS_ENCODING_ZIPLIST
) {
495 size_t l
= ziplistBlobLen((unsigned char*)o
->ptr
);
497 if ((n
= rdbSaveRawString(rdb
,o
->ptr
,l
)) == -1) return -1;
499 } else if (o
->encoding
== REDIS_ENCODING_SKIPLIST
) {
501 dictIterator
*di
= dictGetIterator(zs
->dict
);
504 if ((n
= rdbSaveLen(rdb
,dictSize(zs
->dict
))) == -1) return -1;
507 while((de
= dictNext(di
)) != NULL
) {
508 robj
*eleobj
= dictGetEntryKey(de
);
509 double *score
= dictGetEntryVal(de
);
511 if ((n
= rdbSaveStringObject(rdb
,eleobj
)) == -1) return -1;
513 if ((n
= rdbSaveDoubleValue(rdb
,*score
)) == -1) return -1;
516 dictReleaseIterator(di
);
518 redisPanic("Unknown sorted set encoding");
520 } else if (o
->type
== REDIS_HASH
) {
521 /* Save a hash value */
522 if (o
->encoding
== REDIS_ENCODING_ZIPMAP
) {
523 size_t l
= zipmapBlobLen((unsigned char*)o
->ptr
);
525 if ((n
= rdbSaveRawString(rdb
,o
->ptr
,l
)) == -1) return -1;
528 dictIterator
*di
= dictGetIterator(o
->ptr
);
531 if ((n
= rdbSaveLen(rdb
,dictSize((dict
*)o
->ptr
))) == -1) return -1;
534 while((de
= dictNext(di
)) != NULL
) {
535 robj
*key
= dictGetEntryKey(de
);
536 robj
*val
= dictGetEntryVal(de
);
538 if ((n
= rdbSaveStringObject(rdb
,key
)) == -1) return -1;
540 if ((n
= rdbSaveStringObject(rdb
,val
)) == -1) return -1;
543 dictReleaseIterator(di
);
546 redisPanic("Unknown object type");
551 /* Return the length the object will have on disk if saved with
552 * the rdbSaveObject() function. Currently we use a trick to get
553 * this length with very little changes to the code. In the future
554 * we could switch to a faster solution. */
555 off_t
rdbSavedObjectLen(robj
*o
) {
556 int len
= rdbSaveObject(NULL
,o
);
557 redisAssertWithInfo(NULL
,o
,len
!= -1);
561 /* Save a key-value pair, with expire time, type, key, value.
562 * On error -1 is returned.
563 * On success if the key was actaully saved 1 is returned, otherwise 0
564 * is returned (the key was already expired). */
565 int rdbSaveKeyValuePair(rio
*rdb
, robj
*key
, robj
*val
,
566 time_t expiretime
, time_t now
)
568 /* Save the expire time */
569 if (expiretime
!= -1) {
570 /* If this key is already expired skip it */
571 if (expiretime
< now
) return 0;
572 if (rdbSaveType(rdb
,REDIS_RDB_OPCODE_EXPIRETIME
) == -1) return -1;
573 if (rdbSaveTime(rdb
,expiretime
) == -1) return -1;
576 /* Save type, key, value */
577 if (rdbSaveObjectType(rdb
,val
) == -1) return -1;
578 if (rdbSaveStringObject(rdb
,key
) == -1) return -1;
579 if (rdbSaveObject(rdb
,val
) == -1) return -1;
583 /* Save the DB on disk. Return REDIS_ERR on error, REDIS_OK on success */
584 int rdbSave(char *filename
) {
585 dictIterator
*di
= NULL
;
589 time_t now
= time(NULL
);
593 snprintf(tmpfile
,256,"temp-%d.rdb", (int) getpid());
594 fp
= fopen(tmpfile
,"w");
596 redisLog(REDIS_WARNING
, "Failed opening .rdb for saving: %s",
601 rioInitWithFile(&rdb
,fp
);
602 if (rdbWriteRaw(&rdb
,"REDIS0002",9) == -1) goto werr
;
604 for (j
= 0; j
< server
.dbnum
; j
++) {
605 redisDb
*db
= server
.db
+j
;
607 if (dictSize(d
) == 0) continue;
608 di
= dictGetSafeIterator(d
);
614 /* Write the SELECT DB opcode */
615 if (rdbSaveType(&rdb
,REDIS_RDB_OPCODE_SELECTDB
) == -1) goto werr
;
616 if (rdbSaveLen(&rdb
,j
) == -1) goto werr
;
618 /* Iterate this DB writing every entry */
619 while((de
= dictNext(di
)) != NULL
) {
620 sds keystr
= dictGetEntryKey(de
);
621 robj key
, *o
= dictGetEntryVal(de
);
624 initStaticStringObject(key
,keystr
);
625 expire
= getExpire(db
,&key
);
626 if (rdbSaveKeyValuePair(&rdb
,&key
,o
,expire
,now
) == -1) goto werr
;
628 dictReleaseIterator(di
);
631 if (rdbSaveType(&rdb
,REDIS_RDB_OPCODE_EOF
) == -1) goto werr
;
633 /* Make sure data will not remain on the OS's output buffers */
638 /* Use RENAME to make sure the DB file is changed atomically only
639 * if the generate DB file is ok. */
640 if (rename(tmpfile
,filename
) == -1) {
641 redisLog(REDIS_WARNING
,"Error moving temp DB file on the final destination: %s", strerror(errno
));
645 redisLog(REDIS_NOTICE
,"DB saved on disk");
647 server
.lastsave
= time(NULL
);
653 redisLog(REDIS_WARNING
,"Write error saving DB on disk: %s", strerror(errno
));
654 if (di
) dictReleaseIterator(di
);
658 int rdbSaveBackground(char *filename
) {
662 if (server
.bgsavechildpid
!= -1) return REDIS_ERR
;
664 server
.dirty_before_bgsave
= server
.dirty
;
667 if ((childpid
= fork()) == 0) {
671 if (server
.ipfd
> 0) close(server
.ipfd
);
672 if (server
.sofd
> 0) close(server
.sofd
);
673 retval
= rdbSave(filename
);
674 _exit((retval
== REDIS_OK
) ? 0 : 1);
677 server
.stat_fork_time
= ustime()-start
;
678 if (childpid
== -1) {
679 redisLog(REDIS_WARNING
,"Can't save in background: fork: %s",
683 redisLog(REDIS_NOTICE
,"Background saving started by pid %d",childpid
);
684 server
.bgsavechildpid
= childpid
;
685 updateDictResizePolicy();
688 return REDIS_OK
; /* unreached */
691 void rdbRemoveTempFile(pid_t childpid
) {
694 snprintf(tmpfile
,256,"temp-%d.rdb", (int) childpid
);
698 /* Load a Redis object of the specified type from the specified file.
699 * On success a newly allocated object is returned, otherwise NULL. */
700 robj
*rdbLoadObject(int rdbtype
, rio
*rdb
) {
705 redisLog(REDIS_DEBUG
,"LOADING OBJECT %d (at %d)\n",rdbtype
,rdb
->tell(rdb
));
706 if (rdbtype
== REDIS_RDB_TYPE_STRING
) {
707 /* Read string value */
708 if ((o
= rdbLoadEncodedStringObject(rdb
)) == NULL
) return NULL
;
709 o
= tryObjectEncoding(o
);
710 } else if (rdbtype
== REDIS_RDB_TYPE_LIST
) {
711 /* Read list value */
712 if ((len
= rdbLoadLen(rdb
,NULL
)) == REDIS_RDB_LENERR
) return NULL
;
714 /* Use a real list when there are too many entries */
715 if (len
> server
.list_max_ziplist_entries
) {
716 o
= createListObject();
718 o
= createZiplistObject();
721 /* Load every single element of the list */
723 if ((ele
= rdbLoadEncodedStringObject(rdb
)) == NULL
) return NULL
;
725 /* If we are using a ziplist and the value is too big, convert
726 * the object to a real list. */
727 if (o
->encoding
== REDIS_ENCODING_ZIPLIST
&&
728 ele
->encoding
== REDIS_ENCODING_RAW
&&
729 sdslen(ele
->ptr
) > server
.list_max_ziplist_value
)
730 listTypeConvert(o
,REDIS_ENCODING_LINKEDLIST
);
732 if (o
->encoding
== REDIS_ENCODING_ZIPLIST
) {
733 dec
= getDecodedObject(ele
);
734 o
->ptr
= ziplistPush(o
->ptr
,dec
->ptr
,sdslen(dec
->ptr
),REDIS_TAIL
);
738 ele
= tryObjectEncoding(ele
);
739 listAddNodeTail(o
->ptr
,ele
);
742 } else if (rdbtype
== REDIS_RDB_TYPE_SET
) {
743 /* Read list/set value */
744 if ((len
= rdbLoadLen(rdb
,NULL
)) == REDIS_RDB_LENERR
) return NULL
;
746 /* Use a regular set when there are too many entries. */
747 if (len
> server
.set_max_intset_entries
) {
748 o
= createSetObject();
749 /* It's faster to expand the dict to the right size asap in order
750 * to avoid rehashing */
751 if (len
> DICT_HT_INITIAL_SIZE
)
752 dictExpand(o
->ptr
,len
);
754 o
= createIntsetObject();
757 /* Load every single element of the list/set */
758 for (i
= 0; i
< len
; i
++) {
760 if ((ele
= rdbLoadEncodedStringObject(rdb
)) == NULL
) return NULL
;
761 ele
= tryObjectEncoding(ele
);
763 if (o
->encoding
== REDIS_ENCODING_INTSET
) {
764 /* Fetch integer value from element */
765 if (isObjectRepresentableAsLongLong(ele
,&llval
) == REDIS_OK
) {
766 o
->ptr
= intsetAdd(o
->ptr
,llval
,NULL
);
768 setTypeConvert(o
,REDIS_ENCODING_HT
);
769 dictExpand(o
->ptr
,len
);
773 /* This will also be called when the set was just converted
774 * to regular hashtable encoded set */
775 if (o
->encoding
== REDIS_ENCODING_HT
) {
776 dictAdd((dict
*)o
->ptr
,ele
,NULL
);
781 } else if (rdbtype
== REDIS_RDB_TYPE_ZSET
) {
782 /* Read list/set value */
784 size_t maxelelen
= 0;
787 if ((zsetlen
= rdbLoadLen(rdb
,NULL
)) == REDIS_RDB_LENERR
) return NULL
;
788 o
= createZsetObject();
791 /* Load every single element of the list/set */
795 zskiplistNode
*znode
;
797 if ((ele
= rdbLoadEncodedStringObject(rdb
)) == NULL
) return NULL
;
798 ele
= tryObjectEncoding(ele
);
799 if (rdbLoadDoubleValue(rdb
,&score
) == -1) return NULL
;
801 /* Don't care about integer-encoded strings. */
802 if (ele
->encoding
== REDIS_ENCODING_RAW
&&
803 sdslen(ele
->ptr
) > maxelelen
)
804 maxelelen
= sdslen(ele
->ptr
);
806 znode
= zslInsert(zs
->zsl
,score
,ele
);
807 dictAdd(zs
->dict
,ele
,&znode
->score
);
808 incrRefCount(ele
); /* added to skiplist */
811 /* Convert *after* loading, since sorted sets are not stored ordered. */
812 if (zsetLength(o
) <= server
.zset_max_ziplist_entries
&&
813 maxelelen
<= server
.zset_max_ziplist_value
)
814 zsetConvert(o
,REDIS_ENCODING_ZIPLIST
);
815 } else if (rdbtype
== REDIS_RDB_TYPE_HASH
) {
818 if ((hashlen
= rdbLoadLen(rdb
,NULL
)) == REDIS_RDB_LENERR
) return NULL
;
819 o
= createHashObject();
820 /* Too many entries? Use an hash table. */
821 if (hashlen
> server
.hash_max_zipmap_entries
)
822 convertToRealHash(o
);
823 /* Load every key/value, then set it into the zipmap or hash
824 * table, as needed. */
828 if ((key
= rdbLoadEncodedStringObject(rdb
)) == NULL
) return NULL
;
829 if ((val
= rdbLoadEncodedStringObject(rdb
)) == NULL
) return NULL
;
830 /* If we are using a zipmap and there are too big values
831 * the object is converted to real hash table encoding. */
832 if (o
->encoding
!= REDIS_ENCODING_HT
&&
833 ((key
->encoding
== REDIS_ENCODING_RAW
&&
834 sdslen(key
->ptr
) > server
.hash_max_zipmap_value
) ||
835 (val
->encoding
== REDIS_ENCODING_RAW
&&
836 sdslen(val
->ptr
) > server
.hash_max_zipmap_value
)))
838 convertToRealHash(o
);
841 if (o
->encoding
== REDIS_ENCODING_ZIPMAP
) {
842 unsigned char *zm
= o
->ptr
;
843 robj
*deckey
, *decval
;
845 /* We need raw string objects to add them to the zipmap */
846 deckey
= getDecodedObject(key
);
847 decval
= getDecodedObject(val
);
848 zm
= zipmapSet(zm
,deckey
->ptr
,sdslen(deckey
->ptr
),
849 decval
->ptr
,sdslen(decval
->ptr
),NULL
);
851 decrRefCount(deckey
);
852 decrRefCount(decval
);
856 key
= tryObjectEncoding(key
);
857 val
= tryObjectEncoding(val
);
858 dictAdd((dict
*)o
->ptr
,key
,val
);
861 } else if (rdbtype
== REDIS_RDB_TYPE_HASH_ZIPMAP
||
862 rdbtype
== REDIS_RDB_TYPE_LIST_ZIPLIST
||
863 rdbtype
== REDIS_RDB_TYPE_SET_INTSET
||
864 rdbtype
== REDIS_RDB_TYPE_ZSET_ZIPLIST
)
866 robj
*aux
= rdbLoadStringObject(rdb
);
868 if (aux
== NULL
) return NULL
;
869 o
= createObject(REDIS_STRING
,NULL
); /* string is just placeholder */
870 o
->ptr
= zmalloc(sdslen(aux
->ptr
));
871 memcpy(o
->ptr
,aux
->ptr
,sdslen(aux
->ptr
));
874 /* Fix the object encoding, and make sure to convert the encoded
875 * data type into the base type if accordingly to the current
876 * configuration there are too many elements in the encoded data
877 * type. Note that we only check the length and not max element
878 * size as this is an O(N) scan. Eventually everything will get
881 case REDIS_RDB_TYPE_HASH_ZIPMAP
:
882 o
->type
= REDIS_HASH
;
883 o
->encoding
= REDIS_ENCODING_ZIPMAP
;
884 if (zipmapLen(o
->ptr
) > server
.hash_max_zipmap_entries
)
885 convertToRealHash(o
);
887 case REDIS_RDB_TYPE_LIST_ZIPLIST
:
888 o
->type
= REDIS_LIST
;
889 o
->encoding
= REDIS_ENCODING_ZIPLIST
;
890 if (ziplistLen(o
->ptr
) > server
.list_max_ziplist_entries
)
891 listTypeConvert(o
,REDIS_ENCODING_LINKEDLIST
);
893 case REDIS_RDB_TYPE_SET_INTSET
:
895 o
->encoding
= REDIS_ENCODING_INTSET
;
896 if (intsetLen(o
->ptr
) > server
.set_max_intset_entries
)
897 setTypeConvert(o
,REDIS_ENCODING_HT
);
899 case REDIS_RDB_TYPE_ZSET_ZIPLIST
:
900 o
->type
= REDIS_ZSET
;
901 o
->encoding
= REDIS_ENCODING_ZIPLIST
;
902 if (zsetLength(o
) > server
.zset_max_ziplist_entries
)
903 zsetConvert(o
,REDIS_ENCODING_SKIPLIST
);
906 redisPanic("Unknown encoding");
910 redisPanic("Unknown object type");
915 /* Mark that we are loading in the global state and setup the fields
916 * needed to provide loading stats. */
917 void startLoading(FILE *fp
) {
922 server
.loading_start_time
= time(NULL
);
923 if (fstat(fileno(fp
), &sb
) == -1) {
924 server
.loading_total_bytes
= 1; /* just to avoid division by zero */
926 server
.loading_total_bytes
= sb
.st_size
;
930 /* Refresh the loading progress info */
931 void loadingProgress(off_t pos
) {
932 server
.loading_loaded_bytes
= pos
;
935 /* Loading finished */
936 void stopLoading(void) {
940 int rdbLoad(char *filename
) {
943 redisDb
*db
= server
.db
+0;
945 time_t expiretime
, now
= time(NULL
);
950 fp
= fopen(filename
,"r");
955 rioInitWithFile(&rdb
,fp
);
956 if (rioRead(&rdb
,buf
,9) == 0) goto eoferr
;
958 if (memcmp(buf
,"REDIS",5) != 0) {
960 redisLog(REDIS_WARNING
,"Wrong signature trying to load DB from file");
964 rdbver
= atoi(buf
+5);
965 if (rdbver
< 1 || rdbver
> 2) {
967 redisLog(REDIS_WARNING
,"Can't handle RDB format version %d",rdbver
);
977 /* Serve the clients from time to time */
978 if (!(loops
++ % 1000)) {
979 loadingProgress(rdb
.tell(&rdb
));
980 aeProcessEvents(server
.el
, AE_FILE_EVENTS
|AE_DONT_WAIT
);
984 if ((type
= rdbLoadType(&rdb
)) == -1) goto eoferr
;
985 if (type
== REDIS_RDB_OPCODE_EXPIRETIME
) {
986 if ((expiretime
= rdbLoadTime(&rdb
)) == -1) goto eoferr
;
987 /* We read the time so we need to read the object type again. */
988 if ((type
= rdbLoadType(&rdb
)) == -1) goto eoferr
;
991 if (type
== REDIS_RDB_OPCODE_EOF
)
994 /* Handle SELECT DB opcode as a special case */
995 if (type
== REDIS_RDB_OPCODE_SELECTDB
) {
996 if ((dbid
= rdbLoadLen(&rdb
,NULL
)) == REDIS_RDB_LENERR
)
998 if (dbid
>= (unsigned)server
.dbnum
) {
999 redisLog(REDIS_WARNING
,"FATAL: Data file was created with a Redis server configured to handle more than %d databases. Exiting\n", server
.dbnum
);
1002 db
= server
.db
+dbid
;
1006 if ((key
= rdbLoadStringObject(&rdb
)) == NULL
) goto eoferr
;
1008 if ((val
= rdbLoadObject(type
,&rdb
)) == NULL
) goto eoferr
;
1009 /* Check if the key already expired */
1010 if (expiretime
!= -1 && expiretime
< now
) {
1015 /* Add the new object in the hash table */
1018 /* Set the expire time if needed */
1019 if (expiretime
!= -1) setExpire(db
,key
,expiretime
);
1027 eoferr
: /* unexpected end of file is handled here with a fatal exit */
1028 redisLog(REDIS_WARNING
,"Short read or OOM loading DB. Unrecoverable error, aborting now.");
1030 return REDIS_ERR
; /* Just to avoid warning */
1033 /* A background saving child (BGSAVE) terminated its work. Handle this. */
1034 void backgroundSaveDoneHandler(int exitcode
, int bysignal
) {
1035 if (!bysignal
&& exitcode
== 0) {
1036 redisLog(REDIS_NOTICE
,
1037 "Background saving terminated with success");
1038 server
.dirty
= server
.dirty
- server
.dirty_before_bgsave
;
1039 server
.lastsave
= time(NULL
);
1040 } else if (!bysignal
&& exitcode
!= 0) {
1041 redisLog(REDIS_WARNING
, "Background saving error");
1043 redisLog(REDIS_WARNING
,
1044 "Background saving terminated by signal %d", bysignal
);
1045 rdbRemoveTempFile(server
.bgsavechildpid
);
1047 server
.bgsavechildpid
= -1;
1048 /* Possibly there are slaves waiting for a BGSAVE in order to be served
1049 * (the first stage of SYNC is a bulk transfer of dump.rdb) */
1050 updateSlavesWaitingBgsave(exitcode
== 0 ? REDIS_OK
: REDIS_ERR
);
1053 void saveCommand(redisClient
*c
) {
1054 if (server
.bgsavechildpid
!= -1) {
1055 addReplyError(c
,"Background save already in progress");
1058 if (rdbSave(server
.dbfilename
) == REDIS_OK
) {
1059 addReply(c
,shared
.ok
);
1061 addReply(c
,shared
.err
);
1065 void bgsaveCommand(redisClient
*c
) {
1066 if (server
.bgsavechildpid
!= -1) {
1067 addReplyError(c
,"Background save already in progress");
1068 } else if (server
.bgrewritechildpid
!= -1) {
1069 addReplyError(c
,"Can't BGSAVE while AOF log rewriting is in progress");
1070 } else if (rdbSaveBackground(server
.dbfilename
) == REDIS_OK
) {
1071 addReplyStatus(c
,"Background saving started");
1073 addReply(c
,shared
.err
);