xref: /redis-3.2.3/src/rdb.c (revision 28343966)
1 /*
2  * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  *   * Redistributions of source code must retain the above copyright notice,
9  *     this list of conditions and the following disclaimer.
10  *   * Redistributions in binary form must reproduce the above copyright
11  *     notice, this list of conditions and the following disclaimer in the
12  *     documentation and/or other materials provided with the distribution.
13  *   * Neither the name of Redis nor the names of its contributors may be used
14  *     to endorse or promote products derived from this software without
15  *     specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27  * POSSIBILITY OF SUCH DAMAGE.
28  */
29 
30 #include "redis.h"
31 #include "lzf.h"    /* LZF compression library */
32 #include "zipmap.h"
33 #include "endianconv.h"
34 
35 #include <math.h>
36 #include <sys/types.h>
37 #include <sys/time.h>
38 #include <sys/resource.h>
39 #include <sys/wait.h>
40 #include <arpa/inet.h>
41 #include <sys/stat.h>
42 
43 static int rdbWriteRaw(rio *rdb, void *p, size_t len) {
44     if (rdb && rioWrite(rdb,p,len) == 0)
45         return -1;
46     return len;
47 }
48 
49 int rdbSaveType(rio *rdb, unsigned char type) {
50     return rdbWriteRaw(rdb,&type,1);
51 }
52 
53 /* Load a "type" in RDB format, that is a one byte unsigned integer.
54  * This function is not only used to load object types, but also special
55  * "types" like the end-of-file type, the EXPIRE type, and so forth. */
56 int rdbLoadType(rio *rdb) {
57     unsigned char type;
58     if (rioRead(rdb,&type,1) == 0) return -1;
59     return type;
60 }
61 
62 time_t rdbLoadTime(rio *rdb) {
63     int32_t t32;
64     if (rioRead(rdb,&t32,4) == 0) return -1;
65     return (time_t)t32;
66 }
67 
68 int rdbSaveMillisecondTime(rio *rdb, long long t) {
69     int64_t t64 = (int64_t) t;
70     return rdbWriteRaw(rdb,&t64,8);
71 }
72 
73 long long rdbLoadMillisecondTime(rio *rdb) {
74     int64_t t64;
75     if (rioRead(rdb,&t64,8) == 0) return -1;
76     return (long long)t64;
77 }
78 
79 /* Saves an encoded length. The first two bits in the first byte are used to
80  * hold the encoding type. See the REDIS_RDB_* definitions for more information
81  * on the types of encoding. */
82 int rdbSaveLen(rio *rdb, uint32_t len) {
83     unsigned char buf[2];
84     size_t nwritten;
85 
86     if (len < (1<<6)) {
87         /* Save a 6 bit len */
88         buf[0] = (len&0xFF)|(REDIS_RDB_6BITLEN<<6);
89         if (rdbWriteRaw(rdb,buf,1) == -1) return -1;
90         nwritten = 1;
91     } else if (len < (1<<14)) {
92         /* Save a 14 bit len */
93         buf[0] = ((len>>8)&0xFF)|(REDIS_RDB_14BITLEN<<6);
94         buf[1] = len&0xFF;
95         if (rdbWriteRaw(rdb,buf,2) == -1) return -1;
96         nwritten = 2;
97     } else {
98         /* Save a 32 bit len */
99         buf[0] = (REDIS_RDB_32BITLEN<<6);
100         if (rdbWriteRaw(rdb,buf,1) == -1) return -1;
101         len = htonl(len);
102         if (rdbWriteRaw(rdb,&len,4) == -1) return -1;
103         nwritten = 1+4;
104     }
105     return nwritten;
106 }
107 
108 /* Load an encoded length. The "isencoded" argument is set to 1 if the length
109  * is not actually a length but an "encoding type". See the REDIS_RDB_ENC_*
110  * definitions in rdb.h for more information. */
111 uint32_t rdbLoadLen(rio *rdb, int *isencoded) {
112     unsigned char buf[2];
113     uint32_t len;
114     int type;
115 
116     if (isencoded) *isencoded = 0;
117     if (rioRead(rdb,buf,1) == 0) return REDIS_RDB_LENERR;
118     type = (buf[0]&0xC0)>>6;
119     if (type == REDIS_RDB_ENCVAL) {
120         /* Read a 6 bit encoding type. */
121         if (isencoded) *isencoded = 1;
122         return buf[0]&0x3F;
123     } else if (type == REDIS_RDB_6BITLEN) {
124         /* Read a 6 bit len. */
125         return buf[0]&0x3F;
126     } else if (type == REDIS_RDB_14BITLEN) {
127         /* Read a 14 bit len. */
128         if (rioRead(rdb,buf+1,1) == 0) return REDIS_RDB_LENERR;
129         return ((buf[0]&0x3F)<<8)|buf[1];
130     } else {
131         /* Read a 32 bit len. */
132         if (rioRead(rdb,&len,4) == 0) return REDIS_RDB_LENERR;
133         return ntohl(len);
134     }
135 }
136 
137 /* Encodes the "value" argument as integer when it fits in the supported ranges
138  * for encoded types. If the function successfully encodes the integer, the
139  * representation is stored in the buffer pointer to by "enc" and the string
140  * length is returned. Otherwise 0 is returned. */
141 int rdbEncodeInteger(long long value, unsigned char *enc) {
142     if (value >= -(1<<7) && value <= (1<<7)-1) {
143         enc[0] = (REDIS_RDB_ENCVAL<<6)|REDIS_RDB_ENC_INT8;
144         enc[1] = value&0xFF;
145         return 2;
146     } else if (value >= -(1<<15) && value <= (1<<15)-1) {
147         enc[0] = (REDIS_RDB_ENCVAL<<6)|REDIS_RDB_ENC_INT16;
148         enc[1] = value&0xFF;
149         enc[2] = (value>>8)&0xFF;
150         return 3;
151     } else if (value >= -((long long)1<<31) && value <= ((long long)1<<31)-1) {
152         enc[0] = (REDIS_RDB_ENCVAL<<6)|REDIS_RDB_ENC_INT32;
153         enc[1] = value&0xFF;
154         enc[2] = (value>>8)&0xFF;
155         enc[3] = (value>>16)&0xFF;
156         enc[4] = (value>>24)&0xFF;
157         return 5;
158     } else {
159         return 0;
160     }
161 }
162 
163 /* Loads an integer-encoded object with the specified encoding type "enctype".
164  * If the "encode" argument is set the function may return an integer-encoded
165  * string object, otherwise it always returns a raw string object. */
166 robj *rdbLoadIntegerObject(rio *rdb, int enctype, int encode) {
167     unsigned char enc[4];
168     long long val;
169 
170     if (enctype == REDIS_RDB_ENC_INT8) {
171         if (rioRead(rdb,enc,1) == 0) return NULL;
172         val = (signed char)enc[0];
173     } else if (enctype == REDIS_RDB_ENC_INT16) {
174         uint16_t v;
175         if (rioRead(rdb,enc,2) == 0) return NULL;
176         v = enc[0]|(enc[1]<<8);
177         val = (int16_t)v;
178     } else if (enctype == REDIS_RDB_ENC_INT32) {
179         uint32_t v;
180         if (rioRead(rdb,enc,4) == 0) return NULL;
181         v = enc[0]|(enc[1]<<8)|(enc[2]<<16)|(enc[3]<<24);
182         val = (int32_t)v;
183     } else {
184         val = 0; /* anti-warning */
185         redisPanic("Unknown RDB integer encoding type");
186     }
187     if (encode)
188         return createStringObjectFromLongLong(val);
189     else
190         return createObject(REDIS_STRING,sdsfromlonglong(val));
191 }
192 
193 /* String objects in the form "2391" "-100" without any space and with a
194  * range of values that can fit in an 8, 16 or 32 bit signed value can be
195  * encoded as integers to save space */
196 int rdbTryIntegerEncoding(char *s, size_t len, unsigned char *enc) {
197     long long value;
198     char *endptr, buf[32];
199 
200     /* Check if it's possible to encode this value as a number */
201     value = strtoll(s, &endptr, 10);
202     if (endptr[0] != '\0') return 0;
203     ll2string(buf,32,value);
204 
205     /* If the number converted back into a string is not identical
206      * then it's not possible to encode the string as integer */
207     if (strlen(buf) != len || memcmp(buf,s,len)) return 0;
208 
209     return rdbEncodeInteger(value,enc);
210 }
211 
212 int rdbSaveLzfStringObject(rio *rdb, unsigned char *s, size_t len) {
213     size_t comprlen, outlen;
214     unsigned char byte;
215     int n, nwritten = 0;
216     void *out;
217 
218     /* We require at least four bytes compression for this to be worth it */
219     if (len <= 4) return 0;
220     outlen = len-4;
221     if ((out = zmalloc(outlen+1)) == NULL) return 0;
222     comprlen = lzf_compress(s, len, out, outlen);
223     if (comprlen == 0) {
224         zfree(out);
225         return 0;
226     }
227     /* Data compressed! Let's save it on disk */
228     byte = (REDIS_RDB_ENCVAL<<6)|REDIS_RDB_ENC_LZF;
229     if ((n = rdbWriteRaw(rdb,&byte,1)) == -1) goto writeerr;
230     nwritten += n;
231 
232     if ((n = rdbSaveLen(rdb,comprlen)) == -1) goto writeerr;
233     nwritten += n;
234 
235     if ((n = rdbSaveLen(rdb,len)) == -1) goto writeerr;
236     nwritten += n;
237 
238     if ((n = rdbWriteRaw(rdb,out,comprlen)) == -1) goto writeerr;
239     nwritten += n;
240 
241     zfree(out);
242     return nwritten;
243 
244 writeerr:
245     zfree(out);
246     return -1;
247 }
248 
249 robj *rdbLoadLzfStringObject(rio *rdb) {
250     unsigned int len, clen;
251     unsigned char *c = NULL;
252     sds val = NULL;
253 
254     if ((clen = rdbLoadLen(rdb,NULL)) == REDIS_RDB_LENERR) return NULL;
255     if ((len = rdbLoadLen(rdb,NULL)) == REDIS_RDB_LENERR) return NULL;
256     if ((c = zmalloc(clen)) == NULL) goto err;
257     if ((val = sdsnewlen(NULL,len)) == NULL) goto err;
258     if (rioRead(rdb,c,clen) == 0) goto err;
259     if (lzf_decompress(c,clen,val,len) == 0) goto err;
260     zfree(c);
261     return createObject(REDIS_STRING,val);
262 err:
263     zfree(c);
264     sdsfree(val);
265     return NULL;
266 }
267 
268 /* Save a string object as [len][data] on disk. If the object is a string
269  * representation of an integer value we try to save it in a special form */
270 int rdbSaveRawString(rio *rdb, unsigned char *s, size_t len) {
271     int enclen;
272     int n, nwritten = 0;
273 
274     /* Try integer encoding */
275     if (len <= 11) {
276         unsigned char buf[5];
277         if ((enclen = rdbTryIntegerEncoding((char*)s,len,buf)) > 0) {
278             if (rdbWriteRaw(rdb,buf,enclen) == -1) return -1;
279             return enclen;
280         }
281     }
282 
283     /* Try LZF compression - under 20 bytes it's unable to compress even
284      * aaaaaaaaaaaaaaaaaa so skip it */
285     if (server.rdb_compression && len > 20) {
286         n = rdbSaveLzfStringObject(rdb,s,len);
287         if (n == -1) return -1;
288         if (n > 0) return n;
289         /* Return value of 0 means data can't be compressed, save the old way */
290     }
291 
292     /* Store verbatim */
293     if ((n = rdbSaveLen(rdb,len)) == -1) return -1;
294     nwritten += n;
295     if (len > 0) {
296         if (rdbWriteRaw(rdb,s,len) == -1) return -1;
297         nwritten += len;
298     }
299     return nwritten;
300 }
301 
302 /* Save a long long value as either an encoded string or a string. */
303 int rdbSaveLongLongAsStringObject(rio *rdb, long long value) {
304     unsigned char buf[32];
305     int n, nwritten = 0;
306     int enclen = rdbEncodeInteger(value,buf);
307     if (enclen > 0) {
308         return rdbWriteRaw(rdb,buf,enclen);
309     } else {
310         /* Encode as string */
311         enclen = ll2string((char*)buf,32,value);
312         redisAssert(enclen < 32);
313         if ((n = rdbSaveLen(rdb,enclen)) == -1) return -1;
314         nwritten += n;
315         if ((n = rdbWriteRaw(rdb,buf,enclen)) == -1) return -1;
316         nwritten += n;
317     }
318     return nwritten;
319 }
320 
321 /* Like rdbSaveStringObjectRaw() but handle encoded objects */
322 int rdbSaveStringObject(rio *rdb, robj *obj) {
323     /* Avoid to decode the object, then encode it again, if the
324      * object is already integer encoded. */
325     if (obj->encoding == REDIS_ENCODING_INT) {
326         return rdbSaveLongLongAsStringObject(rdb,(long)obj->ptr);
327     } else {
328         redisAssertWithInfo(NULL,obj,sdsEncodedObject(obj));
329         return rdbSaveRawString(rdb,obj->ptr,sdslen(obj->ptr));
330     }
331 }
332 
333 robj *rdbGenericLoadStringObject(rio *rdb, int encode) {
334     int isencoded;
335     uint32_t len;
336     robj *o;
337 
338     len = rdbLoadLen(rdb,&isencoded);
339     if (isencoded) {
340         switch(len) {
341         case REDIS_RDB_ENC_INT8:
342         case REDIS_RDB_ENC_INT16:
343         case REDIS_RDB_ENC_INT32:
344             return rdbLoadIntegerObject(rdb,len,encode);
345         case REDIS_RDB_ENC_LZF:
346             return rdbLoadLzfStringObject(rdb);
347         default:
348             redisPanic("Unknown RDB encoding type");
349         }
350     }
351 
352     if (len == REDIS_RDB_LENERR) return NULL;
353     o = encode ? createStringObject(NULL,len) :
354                  createRawStringObject(NULL,len);
355     if (len && rioRead(rdb,o->ptr,len) == 0) {
356         decrRefCount(o);
357         return NULL;
358     }
359     return o;
360 }
361 
362 robj *rdbLoadStringObject(rio *rdb) {
363     return rdbGenericLoadStringObject(rdb,0);
364 }
365 
366 robj *rdbLoadEncodedStringObject(rio *rdb) {
367     return rdbGenericLoadStringObject(rdb,1);
368 }
369 
370 /* Save a double value. Doubles are saved as strings prefixed by an unsigned
371  * 8 bit integer specifying the length of the representation.
372  * This 8 bit integer has special values in order to specify the following
373  * conditions:
374  * 253: not a number
375  * 254: + inf
376  * 255: - inf
377  */
378 int rdbSaveDoubleValue(rio *rdb, double val) {
379     unsigned char buf[128];
380     int len;
381 
382     if (isnan(val)) {
383         buf[0] = 253;
384         len = 1;
385     } else if (!isfinite(val)) {
386         len = 1;
387         buf[0] = (val < 0) ? 255 : 254;
388     } else {
389 #if (DBL_MANT_DIG >= 52) && (LLONG_MAX == 0x7fffffffffffffffLL)
390         /* Check if the float is in a safe range to be casted into a
391          * long long. We are assuming that long long is 64 bit here.
392          * Also we are assuming that there are no implementations around where
393          * double has precision < 52 bit.
394          *
395          * Under this assumptions we test if a double is inside an interval
396          * where casting to long long is safe. Then using two castings we
397          * make sure the decimal part is zero. If all this is true we use
398          * integer printing function that is much faster. */
399         double min = -4503599627370495; /* (2^52)-1 */
400         double max = 4503599627370496; /* -(2^52) */
401         if (val > min && val < max && val == ((double)((long long)val)))
402             ll2string((char*)buf+1,sizeof(buf)-1,(long long)val);
403         else
404 #endif
405             snprintf((char*)buf+1,sizeof(buf)-1,"%.17g",val);
406         buf[0] = strlen((char*)buf+1);
407         len = buf[0]+1;
408     }
409     return rdbWriteRaw(rdb,buf,len);
410 }
411 
412 /* For information about double serialization check rdbSaveDoubleValue() */
413 int rdbLoadDoubleValue(rio *rdb, double *val) {
414     char buf[256];
415     unsigned char len;
416 
417     if (rioRead(rdb,&len,1) == 0) return -1;
418     switch(len) {
419     case 255: *val = R_NegInf; return 0;
420     case 254: *val = R_PosInf; return 0;
421     case 253: *val = R_Nan; return 0;
422     default:
423         if (rioRead(rdb,buf,len) == 0) return -1;
424         buf[len] = '\0';
425         sscanf(buf, "%lg", val);
426         return 0;
427     }
428 }
429 
430 /* Save the object type of object "o". */
431 int rdbSaveObjectType(rio *rdb, robj *o) {
432     switch (o->type) {
433     case REDIS_STRING:
434         return rdbSaveType(rdb,REDIS_RDB_TYPE_STRING);
435     case REDIS_LIST:
436         if (o->encoding == REDIS_ENCODING_ZIPLIST)
437             return rdbSaveType(rdb,REDIS_RDB_TYPE_LIST_ZIPLIST);
438         else if (o->encoding == REDIS_ENCODING_LINKEDLIST)
439             return rdbSaveType(rdb,REDIS_RDB_TYPE_LIST);
440         else
441             redisPanic("Unknown list encoding");
442     case REDIS_SET:
443         if (o->encoding == REDIS_ENCODING_INTSET)
444             return rdbSaveType(rdb,REDIS_RDB_TYPE_SET_INTSET);
445         else if (o->encoding == REDIS_ENCODING_HT)
446             return rdbSaveType(rdb,REDIS_RDB_TYPE_SET);
447         else
448             redisPanic("Unknown set encoding");
449     case REDIS_ZSET:
450         if (o->encoding == REDIS_ENCODING_ZIPLIST)
451             return rdbSaveType(rdb,REDIS_RDB_TYPE_ZSET_ZIPLIST);
452         else if (o->encoding == REDIS_ENCODING_SKIPLIST)
453             return rdbSaveType(rdb,REDIS_RDB_TYPE_ZSET);
454         else
455             redisPanic("Unknown sorted set encoding");
456     case REDIS_HASH:
457         if (o->encoding == REDIS_ENCODING_ZIPLIST)
458             return rdbSaveType(rdb,REDIS_RDB_TYPE_HASH_ZIPLIST);
459         else if (o->encoding == REDIS_ENCODING_HT)
460             return rdbSaveType(rdb,REDIS_RDB_TYPE_HASH);
461         else
462             redisPanic("Unknown hash encoding");
463     default:
464         redisPanic("Unknown object type");
465     }
466     return -1; /* avoid warning */
467 }
468 
469 /* Use rdbLoadType() to load a TYPE in RDB format, but returns -1 if the
470  * type is not specifically a valid Object Type. */
471 int rdbLoadObjectType(rio *rdb) {
472     int type;
473     if ((type = rdbLoadType(rdb)) == -1) return -1;
474     if (!rdbIsObjectType(type)) return -1;
475     return type;
476 }
477 
478 /* Save a Redis object. Returns -1 on error, number of bytes written on success. */
479 int rdbSaveObject(rio *rdb, robj *o) {
480     int n, nwritten = 0;
481 
482     if (o->type == REDIS_STRING) {
483         /* Save a string value */
484         if ((n = rdbSaveStringObject(rdb,o)) == -1) return -1;
485         nwritten += n;
486     } else if (o->type == REDIS_LIST) {
487         /* Save a list value */
488         if (o->encoding == REDIS_ENCODING_ZIPLIST) {
489             size_t l = ziplistBlobLen((unsigned char*)o->ptr);
490 
491             if ((n = rdbSaveRawString(rdb,o->ptr,l)) == -1) return -1;
492             nwritten += n;
493         } else if (o->encoding == REDIS_ENCODING_LINKEDLIST) {
494             list *list = o->ptr;
495             listIter li;
496             listNode *ln;
497 
498             if ((n = rdbSaveLen(rdb,listLength(list))) == -1) return -1;
499             nwritten += n;
500 
501             listRewind(list,&li);
502             while((ln = listNext(&li))) {
503                 robj *eleobj = listNodeValue(ln);
504                 if ((n = rdbSaveStringObject(rdb,eleobj)) == -1) return -1;
505                 nwritten += n;
506             }
507         } else {
508             redisPanic("Unknown list encoding");
509         }
510     } else if (o->type == REDIS_SET) {
511         /* Save a set value */
512         if (o->encoding == REDIS_ENCODING_HT) {
513             dict *set = o->ptr;
514             dictIterator *di = dictGetIterator(set);
515             dictEntry *de;
516 
517             if ((n = rdbSaveLen(rdb,dictSize(set))) == -1) return -1;
518             nwritten += n;
519 
520             while((de = dictNext(di)) != NULL) {
521                 robj *eleobj = dictGetKey(de);
522                 if ((n = rdbSaveStringObject(rdb,eleobj)) == -1) return -1;
523                 nwritten += n;
524             }
525             dictReleaseIterator(di);
526         } else if (o->encoding == REDIS_ENCODING_INTSET) {
527             size_t l = intsetBlobLen((intset*)o->ptr);
528 
529             if ((n = rdbSaveRawString(rdb,o->ptr,l)) == -1) return -1;
530             nwritten += n;
531         } else {
532             redisPanic("Unknown set encoding");
533         }
534     } else if (o->type == REDIS_ZSET) {
535         /* Save a sorted set value */
536         if (o->encoding == REDIS_ENCODING_ZIPLIST) {
537             size_t l = ziplistBlobLen((unsigned char*)o->ptr);
538 
539             if ((n = rdbSaveRawString(rdb,o->ptr,l)) == -1) return -1;
540             nwritten += n;
541         } else if (o->encoding == REDIS_ENCODING_SKIPLIST) {
542             zset *zs = o->ptr;
543             dictIterator *di = dictGetIterator(zs->dict);
544             dictEntry *de;
545 
546             if ((n = rdbSaveLen(rdb,dictSize(zs->dict))) == -1) return -1;
547             nwritten += n;
548 
549             while((de = dictNext(di)) != NULL) {
550                 robj *eleobj = dictGetKey(de);
551                 double *score = dictGetVal(de);
552 
553                 if ((n = rdbSaveStringObject(rdb,eleobj)) == -1) return -1;
554                 nwritten += n;
555                 if ((n = rdbSaveDoubleValue(rdb,*score)) == -1) return -1;
556                 nwritten += n;
557             }
558             dictReleaseIterator(di);
559         } else {
560             redisPanic("Unknown sorted set encoding");
561         }
562     } else if (o->type == REDIS_HASH) {
563         /* Save a hash value */
564         if (o->encoding == REDIS_ENCODING_ZIPLIST) {
565             size_t l = ziplistBlobLen((unsigned char*)o->ptr);
566 
567             if ((n = rdbSaveRawString(rdb,o->ptr,l)) == -1) return -1;
568             nwritten += n;
569 
570         } else if (o->encoding == REDIS_ENCODING_HT) {
571             dictIterator *di = dictGetIterator(o->ptr);
572             dictEntry *de;
573 
574             if ((n = rdbSaveLen(rdb,dictSize((dict*)o->ptr))) == -1) return -1;
575             nwritten += n;
576 
577             while((de = dictNext(di)) != NULL) {
578                 robj *key = dictGetKey(de);
579                 robj *val = dictGetVal(de);
580 
581                 if ((n = rdbSaveStringObject(rdb,key)) == -1) return -1;
582                 nwritten += n;
583                 if ((n = rdbSaveStringObject(rdb,val)) == -1) return -1;
584                 nwritten += n;
585             }
586             dictReleaseIterator(di);
587 
588         } else {
589             redisPanic("Unknown hash encoding");
590         }
591 
592     } else {
593         redisPanic("Unknown object type");
594     }
595     return nwritten;
596 }
597 
598 /* Return the length the object will have on disk if saved with
599  * the rdbSaveObject() function. Currently we use a trick to get
600  * this length with very little changes to the code. In the future
601  * we could switch to a faster solution. */
602 off_t rdbSavedObjectLen(robj *o) {
603     int len = rdbSaveObject(NULL,o);
604     redisAssertWithInfo(NULL,o,len != -1);
605     return len;
606 }
607 
608 /* Save a key-value pair, with expire time, type, key, value.
609  * On error -1 is returned.
610  * On success if the key was actually saved 1 is returned, otherwise 0
611  * is returned (the key was already expired). */
612 int rdbSaveKeyValuePair(rio *rdb, robj *key, robj *val,
613                         long long expiretime, long long now)
614 {
615     /* Save the expire time */
616     if (expiretime != -1) {
617         /* If this key is already expired skip it */
618         if (expiretime < now) return 0;
619         if (rdbSaveType(rdb,REDIS_RDB_OPCODE_EXPIRETIME_MS) == -1) return -1;
620         if (rdbSaveMillisecondTime(rdb,expiretime) == -1) return -1;
621     }
622 
623     /* Save type, key, value */
624     if (rdbSaveObjectType(rdb,val) == -1) return -1;
625     if (rdbSaveStringObject(rdb,key) == -1) return -1;
626     if (rdbSaveObject(rdb,val) == -1) return -1;
627     return 1;
628 }
629 
630 /* Save the DB on disk. Return REDIS_ERR on error, REDIS_OK on success */
631 int rdbSave(char *filename) {
632     dictIterator *di = NULL;
633     dictEntry *de;
634     char tmpfile[256];
635     char magic[10];
636     int j;
637     long long now = mstime();
638     FILE *fp;
639     rio rdb;
640     uint64_t cksum;
641 
642     snprintf(tmpfile,256,"temp-%d.rdb", (int) getpid());
643     fp = fopen(tmpfile,"w");
644     if (!fp) {
645         redisLog(REDIS_WARNING, "Failed opening .rdb for saving: %s",
646             strerror(errno));
647         return REDIS_ERR;
648     }
649 
650     rioInitWithFile(&rdb,fp);
651     if (server.rdb_checksum)
652         rdb.update_cksum = rioGenericUpdateChecksum;
653     snprintf(magic,sizeof(magic),"REDIS%04d",REDIS_RDB_VERSION);
654     if (rdbWriteRaw(&rdb,magic,9) == -1) goto werr;
655 
656     for (j = 0; j < server.dbnum; j++) {
657         redisDb *db = server.db+j;
658         dict *d = db->dict;
659         if (dictSize(d) == 0) continue;
660         di = dictGetSafeIterator(d);
661         if (!di) {
662             fclose(fp);
663             return REDIS_ERR;
664         }
665 
666         /* Write the SELECT DB opcode */
667         if (rdbSaveType(&rdb,REDIS_RDB_OPCODE_SELECTDB) == -1) goto werr;
668         if (rdbSaveLen(&rdb,j) == -1) goto werr;
669 
670         /* Iterate this DB writing every entry */
671         while((de = dictNext(di)) != NULL) {
672             sds keystr = dictGetKey(de);
673             robj key, *o = dictGetVal(de);
674             long long expire;
675 
676             initStaticStringObject(key,keystr);
677             expire = getExpire(db,&key);
678             if (rdbSaveKeyValuePair(&rdb,&key,o,expire,now) == -1) goto werr;
679         }
680         dictReleaseIterator(di);
681     }
682     di = NULL; /* So that we don't release it again on error. */
683 
684     /* EOF opcode */
685     if (rdbSaveType(&rdb,REDIS_RDB_OPCODE_EOF) == -1) goto werr;
686 
687     /* CRC64 checksum. It will be zero if checksum computation is disabled, the
688      * loading code skips the check in this case. */
689     cksum = rdb.cksum;
690     memrev64ifbe(&cksum);
691     if (rioWrite(&rdb,&cksum,8) == 0) goto werr;
692 
693     /* Make sure data will not remain on the OS's output buffers */
694     if (fflush(fp) == EOF) goto werr;
695     if (fsync(fileno(fp)) == -1) goto werr;
696     if (fclose(fp) == EOF) goto werr;
697 
698     /* Use RENAME to make sure the DB file is changed atomically only
699      * if the generate DB file is ok. */
700     if (rename(tmpfile,filename) == -1) {
701         redisLog(REDIS_WARNING,"Error moving temp DB file on the final destination: %s", strerror(errno));
702         unlink(tmpfile);
703         return REDIS_ERR;
704     }
705     redisLog(REDIS_NOTICE,"DB saved on disk");
706     server.dirty = 0;
707     server.lastsave = time(NULL);
708     server.lastbgsave_status = REDIS_OK;
709     return REDIS_OK;
710 
711 werr:
712     fclose(fp);
713     unlink(tmpfile);
714     redisLog(REDIS_WARNING,"Write error saving DB on disk: %s", strerror(errno));
715     if (di) dictReleaseIterator(di);
716     return REDIS_ERR;
717 }
718 
719 int rdbSaveBackground(char *filename) {
720     pid_t childpid;
721     long long start;
722 
723     if (server.rdb_child_pid != -1) return REDIS_ERR;
724 
725     server.dirty_before_bgsave = server.dirty;
726     server.lastbgsave_try = time(NULL);
727 
728     start = ustime();
729     if ((childpid = fork()) == 0) {
730         int retval;
731 
732         /* Child */
733         closeListeningSockets(0);
734         redisSetProcTitle("redis-rdb-bgsave");
735         retval = rdbSave(filename);
736         if (retval == REDIS_OK) {
737             size_t private_dirty = zmalloc_get_private_dirty();
738 
739             if (private_dirty) {
740                 redisLog(REDIS_NOTICE,
741                     "RDB: %zu MB of memory used by copy-on-write",
742                     private_dirty/(1024*1024));
743             }
744         }
745         exitFromChild((retval == REDIS_OK) ? 0 : 1);
746     } else {
747         /* Parent */
748         server.stat_fork_time = ustime()-start;
749         server.stat_fork_rate = (double) zmalloc_used_memory() * 1000000 / server.stat_fork_time / (1024*1024*1024); /* GB per second. */
750         latencyAddSampleIfNeeded("fork",server.stat_fork_time/1000);
751         if (childpid == -1) {
752             server.lastbgsave_status = REDIS_ERR;
753             redisLog(REDIS_WARNING,"Can't save in background: fork: %s",
754                 strerror(errno));
755             return REDIS_ERR;
756         }
757         redisLog(REDIS_NOTICE,"Background saving started by pid %d",childpid);
758         server.rdb_save_time_start = time(NULL);
759         server.rdb_child_pid = childpid;
760         updateDictResizePolicy();
761         return REDIS_OK;
762     }
763     return REDIS_OK; /* unreached */
764 }
765 
766 void rdbRemoveTempFile(pid_t childpid) {
767     char tmpfile[256];
768 
769     snprintf(tmpfile,sizeof(tmpfile),"temp-%d.rdb", (int) childpid);
770     unlink(tmpfile);
771 }
772 
773 /* Load a Redis object of the specified type from the specified file.
774  * On success a newly allocated object is returned, otherwise NULL. */
775 robj *rdbLoadObject(int rdbtype, rio *rdb) {
776     robj *o, *ele, *dec;
777     size_t len;
778     unsigned int i;
779 
780     if (rdbtype == REDIS_RDB_TYPE_STRING) {
781         /* Read string value */
782         if ((o = rdbLoadEncodedStringObject(rdb)) == NULL) return NULL;
783         o = tryObjectEncoding(o);
784     } else if (rdbtype == REDIS_RDB_TYPE_LIST) {
785         /* Read list value */
786         if ((len = rdbLoadLen(rdb,NULL)) == REDIS_RDB_LENERR) return NULL;
787 
788         /* Use a real list when there are too many entries */
789         if (len > server.list_max_ziplist_entries) {
790             o = createListObject();
791         } else {
792             o = createZiplistObject();
793         }
794 
795         /* Load every single element of the list */
796         while(len--) {
797             if ((ele = rdbLoadEncodedStringObject(rdb)) == NULL) return NULL;
798 
799             /* If we are using a ziplist and the value is too big, convert
800              * the object to a real list. */
801             if (o->encoding == REDIS_ENCODING_ZIPLIST &&
802                 sdsEncodedObject(ele) &&
803                 sdslen(ele->ptr) > server.list_max_ziplist_value)
804                     listTypeConvert(o,REDIS_ENCODING_LINKEDLIST);
805 
806             if (o->encoding == REDIS_ENCODING_ZIPLIST) {
807                 dec = getDecodedObject(ele);
808                 o->ptr = ziplistPush(o->ptr,dec->ptr,sdslen(dec->ptr),REDIS_TAIL);
809                 decrRefCount(dec);
810                 decrRefCount(ele);
811             } else {
812                 ele = tryObjectEncoding(ele);
813                 listAddNodeTail(o->ptr,ele);
814             }
815         }
816     } else if (rdbtype == REDIS_RDB_TYPE_SET) {
817         /* Read list/set value */
818         if ((len = rdbLoadLen(rdb,NULL)) == REDIS_RDB_LENERR) return NULL;
819 
820         /* Use a regular set when there are too many entries. */
821         if (len > server.set_max_intset_entries) {
822             o = createSetObject();
823             /* It's faster to expand the dict to the right size asap in order
824              * to avoid rehashing */
825             if (len > DICT_HT_INITIAL_SIZE)
826                 dictExpand(o->ptr,len);
827         } else {
828             o = createIntsetObject();
829         }
830 
831         /* Load every single element of the list/set */
832         for (i = 0; i < len; i++) {
833             long long llval;
834             if ((ele = rdbLoadEncodedStringObject(rdb)) == NULL) return NULL;
835             ele = tryObjectEncoding(ele);
836 
837             if (o->encoding == REDIS_ENCODING_INTSET) {
838                 /* Fetch integer value from element */
839                 if (isObjectRepresentableAsLongLong(ele,&llval) == REDIS_OK) {
840                     o->ptr = intsetAdd(o->ptr,llval,NULL);
841                 } else {
842                     setTypeConvert(o,REDIS_ENCODING_HT);
843                     dictExpand(o->ptr,len);
844                 }
845             }
846 
847             /* This will also be called when the set was just converted
848              * to a regular hash table encoded set */
849             if (o->encoding == REDIS_ENCODING_HT) {
850                 dictAdd((dict*)o->ptr,ele,NULL);
851             } else {
852                 decrRefCount(ele);
853             }
854         }
855     } else if (rdbtype == REDIS_RDB_TYPE_ZSET) {
856         /* Read list/set value */
857         size_t zsetlen;
858         size_t maxelelen = 0;
859         zset *zs;
860 
861         if ((zsetlen = rdbLoadLen(rdb,NULL)) == REDIS_RDB_LENERR) return NULL;
862         o = createZsetObject();
863         zs = o->ptr;
864 
865         /* Load every single element of the list/set */
866         while(zsetlen--) {
867             robj *ele;
868             double score;
869             zskiplistNode *znode;
870 
871             if ((ele = rdbLoadEncodedStringObject(rdb)) == NULL) return NULL;
872             ele = tryObjectEncoding(ele);
873             if (rdbLoadDoubleValue(rdb,&score) == -1) return NULL;
874 
875             /* Don't care about integer-encoded strings. */
876             if (sdsEncodedObject(ele) && sdslen(ele->ptr) > maxelelen)
877                 maxelelen = sdslen(ele->ptr);
878 
879             znode = zslInsert(zs->zsl,score,ele);
880             dictAdd(zs->dict,ele,&znode->score);
881             incrRefCount(ele); /* added to skiplist */
882         }
883 
884         /* Convert *after* loading, since sorted sets are not stored ordered. */
885         if (zsetLength(o) <= server.zset_max_ziplist_entries &&
886             maxelelen <= server.zset_max_ziplist_value)
887                 zsetConvert(o,REDIS_ENCODING_ZIPLIST);
888     } else if (rdbtype == REDIS_RDB_TYPE_HASH) {
889         size_t len;
890         int ret;
891 
892         len = rdbLoadLen(rdb, NULL);
893         if (len == REDIS_RDB_LENERR) return NULL;
894 
895         o = createHashObject();
896 
897         /* Too many entries? Use a hash table. */
898         if (len > server.hash_max_ziplist_entries)
899             hashTypeConvert(o, REDIS_ENCODING_HT);
900 
901         /* Load every field and value into the ziplist */
902         while (o->encoding == REDIS_ENCODING_ZIPLIST && len > 0) {
903             robj *field, *value;
904 
905             len--;
906             /* Load raw strings */
907             field = rdbLoadStringObject(rdb);
908             if (field == NULL) return NULL;
909             redisAssert(sdsEncodedObject(field));
910             value = rdbLoadStringObject(rdb);
911             if (value == NULL) return NULL;
912             redisAssert(sdsEncodedObject(value));
913 
914             /* Add pair to ziplist */
915             o->ptr = ziplistPush(o->ptr, field->ptr, sdslen(field->ptr), ZIPLIST_TAIL);
916             o->ptr = ziplistPush(o->ptr, value->ptr, sdslen(value->ptr), ZIPLIST_TAIL);
917             /* Convert to hash table if size threshold is exceeded */
918             if (sdslen(field->ptr) > server.hash_max_ziplist_value ||
919                 sdslen(value->ptr) > server.hash_max_ziplist_value)
920             {
921                 decrRefCount(field);
922                 decrRefCount(value);
923                 hashTypeConvert(o, REDIS_ENCODING_HT);
924                 break;
925             }
926             decrRefCount(field);
927             decrRefCount(value);
928         }
929 
930         /* Load remaining fields and values into the hash table */
931         while (o->encoding == REDIS_ENCODING_HT && len > 0) {
932             robj *field, *value;
933 
934             len--;
935             /* Load encoded strings */
936             field = rdbLoadEncodedStringObject(rdb);
937             if (field == NULL) return NULL;
938             value = rdbLoadEncodedStringObject(rdb);
939             if (value == NULL) return NULL;
940 
941             field = tryObjectEncoding(field);
942             value = tryObjectEncoding(value);
943 
944             /* Add pair to hash table */
945             ret = dictAdd((dict*)o->ptr, field, value);
946             redisAssert(ret == DICT_OK);
947         }
948 
949         /* All pairs should be read by now */
950         redisAssert(len == 0);
951 
952     } else if (rdbtype == REDIS_RDB_TYPE_HASH_ZIPMAP  ||
953                rdbtype == REDIS_RDB_TYPE_LIST_ZIPLIST ||
954                rdbtype == REDIS_RDB_TYPE_SET_INTSET   ||
955                rdbtype == REDIS_RDB_TYPE_ZSET_ZIPLIST ||
956                rdbtype == REDIS_RDB_TYPE_HASH_ZIPLIST)
957     {
958         robj *aux = rdbLoadStringObject(rdb);
959 
960         if (aux == NULL) return NULL;
961         o = createObject(REDIS_STRING,NULL); /* string is just placeholder */
962         o->ptr = zmalloc(sdslen(aux->ptr));
963         memcpy(o->ptr,aux->ptr,sdslen(aux->ptr));
964         decrRefCount(aux);
965 
966         /* Fix the object encoding, and make sure to convert the encoded
967          * data type into the base type if accordingly to the current
968          * configuration there are too many elements in the encoded data
969          * type. Note that we only check the length and not max element
970          * size as this is an O(N) scan. Eventually everything will get
971          * converted. */
972         switch(rdbtype) {
973             case REDIS_RDB_TYPE_HASH_ZIPMAP:
974                 /* Convert to ziplist encoded hash. This must be deprecated
975                  * when loading dumps created by Redis 2.4 gets deprecated. */
976                 {
977                     unsigned char *zl = ziplistNew();
978                     unsigned char *zi = zipmapRewind(o->ptr);
979                     unsigned char *fstr, *vstr;
980                     unsigned int flen, vlen;
981                     unsigned int maxlen = 0;
982 
983                     while ((zi = zipmapNext(zi, &fstr, &flen, &vstr, &vlen)) != NULL) {
984                         if (flen > maxlen) maxlen = flen;
985                         if (vlen > maxlen) maxlen = vlen;
986                         zl = ziplistPush(zl, fstr, flen, ZIPLIST_TAIL);
987                         zl = ziplistPush(zl, vstr, vlen, ZIPLIST_TAIL);
988                     }
989 
990                     zfree(o->ptr);
991                     o->ptr = zl;
992                     o->type = REDIS_HASH;
993                     o->encoding = REDIS_ENCODING_ZIPLIST;
994 
995                     if (hashTypeLength(o) > server.hash_max_ziplist_entries ||
996                         maxlen > server.hash_max_ziplist_value)
997                     {
998                         hashTypeConvert(o, REDIS_ENCODING_HT);
999                     }
1000                 }
1001                 break;
1002             case REDIS_RDB_TYPE_LIST_ZIPLIST:
1003                 o->type = REDIS_LIST;
1004                 o->encoding = REDIS_ENCODING_ZIPLIST;
1005                 if (ziplistLen(o->ptr) > server.list_max_ziplist_entries)
1006                     listTypeConvert(o,REDIS_ENCODING_LINKEDLIST);
1007                 break;
1008             case REDIS_RDB_TYPE_SET_INTSET:
1009                 o->type = REDIS_SET;
1010                 o->encoding = REDIS_ENCODING_INTSET;
1011                 if (intsetLen(o->ptr) > server.set_max_intset_entries)
1012                     setTypeConvert(o,REDIS_ENCODING_HT);
1013                 break;
1014             case REDIS_RDB_TYPE_ZSET_ZIPLIST:
1015                 o->type = REDIS_ZSET;
1016                 o->encoding = REDIS_ENCODING_ZIPLIST;
1017                 if (zsetLength(o) > server.zset_max_ziplist_entries)
1018                     zsetConvert(o,REDIS_ENCODING_SKIPLIST);
1019                 break;
1020             case REDIS_RDB_TYPE_HASH_ZIPLIST:
1021                 o->type = REDIS_HASH;
1022                 o->encoding = REDIS_ENCODING_ZIPLIST;
1023                 if (hashTypeLength(o) > server.hash_max_ziplist_entries)
1024                     hashTypeConvert(o, REDIS_ENCODING_HT);
1025                 break;
1026             default:
1027                 redisPanic("Unknown encoding");
1028                 break;
1029         }
1030     } else {
1031         redisPanic("Unknown object type");
1032     }
1033     return o;
1034 }
1035 
1036 /* Mark that we are loading in the global state and setup the fields
1037  * needed to provide loading stats. */
1038 void startLoading(FILE *fp) {
1039     struct stat sb;
1040 
1041     /* Load the DB */
1042     server.loading = 1;
1043     server.loading_start_time = time(NULL);
1044     if (fstat(fileno(fp), &sb) == -1) {
1045         server.loading_total_bytes = 1; /* just to avoid division by zero */
1046     } else {
1047         server.loading_total_bytes = sb.st_size;
1048     }
1049 }
1050 
1051 /* Refresh the loading progress info */
1052 void loadingProgress(off_t pos) {
1053     server.loading_loaded_bytes = pos;
1054     if (server.stat_peak_memory < zmalloc_used_memory())
1055         server.stat_peak_memory = zmalloc_used_memory();
1056 }
1057 
1058 /* Loading finished */
1059 void stopLoading(void) {
1060     server.loading = 0;
1061 }
1062 
1063 /* Track loading progress in order to serve client's from time to time
1064    and if needed calculate rdb checksum  */
1065 void rdbLoadProgressCallback(rio *r, const void *buf, size_t len) {
1066     if (server.rdb_checksum)
1067         rioGenericUpdateChecksum(r, buf, len);
1068     if (server.loading_process_events_interval_bytes &&
1069         (r->processed_bytes + len)/server.loading_process_events_interval_bytes > r->processed_bytes/server.loading_process_events_interval_bytes)
1070     {
1071         /* The DB can take some non trivial amount of time to load. Update
1072          * our cached time since it is used to create and update the last
1073          * interaction time with clients and for other important things. */
1074         updateCachedTime();
1075         if (server.masterhost && server.repl_state == REDIS_REPL_TRANSFER)
1076             replicationSendNewlineToMaster();
1077         loadingProgress(r->processed_bytes);
1078         processEventsWhileBlocked();
1079     }
1080 }
1081 
1082 int rdbLoad(char *filename) {
1083     uint32_t dbid;
1084     int type, rdbver;
1085     redisDb *db = server.db+0;
1086     char buf[1024];
1087     long long expiretime, now = mstime();
1088     FILE *fp;
1089     rio rdb;
1090 
1091     if ((fp = fopen(filename,"r")) == NULL) return REDIS_ERR;
1092 
1093     rioInitWithFile(&rdb,fp);
1094     rdb.update_cksum = rdbLoadProgressCallback;
1095     rdb.max_processing_chunk = server.loading_process_events_interval_bytes;
1096     if (rioRead(&rdb,buf,9) == 0) goto eoferr;
1097     buf[9] = '\0';
1098     if (memcmp(buf,"REDIS",5) != 0) {
1099         fclose(fp);
1100         redisLog(REDIS_WARNING,"Wrong signature trying to load DB from file");
1101         errno = EINVAL;
1102         return REDIS_ERR;
1103     }
1104     rdbver = atoi(buf+5);
1105     if (rdbver < 1 || rdbver > REDIS_RDB_VERSION) {
1106         fclose(fp);
1107         redisLog(REDIS_WARNING,"Can't handle RDB format version %d",rdbver);
1108         errno = EINVAL;
1109         return REDIS_ERR;
1110     }
1111 
1112     startLoading(fp);
1113     while(1) {
1114         robj *key, *val;
1115         expiretime = -1;
1116 
1117         /* Read type. */
1118         if ((type = rdbLoadType(&rdb)) == -1) goto eoferr;
1119         if (type == REDIS_RDB_OPCODE_EXPIRETIME) {
1120             if ((expiretime = rdbLoadTime(&rdb)) == -1) goto eoferr;
1121             /* We read the time so we need to read the object type again. */
1122             if ((type = rdbLoadType(&rdb)) == -1) goto eoferr;
1123             /* the EXPIRETIME opcode specifies time in seconds, so convert
1124              * into milliseconds. */
1125             expiretime *= 1000;
1126         } else if (type == REDIS_RDB_OPCODE_EXPIRETIME_MS) {
1127             /* Milliseconds precision expire times introduced with RDB
1128              * version 3. */
1129             if ((expiretime = rdbLoadMillisecondTime(&rdb)) == -1) goto eoferr;
1130             /* We read the time so we need to read the object type again. */
1131             if ((type = rdbLoadType(&rdb)) == -1) goto eoferr;
1132         }
1133 
1134         if (type == REDIS_RDB_OPCODE_EOF)
1135             break;
1136 
1137         /* Handle SELECT DB opcode as a special case */
1138         if (type == REDIS_RDB_OPCODE_SELECTDB) {
1139             if ((dbid = rdbLoadLen(&rdb,NULL)) == REDIS_RDB_LENERR)
1140                 goto eoferr;
1141             if (dbid >= (unsigned)server.dbnum) {
1142                 redisLog(REDIS_WARNING,"FATAL: Data file was created with a Redis server configured to handle more than %d databases. Exiting\n", server.dbnum);
1143                 exit(1);
1144             }
1145             db = server.db+dbid;
1146             continue;
1147         }
1148         /* Read key */
1149         if ((key = rdbLoadStringObject(&rdb)) == NULL) goto eoferr;
1150         /* Read value */
1151         if ((val = rdbLoadObject(type,&rdb)) == NULL) goto eoferr;
1152         /* Check if the key already expired. This function is used when loading
1153          * an RDB file from disk, either at startup, or when an RDB was
1154          * received from the master. In the latter case, the master is
1155          * responsible for key expiry. If we would expire keys here, the
1156          * snapshot taken by the master may not be reflected on the slave. */
1157         if (server.masterhost == NULL && expiretime != -1 && expiretime < now) {
1158             decrRefCount(key);
1159             decrRefCount(val);
1160             continue;
1161         }
1162         /* Add the new object in the hash table */
1163         dbAdd(db,key,val);
1164 
1165         /* Set the expire time if needed */
1166         if (expiretime != -1) setExpire(db,key,expiretime);
1167 
1168         decrRefCount(key);
1169     }
1170     /* Verify the checksum if RDB version is >= 5 */
1171     if (rdbver >= 5 && server.rdb_checksum) {
1172         uint64_t cksum, expected = rdb.cksum;
1173 
1174         if (rioRead(&rdb,&cksum,8) == 0) goto eoferr;
1175         memrev64ifbe(&cksum);
1176         if (cksum == 0) {
1177             redisLog(REDIS_WARNING,"RDB file was saved with checksum disabled: no check performed.");
1178         } else if (cksum != expected) {
1179             redisLog(REDIS_WARNING,"Wrong RDB checksum. Aborting now.");
1180             exit(1);
1181         }
1182     }
1183 
1184     fclose(fp);
1185     stopLoading();
1186     return REDIS_OK;
1187 
1188 eoferr: /* unexpected end of file is handled here with a fatal exit */
1189     redisLog(REDIS_WARNING,"Short read or OOM loading DB. Unrecoverable error, aborting now.");
1190     exit(1);
1191     return REDIS_ERR; /* Just to avoid warning */
1192 }
1193 
1194 /* A background saving child (BGSAVE) terminated its work. Handle this. */
1195 void backgroundSaveDoneHandler(int exitcode, int bysignal) {
1196     if (!bysignal && exitcode == 0) {
1197         redisLog(REDIS_NOTICE,
1198             "Background saving terminated with success");
1199         server.dirty = server.dirty - server.dirty_before_bgsave;
1200         server.lastsave = time(NULL);
1201         server.lastbgsave_status = REDIS_OK;
1202     } else if (!bysignal && exitcode != 0) {
1203         redisLog(REDIS_WARNING, "Background saving error");
1204         server.lastbgsave_status = REDIS_ERR;
1205     } else {
1206         mstime_t latency;
1207 
1208         redisLog(REDIS_WARNING,
1209             "Background saving terminated by signal %d", bysignal);
1210         latencyStartMonitor(latency);
1211         rdbRemoveTempFile(server.rdb_child_pid);
1212         latencyEndMonitor(latency);
1213         latencyAddSampleIfNeeded("rdb-unlink-temp-file",latency);
1214         /* SIGUSR1 is whitelisted, so we have a way to kill a child without
1215          * tirggering an error conditon. */
1216         if (bysignal != SIGUSR1)
1217             server.lastbgsave_status = REDIS_ERR;
1218     }
1219     server.rdb_child_pid = -1;
1220     server.rdb_save_time_last = time(NULL)-server.rdb_save_time_start;
1221     server.rdb_save_time_start = -1;
1222     /* Possibly there are slaves waiting for a BGSAVE in order to be served
1223      * (the first stage of SYNC is a bulk transfer of dump.rdb) */
1224     updateSlavesWaitingBgsave((!bysignal && exitcode == 0) ? REDIS_OK : REDIS_ERR);
1225 }
1226 
1227 void saveCommand(redisClient *c) {
1228     if (server.rdb_child_pid != -1) {
1229         addReplyError(c,"Background save already in progress");
1230         return;
1231     }
1232     if (rdbSave(server.rdb_filename) == REDIS_OK) {
1233         addReply(c,shared.ok);
1234     } else {
1235         addReply(c,shared.err);
1236     }
1237 }
1238 
1239 void bgsaveCommand(redisClient *c) {
1240     if (server.rdb_child_pid != -1) {
1241         addReplyError(c,"Background save already in progress");
1242     } else if (server.aof_child_pid != -1) {
1243         addReplyError(c,"Can't BGSAVE while AOF log rewriting is in progress");
1244     } else if (rdbSaveBackground(server.rdb_filename) == REDIS_OK) {
1245         addReplyStatus(c,"Background saving started");
1246     } else {
1247         addReply(c,shared.err);
1248     }
1249 }
1250