xref: /redis-3.2.3/src/rdb.c (revision 79d2f70f)
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     sds val;
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     val = sdsnewlen(NULL,len);
354     if (len && rioRead(rdb,val,len) == 0) {
355         sdsfree(val);
356         return NULL;
357     }
358     return createObject(REDIS_STRING,val);
359 }
360 
361 robj *rdbLoadStringObject(rio *rdb) {
362     return rdbGenericLoadStringObject(rdb,0);
363 }
364 
365 robj *rdbLoadEncodedStringObject(rio *rdb) {
366     return rdbGenericLoadStringObject(rdb,1);
367 }
368 
369 /* Save a double value. Doubles are saved as strings prefixed by an unsigned
370  * 8 bit integer specifying the length of the representation.
371  * This 8 bit integer has special values in order to specify the following
372  * conditions:
373  * 253: not a number
374  * 254: + inf
375  * 255: - inf
376  */
377 int rdbSaveDoubleValue(rio *rdb, double val) {
378     unsigned char buf[128];
379     int len;
380 
381     if (isnan(val)) {
382         buf[0] = 253;
383         len = 1;
384     } else if (!isfinite(val)) {
385         len = 1;
386         buf[0] = (val < 0) ? 255 : 254;
387     } else {
388 #if (DBL_MANT_DIG >= 52) && (LLONG_MAX == 0x7fffffffffffffffLL)
389         /* Check if the float is in a safe range to be casted into a
390          * long long. We are assuming that long long is 64 bit here.
391          * Also we are assuming that there are no implementations around where
392          * double has precision < 52 bit.
393          *
394          * Under this assumptions we test if a double is inside an interval
395          * where casting to long long is safe. Then using two castings we
396          * make sure the decimal part is zero. If all this is true we use
397          * integer printing function that is much faster. */
398         double min = -4503599627370495; /* (2^52)-1 */
399         double max = 4503599627370496; /* -(2^52) */
400         if (val > min && val < max && val == ((double)((long long)val)))
401             ll2string((char*)buf+1,sizeof(buf)-1,(long long)val);
402         else
403 #endif
404             snprintf((char*)buf+1,sizeof(buf)-1,"%.17g",val);
405         buf[0] = strlen((char*)buf+1);
406         len = buf[0]+1;
407     }
408     return rdbWriteRaw(rdb,buf,len);
409 }
410 
411 /* For information about double serialization check rdbSaveDoubleValue() */
412 int rdbLoadDoubleValue(rio *rdb, double *val) {
413     char buf[256];
414     unsigned char len;
415 
416     if (rioRead(rdb,&len,1) == 0) return -1;
417     switch(len) {
418     case 255: *val = R_NegInf; return 0;
419     case 254: *val = R_PosInf; return 0;
420     case 253: *val = R_Nan; return 0;
421     default:
422         if (rioRead(rdb,buf,len) == 0) return -1;
423         buf[len] = '\0';
424         sscanf(buf, "%lg", val);
425         return 0;
426     }
427 }
428 
429 /* Save the object type of object "o". */
430 int rdbSaveObjectType(rio *rdb, robj *o) {
431     switch (o->type) {
432     case REDIS_STRING:
433         return rdbSaveType(rdb,REDIS_RDB_TYPE_STRING);
434     case REDIS_LIST:
435         if (o->encoding == REDIS_ENCODING_ZIPLIST)
436             return rdbSaveType(rdb,REDIS_RDB_TYPE_LIST_ZIPLIST);
437         else if (o->encoding == REDIS_ENCODING_LINKEDLIST)
438             return rdbSaveType(rdb,REDIS_RDB_TYPE_LIST);
439         else
440             redisPanic("Unknown list encoding");
441     case REDIS_SET:
442         if (o->encoding == REDIS_ENCODING_INTSET)
443             return rdbSaveType(rdb,REDIS_RDB_TYPE_SET_INTSET);
444         else if (o->encoding == REDIS_ENCODING_HT)
445             return rdbSaveType(rdb,REDIS_RDB_TYPE_SET);
446         else
447             redisPanic("Unknown set encoding");
448     case REDIS_ZSET:
449         if (o->encoding == REDIS_ENCODING_ZIPLIST)
450             return rdbSaveType(rdb,REDIS_RDB_TYPE_ZSET_ZIPLIST);
451         else if (o->encoding == REDIS_ENCODING_SKIPLIST)
452             return rdbSaveType(rdb,REDIS_RDB_TYPE_ZSET);
453         else
454             redisPanic("Unknown sorted set encoding");
455     case REDIS_HASH:
456         if (o->encoding == REDIS_ENCODING_ZIPLIST)
457             return rdbSaveType(rdb,REDIS_RDB_TYPE_HASH_ZIPLIST);
458         else if (o->encoding == REDIS_ENCODING_HT)
459             return rdbSaveType(rdb,REDIS_RDB_TYPE_HASH);
460         else
461             redisPanic("Unknown hash encoding");
462     default:
463         redisPanic("Unknown object type");
464     }
465     return -1; /* avoid warning */
466 }
467 
468 /* Use rdbLoadType() to load a TYPE in RDB format, but returns -1 if the
469  * type is not specifically a valid Object Type. */
470 int rdbLoadObjectType(rio *rdb) {
471     int type;
472     if ((type = rdbLoadType(rdb)) == -1) return -1;
473     if (!rdbIsObjectType(type)) return -1;
474     return type;
475 }
476 
477 /* Save a Redis object. Returns -1 on error, 0 on success. */
478 int rdbSaveObject(rio *rdb, robj *o) {
479     int n, nwritten = 0;
480 
481     if (o->type == REDIS_STRING) {
482         /* Save a string value */
483         if ((n = rdbSaveStringObject(rdb,o)) == -1) return -1;
484         nwritten += n;
485     } else if (o->type == REDIS_LIST) {
486         /* Save a list value */
487         if (o->encoding == REDIS_ENCODING_ZIPLIST) {
488             size_t l = ziplistBlobLen((unsigned char*)o->ptr);
489 
490             if ((n = rdbSaveRawString(rdb,o->ptr,l)) == -1) return -1;
491             nwritten += n;
492         } else if (o->encoding == REDIS_ENCODING_LINKEDLIST) {
493             list *list = o->ptr;
494             listIter li;
495             listNode *ln;
496 
497             if ((n = rdbSaveLen(rdb,listLength(list))) == -1) return -1;
498             nwritten += n;
499 
500             listRewind(list,&li);
501             while((ln = listNext(&li))) {
502                 robj *eleobj = listNodeValue(ln);
503                 if ((n = rdbSaveStringObject(rdb,eleobj)) == -1) return -1;
504                 nwritten += n;
505             }
506         } else {
507             redisPanic("Unknown list encoding");
508         }
509     } else if (o->type == REDIS_SET) {
510         /* Save a set value */
511         if (o->encoding == REDIS_ENCODING_HT) {
512             dict *set = o->ptr;
513             dictIterator *di = dictGetIterator(set);
514             dictEntry *de;
515 
516             if ((n = rdbSaveLen(rdb,dictSize(set))) == -1) return -1;
517             nwritten += n;
518 
519             while((de = dictNext(di)) != NULL) {
520                 robj *eleobj = dictGetKey(de);
521                 if ((n = rdbSaveStringObject(rdb,eleobj)) == -1) return -1;
522                 nwritten += n;
523             }
524             dictReleaseIterator(di);
525         } else if (o->encoding == REDIS_ENCODING_INTSET) {
526             size_t l = intsetBlobLen((intset*)o->ptr);
527 
528             if ((n = rdbSaveRawString(rdb,o->ptr,l)) == -1) return -1;
529             nwritten += n;
530         } else {
531             redisPanic("Unknown set encoding");
532         }
533     } else if (o->type == REDIS_ZSET) {
534         /* Save a sorted set value */
535         if (o->encoding == REDIS_ENCODING_ZIPLIST) {
536             size_t l = ziplistBlobLen((unsigned char*)o->ptr);
537 
538             if ((n = rdbSaveRawString(rdb,o->ptr,l)) == -1) return -1;
539             nwritten += n;
540         } else if (o->encoding == REDIS_ENCODING_SKIPLIST) {
541             zset *zs = o->ptr;
542             dictIterator *di = dictGetIterator(zs->dict);
543             dictEntry *de;
544 
545             if ((n = rdbSaveLen(rdb,dictSize(zs->dict))) == -1) return -1;
546             nwritten += n;
547 
548             while((de = dictNext(di)) != NULL) {
549                 robj *eleobj = dictGetKey(de);
550                 double *score = dictGetVal(de);
551 
552                 if ((n = rdbSaveStringObject(rdb,eleobj)) == -1) return -1;
553                 nwritten += n;
554                 if ((n = rdbSaveDoubleValue(rdb,*score)) == -1) return -1;
555                 nwritten += n;
556             }
557             dictReleaseIterator(di);
558         } else {
559             redisPanic("Unknown sorted set encoding");
560         }
561     } else if (o->type == REDIS_HASH) {
562         /* Save a hash value */
563         if (o->encoding == REDIS_ENCODING_ZIPLIST) {
564             size_t l = ziplistBlobLen((unsigned char*)o->ptr);
565 
566             if ((n = rdbSaveRawString(rdb,o->ptr,l)) == -1) return -1;
567             nwritten += n;
568 
569         } else if (o->encoding == REDIS_ENCODING_HT) {
570             dictIterator *di = dictGetIterator(o->ptr);
571             dictEntry *de;
572 
573             if ((n = rdbSaveLen(rdb,dictSize((dict*)o->ptr))) == -1) return -1;
574             nwritten += n;
575 
576             while((de = dictNext(di)) != NULL) {
577                 robj *key = dictGetKey(de);
578                 robj *val = dictGetVal(de);
579 
580                 if ((n = rdbSaveStringObject(rdb,key)) == -1) return -1;
581                 nwritten += n;
582                 if ((n = rdbSaveStringObject(rdb,val)) == -1) return -1;
583                 nwritten += n;
584             }
585             dictReleaseIterator(di);
586 
587         } else {
588             redisPanic("Unknown hash encoding");
589         }
590 
591     } else {
592         redisPanic("Unknown object type");
593     }
594     return nwritten;
595 }
596 
597 /* Return the length the object will have on disk if saved with
598  * the rdbSaveObject() function. Currently we use a trick to get
599  * this length with very little changes to the code. In the future
600  * we could switch to a faster solution. */
601 off_t rdbSavedObjectLen(robj *o) {
602     int len = rdbSaveObject(NULL,o);
603     redisAssertWithInfo(NULL,o,len != -1);
604     return len;
605 }
606 
607 /* Save a key-value pair, with expire time, type, key, value.
608  * On error -1 is returned.
609  * On success if the key was actually saved 1 is returned, otherwise 0
610  * is returned (the key was already expired). */
611 int rdbSaveKeyValuePair(rio *rdb, robj *key, robj *val,
612                         long long expiretime, long long now)
613 {
614     /* Save the expire time */
615     if (expiretime != -1) {
616         /* If this key is already expired skip it */
617         if (expiretime < now) return 0;
618         if (rdbSaveType(rdb,REDIS_RDB_OPCODE_EXPIRETIME_MS) == -1) return -1;
619         if (rdbSaveMillisecondTime(rdb,expiretime) == -1) return -1;
620     }
621 
622     /* Save type, key, value */
623     if (rdbSaveObjectType(rdb,val) == -1) return -1;
624     if (rdbSaveStringObject(rdb,key) == -1) return -1;
625     if (rdbSaveObject(rdb,val) == -1) return -1;
626     return 1;
627 }
628 
629 /* Save the DB on disk. Return REDIS_ERR on error, REDIS_OK on success */
630 int rdbSave(char *filename) {
631     dictIterator *di = NULL;
632     dictEntry *de;
633     char tmpfile[256];
634     char magic[10];
635     int j;
636     long long now = mstime();
637     FILE *fp;
638     rio rdb;
639     uint64_t cksum;
640 
641     snprintf(tmpfile,256,"temp-%d.rdb", (int) getpid());
642     fp = fopen(tmpfile,"w");
643     if (!fp) {
644         redisLog(REDIS_WARNING, "Failed opening .rdb for saving: %s",
645             strerror(errno));
646         return REDIS_ERR;
647     }
648 
649     rioInitWithFile(&rdb,fp);
650     if (server.rdb_checksum)
651         rdb.update_cksum = rioGenericUpdateChecksum;
652     snprintf(magic,sizeof(magic),"REDIS%04d",REDIS_RDB_VERSION);
653     if (rdbWriteRaw(&rdb,magic,9) == -1) goto werr;
654 
655     for (j = 0; j < server.dbnum; j++) {
656         redisDb *db = server.db+j;
657         dict *d = db->dict;
658         if (dictSize(d) == 0) continue;
659         di = dictGetSafeIterator(d);
660         if (!di) {
661             fclose(fp);
662             return REDIS_ERR;
663         }
664 
665         /* Write the SELECT DB opcode */
666         if (rdbSaveType(&rdb,REDIS_RDB_OPCODE_SELECTDB) == -1) goto werr;
667         if (rdbSaveLen(&rdb,j) == -1) goto werr;
668 
669         /* Iterate this DB writing every entry */
670         while((de = dictNext(di)) != NULL) {
671             sds keystr = dictGetKey(de);
672             robj key, *o = dictGetVal(de);
673             long long expire;
674 
675             initStaticStringObject(key,keystr);
676             expire = getExpire(db,&key);
677             if (rdbSaveKeyValuePair(&rdb,&key,o,expire,now) == -1) goto werr;
678         }
679         dictReleaseIterator(di);
680     }
681     di = NULL; /* So that we don't release it again on error. */
682 
683     /* EOF opcode */
684     if (rdbSaveType(&rdb,REDIS_RDB_OPCODE_EOF) == -1) goto werr;
685 
686     /* CRC64 checksum. It will be zero if checksum computation is disabled, the
687      * loading code skips the check in this case. */
688     cksum = rdb.cksum;
689     memrev64ifbe(&cksum);
690     rioWrite(&rdb,&cksum,8);
691 
692     /* Make sure data will not remain on the OS's output buffers */
693     if (fflush(fp) == EOF) goto werr;
694     if (fsync(fileno(fp)) == -1) goto werr;
695     if (fclose(fp) == EOF) goto werr;
696 
697     /* Use RENAME to make sure the DB file is changed atomically only
698      * if the generate DB file is ok. */
699     if (rename(tmpfile,filename) == -1) {
700         redisLog(REDIS_WARNING,"Error moving temp DB file on the final destination: %s", strerror(errno));
701         unlink(tmpfile);
702         return REDIS_ERR;
703     }
704     redisLog(REDIS_NOTICE,"DB saved on disk");
705     server.dirty = 0;
706     server.lastsave = time(NULL);
707     server.lastbgsave_status = REDIS_OK;
708     return REDIS_OK;
709 
710 werr:
711     fclose(fp);
712     unlink(tmpfile);
713     redisLog(REDIS_WARNING,"Write error saving DB on disk: %s", strerror(errno));
714     if (di) dictReleaseIterator(di);
715     return REDIS_ERR;
716 }
717 
718 int rdbSaveBackground(char *filename) {
719     pid_t childpid;
720     long long start;
721 
722     if (server.rdb_child_pid != -1) return REDIS_ERR;
723 
724     server.dirty_before_bgsave = server.dirty;
725     server.lastbgsave_try = time(NULL);
726 
727     start = ustime();
728     if ((childpid = fork()) == 0) {
729         int retval;
730 
731         /* Child */
732         closeListeningSockets(0);
733         redisSetProcTitle("redis-rdb-bgsave");
734         retval = rdbSave(filename);
735         if (retval == REDIS_OK) {
736             size_t private_dirty = zmalloc_get_private_dirty();
737 
738             if (private_dirty) {
739                 redisLog(REDIS_NOTICE,
740                     "RDB: %zu MB of memory used by copy-on-write",
741                     private_dirty/(1024*1024));
742             }
743         }
744         exitFromChild((retval == REDIS_OK) ? 0 : 1);
745     } else {
746         /* Parent */
747         server.stat_fork_time = ustime()-start;
748         server.stat_fork_rate = (double) zmalloc_used_memory() * 1000000 / server.stat_fork_time / (1024*1024*1024); /* GB per second. */
749         latencyAddSampleIfNeeded("fork",server.stat_fork_time/1000);
750         if (childpid == -1) {
751             server.lastbgsave_status = REDIS_ERR;
752             redisLog(REDIS_WARNING,"Can't save in background: fork: %s",
753                 strerror(errno));
754             return REDIS_ERR;
755         }
756         redisLog(REDIS_NOTICE,"Background saving started by pid %d",childpid);
757         server.rdb_save_time_start = time(NULL);
758         server.rdb_child_pid = childpid;
759         updateDictResizePolicy();
760         return REDIS_OK;
761     }
762     return REDIS_OK; /* unreached */
763 }
764 
765 void rdbRemoveTempFile(pid_t childpid) {
766     char tmpfile[256];
767 
768     snprintf(tmpfile,256,"temp-%d.rdb", (int) childpid);
769     unlink(tmpfile);
770 }
771 
772 /* Load a Redis object of the specified type from the specified file.
773  * On success a newly allocated object is returned, otherwise NULL. */
774 robj *rdbLoadObject(int rdbtype, rio *rdb) {
775     robj *o, *ele, *dec;
776     size_t len;
777     unsigned int i;
778 
779     if (rdbtype == REDIS_RDB_TYPE_STRING) {
780         /* Read string value */
781         if ((o = rdbLoadEncodedStringObject(rdb)) == NULL) return NULL;
782         o = tryObjectEncoding(o);
783     } else if (rdbtype == REDIS_RDB_TYPE_LIST) {
784         /* Read list value */
785         if ((len = rdbLoadLen(rdb,NULL)) == REDIS_RDB_LENERR) return NULL;
786 
787         /* Use a real list when there are too many entries */
788         if (len > server.list_max_ziplist_entries) {
789             o = createListObject();
790         } else {
791             o = createZiplistObject();
792         }
793 
794         /* Load every single element of the list */
795         while(len--) {
796             if ((ele = rdbLoadEncodedStringObject(rdb)) == NULL) return NULL;
797 
798             /* If we are using a ziplist and the value is too big, convert
799              * the object to a real list. */
800             if (o->encoding == REDIS_ENCODING_ZIPLIST &&
801                 sdsEncodedObject(ele) &&
802                 sdslen(ele->ptr) > server.list_max_ziplist_value)
803                     listTypeConvert(o,REDIS_ENCODING_LINKEDLIST);
804 
805             if (o->encoding == REDIS_ENCODING_ZIPLIST) {
806                 dec = getDecodedObject(ele);
807                 o->ptr = ziplistPush(o->ptr,dec->ptr,sdslen(dec->ptr),REDIS_TAIL);
808                 decrRefCount(dec);
809                 decrRefCount(ele);
810             } else {
811                 ele = tryObjectEncoding(ele);
812                 listAddNodeTail(o->ptr,ele);
813             }
814         }
815     } else if (rdbtype == REDIS_RDB_TYPE_SET) {
816         /* Read list/set value */
817         if ((len = rdbLoadLen(rdb,NULL)) == REDIS_RDB_LENERR) return NULL;
818 
819         /* Use a regular set when there are too many entries. */
820         if (len > server.set_max_intset_entries) {
821             o = createSetObject();
822             /* It's faster to expand the dict to the right size asap in order
823              * to avoid rehashing */
824             if (len > DICT_HT_INITIAL_SIZE)
825                 dictExpand(o->ptr,len);
826         } else {
827             o = createIntsetObject();
828         }
829 
830         /* Load every single element of the list/set */
831         for (i = 0; i < len; i++) {
832             long long llval;
833             if ((ele = rdbLoadEncodedStringObject(rdb)) == NULL) return NULL;
834             ele = tryObjectEncoding(ele);
835 
836             if (o->encoding == REDIS_ENCODING_INTSET) {
837                 /* Fetch integer value from element */
838                 if (isObjectRepresentableAsLongLong(ele,&llval) == REDIS_OK) {
839                     o->ptr = intsetAdd(o->ptr,llval,NULL);
840                 } else {
841                     setTypeConvert(o,REDIS_ENCODING_HT);
842                     dictExpand(o->ptr,len);
843                 }
844             }
845 
846             /* This will also be called when the set was just converted
847              * to a regular hash table encoded set */
848             if (o->encoding == REDIS_ENCODING_HT) {
849                 dictAdd((dict*)o->ptr,ele,NULL);
850             } else {
851                 decrRefCount(ele);
852             }
853         }
854     } else if (rdbtype == REDIS_RDB_TYPE_ZSET) {
855         /* Read list/set value */
856         size_t zsetlen;
857         size_t maxelelen = 0;
858         zset *zs;
859 
860         if ((zsetlen = rdbLoadLen(rdb,NULL)) == REDIS_RDB_LENERR) return NULL;
861         o = createZsetObject();
862         zs = o->ptr;
863 
864         /* Load every single element of the list/set */
865         while(zsetlen--) {
866             robj *ele;
867             double score;
868             zskiplistNode *znode;
869 
870             if ((ele = rdbLoadEncodedStringObject(rdb)) == NULL) return NULL;
871             ele = tryObjectEncoding(ele);
872             if (rdbLoadDoubleValue(rdb,&score) == -1) return NULL;
873 
874             /* Don't care about integer-encoded strings. */
875             if (sdsEncodedObject(ele) && sdslen(ele->ptr) > maxelelen)
876                 maxelelen = sdslen(ele->ptr);
877 
878             znode = zslInsert(zs->zsl,score,ele);
879             dictAdd(zs->dict,ele,&znode->score);
880             incrRefCount(ele); /* added to skiplist */
881         }
882 
883         /* Convert *after* loading, since sorted sets are not stored ordered. */
884         if (zsetLength(o) <= server.zset_max_ziplist_entries &&
885             maxelelen <= server.zset_max_ziplist_value)
886                 zsetConvert(o,REDIS_ENCODING_ZIPLIST);
887     } else if (rdbtype == REDIS_RDB_TYPE_HASH) {
888         size_t len;
889         int ret;
890 
891         len = rdbLoadLen(rdb, NULL);
892         if (len == REDIS_RDB_LENERR) return NULL;
893 
894         o = createHashObject();
895 
896         /* Too many entries? Use a hash table. */
897         if (len > server.hash_max_ziplist_entries)
898             hashTypeConvert(o, REDIS_ENCODING_HT);
899 
900         /* Load every field and value into the ziplist */
901         while (o->encoding == REDIS_ENCODING_ZIPLIST && len > 0) {
902             robj *field, *value;
903 
904             len--;
905             /* Load raw strings */
906             field = rdbLoadStringObject(rdb);
907             if (field == NULL) return NULL;
908             redisAssert(sdsEncodedObject(field));
909             value = rdbLoadStringObject(rdb);
910             if (value == NULL) return NULL;
911             redisAssert(sdsEncodedObject(value));
912 
913             /* Add pair to ziplist */
914             o->ptr = ziplistPush(o->ptr, field->ptr, sdslen(field->ptr), ZIPLIST_TAIL);
915             o->ptr = ziplistPush(o->ptr, value->ptr, sdslen(value->ptr), ZIPLIST_TAIL);
916             /* Convert to hash table if size threshold is exceeded */
917             if (sdslen(field->ptr) > server.hash_max_ziplist_value ||
918                 sdslen(value->ptr) > server.hash_max_ziplist_value)
919             {
920                 decrRefCount(field);
921                 decrRefCount(value);
922                 hashTypeConvert(o, REDIS_ENCODING_HT);
923                 break;
924             }
925             decrRefCount(field);
926             decrRefCount(value);
927         }
928 
929         /* Load remaining fields and values into the hash table */
930         while (o->encoding == REDIS_ENCODING_HT && len > 0) {
931             robj *field, *value;
932 
933             len--;
934             /* Load encoded strings */
935             field = rdbLoadEncodedStringObject(rdb);
936             if (field == NULL) return NULL;
937             value = rdbLoadEncodedStringObject(rdb);
938             if (value == NULL) return NULL;
939 
940             field = tryObjectEncoding(field);
941             value = tryObjectEncoding(value);
942 
943             /* Add pair to hash table */
944             ret = dictAdd((dict*)o->ptr, field, value);
945             redisAssert(ret == REDIS_OK);
946         }
947 
948         /* All pairs should be read by now */
949         redisAssert(len == 0);
950 
951     } else if (rdbtype == REDIS_RDB_TYPE_HASH_ZIPMAP  ||
952                rdbtype == REDIS_RDB_TYPE_LIST_ZIPLIST ||
953                rdbtype == REDIS_RDB_TYPE_SET_INTSET   ||
954                rdbtype == REDIS_RDB_TYPE_ZSET_ZIPLIST ||
955                rdbtype == REDIS_RDB_TYPE_HASH_ZIPLIST)
956     {
957         robj *aux = rdbLoadStringObject(rdb);
958 
959         if (aux == NULL) return NULL;
960         o = createObject(REDIS_STRING,NULL); /* string is just placeholder */
961         o->ptr = zmalloc(sdslen(aux->ptr));
962         memcpy(o->ptr,aux->ptr,sdslen(aux->ptr));
963         decrRefCount(aux);
964 
965         /* Fix the object encoding, and make sure to convert the encoded
966          * data type into the base type if accordingly to the current
967          * configuration there are too many elements in the encoded data
968          * type. Note that we only check the length and not max element
969          * size as this is an O(N) scan. Eventually everything will get
970          * converted. */
971         switch(rdbtype) {
972             case REDIS_RDB_TYPE_HASH_ZIPMAP:
973                 /* Convert to ziplist encoded hash. This must be deprecated
974                  * when loading dumps created by Redis 2.4 gets deprecated. */
975                 {
976                     unsigned char *zl = ziplistNew();
977                     unsigned char *zi = zipmapRewind(o->ptr);
978                     unsigned char *fstr, *vstr;
979                     unsigned int flen, vlen;
980                     unsigned int maxlen = 0;
981 
982                     while ((zi = zipmapNext(zi, &fstr, &flen, &vstr, &vlen)) != NULL) {
983                         if (flen > maxlen) maxlen = flen;
984                         if (vlen > maxlen) maxlen = vlen;
985                         zl = ziplistPush(zl, fstr, flen, ZIPLIST_TAIL);
986                         zl = ziplistPush(zl, vstr, vlen, ZIPLIST_TAIL);
987                     }
988 
989                     zfree(o->ptr);
990                     o->ptr = zl;
991                     o->type = REDIS_HASH;
992                     o->encoding = REDIS_ENCODING_ZIPLIST;
993 
994                     if (hashTypeLength(o) > server.hash_max_ziplist_entries ||
995                         maxlen > server.hash_max_ziplist_value)
996                     {
997                         hashTypeConvert(o, REDIS_ENCODING_HT);
998                     }
999                 }
1000                 break;
1001             case REDIS_RDB_TYPE_LIST_ZIPLIST:
1002                 o->type = REDIS_LIST;
1003                 o->encoding = REDIS_ENCODING_ZIPLIST;
1004                 if (ziplistLen(o->ptr) > server.list_max_ziplist_entries)
1005                     listTypeConvert(o,REDIS_ENCODING_LINKEDLIST);
1006                 break;
1007             case REDIS_RDB_TYPE_SET_INTSET:
1008                 o->type = REDIS_SET;
1009                 o->encoding = REDIS_ENCODING_INTSET;
1010                 if (intsetLen(o->ptr) > server.set_max_intset_entries)
1011                     setTypeConvert(o,REDIS_ENCODING_HT);
1012                 break;
1013             case REDIS_RDB_TYPE_ZSET_ZIPLIST:
1014                 o->type = REDIS_ZSET;
1015                 o->encoding = REDIS_ENCODING_ZIPLIST;
1016                 if (zsetLength(o) > server.zset_max_ziplist_entries)
1017                     zsetConvert(o,REDIS_ENCODING_SKIPLIST);
1018                 break;
1019             case REDIS_RDB_TYPE_HASH_ZIPLIST:
1020                 o->type = REDIS_HASH;
1021                 o->encoding = REDIS_ENCODING_ZIPLIST;
1022                 if (hashTypeLength(o) > server.hash_max_ziplist_entries)
1023                     hashTypeConvert(o, REDIS_ENCODING_HT);
1024                 break;
1025             default:
1026                 redisPanic("Unknown encoding");
1027                 break;
1028         }
1029     } else {
1030         redisPanic("Unknown object type");
1031     }
1032     return o;
1033 }
1034 
1035 /* Mark that we are loading in the global state and setup the fields
1036  * needed to provide loading stats. */
1037 void startLoading(FILE *fp) {
1038     struct stat sb;
1039 
1040     /* Load the DB */
1041     server.loading = 1;
1042     server.loading_start_time = time(NULL);
1043     if (fstat(fileno(fp), &sb) == -1) {
1044         server.loading_total_bytes = 1; /* just to avoid division by zero */
1045     } else {
1046         server.loading_total_bytes = sb.st_size;
1047     }
1048 }
1049 
1050 /* Refresh the loading progress info */
1051 void loadingProgress(off_t pos) {
1052     server.loading_loaded_bytes = pos;
1053     if (server.stat_peak_memory < zmalloc_used_memory())
1054         server.stat_peak_memory = zmalloc_used_memory();
1055 }
1056 
1057 /* Loading finished */
1058 void stopLoading(void) {
1059     server.loading = 0;
1060 }
1061 
1062 /* Track loading progress in order to serve client's from time to time
1063    and if needed calculate rdb checksum  */
1064 void rdbLoadProgressCallback(rio *r, const void *buf, size_t len) {
1065     if (server.rdb_checksum)
1066         rioGenericUpdateChecksum(r, buf, len);
1067     if (server.loading_process_events_interval_bytes &&
1068         (r->processed_bytes + len)/server.loading_process_events_interval_bytes > r->processed_bytes/server.loading_process_events_interval_bytes)
1069     {
1070         /* The DB can take some non trivial amount of time to load. Update
1071          * our cached time since it is used to create and update the last
1072          * interaction time with clients and for other important things. */
1073         updateCachedTime();
1074         if (server.masterhost && server.repl_state == REDIS_REPL_TRANSFER)
1075             replicationSendNewlineToMaster();
1076         loadingProgress(r->processed_bytes);
1077         processEventsWhileBlocked();
1078     }
1079 }
1080 
1081 int rdbLoad(char *filename) {
1082     uint32_t dbid;
1083     int type, rdbver;
1084     redisDb *db = server.db+0;
1085     char buf[1024];
1086     long long expiretime, now = mstime();
1087     FILE *fp;
1088     rio rdb;
1089 
1090     if ((fp = fopen(filename,"r")) == NULL) return REDIS_ERR;
1091 
1092     rioInitWithFile(&rdb,fp);
1093     rdb.update_cksum = rdbLoadProgressCallback;
1094     rdb.max_processing_chunk = server.loading_process_events_interval_bytes;
1095     if (rioRead(&rdb,buf,9) == 0) goto eoferr;
1096     buf[9] = '\0';
1097     if (memcmp(buf,"REDIS",5) != 0) {
1098         fclose(fp);
1099         redisLog(REDIS_WARNING,"Wrong signature trying to load DB from file");
1100         errno = EINVAL;
1101         return REDIS_ERR;
1102     }
1103     rdbver = atoi(buf+5);
1104     if (rdbver < 1 || rdbver > REDIS_RDB_VERSION) {
1105         fclose(fp);
1106         redisLog(REDIS_WARNING,"Can't handle RDB format version %d",rdbver);
1107         errno = EINVAL;
1108         return REDIS_ERR;
1109     }
1110 
1111     startLoading(fp);
1112     while(1) {
1113         robj *key, *val;
1114         expiretime = -1;
1115 
1116         /* Read type. */
1117         if ((type = rdbLoadType(&rdb)) == -1) goto eoferr;
1118         if (type == REDIS_RDB_OPCODE_EXPIRETIME) {
1119             if ((expiretime = rdbLoadTime(&rdb)) == -1) goto eoferr;
1120             /* We read the time so we need to read the object type again. */
1121             if ((type = rdbLoadType(&rdb)) == -1) goto eoferr;
1122             /* the EXPIRETIME opcode specifies time in seconds, so convert
1123              * into milliseconds. */
1124             expiretime *= 1000;
1125         } else if (type == REDIS_RDB_OPCODE_EXPIRETIME_MS) {
1126             /* Milliseconds precision expire times introduced with RDB
1127              * version 3. */
1128             if ((expiretime = rdbLoadMillisecondTime(&rdb)) == -1) goto eoferr;
1129             /* We read the time so we need to read the object type again. */
1130             if ((type = rdbLoadType(&rdb)) == -1) goto eoferr;
1131         }
1132 
1133         if (type == REDIS_RDB_OPCODE_EOF)
1134             break;
1135 
1136         /* Handle SELECT DB opcode as a special case */
1137         if (type == REDIS_RDB_OPCODE_SELECTDB) {
1138             if ((dbid = rdbLoadLen(&rdb,NULL)) == REDIS_RDB_LENERR)
1139                 goto eoferr;
1140             if (dbid >= (unsigned)server.dbnum) {
1141                 redisLog(REDIS_WARNING,"FATAL: Data file was created with a Redis server configured to handle more than %d databases. Exiting\n", server.dbnum);
1142                 exit(1);
1143             }
1144             db = server.db+dbid;
1145             continue;
1146         }
1147         /* Read key */
1148         if ((key = rdbLoadStringObject(&rdb)) == NULL) goto eoferr;
1149         /* Read value */
1150         if ((val = rdbLoadObject(type,&rdb)) == NULL) goto eoferr;
1151         /* Check if the key already expired. This function is used when loading
1152          * an RDB file from disk, either at startup, or when an RDB was
1153          * received from the master. In the latter case, the master is
1154          * responsible for key expiry. If we would expire keys here, the
1155          * snapshot taken by the master may not be reflected on the slave. */
1156         if (server.masterhost == NULL && expiretime != -1 && expiretime < now) {
1157             decrRefCount(key);
1158             decrRefCount(val);
1159             continue;
1160         }
1161         /* Add the new object in the hash table */
1162         dbAdd(db,key,val);
1163 
1164         /* Set the expire time if needed */
1165         if (expiretime != -1) setExpire(db,key,expiretime);
1166 
1167         decrRefCount(key);
1168     }
1169     /* Verify the checksum if RDB version is >= 5 */
1170     if (rdbver >= 5 && server.rdb_checksum) {
1171         uint64_t cksum, expected = rdb.cksum;
1172 
1173         if (rioRead(&rdb,&cksum,8) == 0) goto eoferr;
1174         memrev64ifbe(&cksum);
1175         if (cksum == 0) {
1176             redisLog(REDIS_WARNING,"RDB file was saved with checksum disabled: no check performed.");
1177         } else if (cksum != expected) {
1178             redisLog(REDIS_WARNING,"Wrong RDB checksum. Aborting now.");
1179             exit(1);
1180         }
1181     }
1182 
1183     fclose(fp);
1184     stopLoading();
1185     return REDIS_OK;
1186 
1187 eoferr: /* unexpected end of file is handled here with a fatal exit */
1188     redisLog(REDIS_WARNING,"Short read or OOM loading DB. Unrecoverable error, aborting now.");
1189     exit(1);
1190     return REDIS_ERR; /* Just to avoid warning */
1191 }
1192 
1193 /* A background saving child (BGSAVE) terminated its work. Handle this. */
1194 void backgroundSaveDoneHandler(int exitcode, int bysignal) {
1195     if (!bysignal && exitcode == 0) {
1196         redisLog(REDIS_NOTICE,
1197             "Background saving terminated with success");
1198         server.dirty = server.dirty - server.dirty_before_bgsave;
1199         server.lastsave = time(NULL);
1200         server.lastbgsave_status = REDIS_OK;
1201     } else if (!bysignal && exitcode != 0) {
1202         redisLog(REDIS_WARNING, "Background saving error");
1203         server.lastbgsave_status = REDIS_ERR;
1204     } else {
1205         mstime_t latency;
1206 
1207         redisLog(REDIS_WARNING,
1208             "Background saving terminated by signal %d", bysignal);
1209         latencyStartMonitor(latency);
1210         rdbRemoveTempFile(server.rdb_child_pid);
1211         latencyEndMonitor(latency);
1212         latencyAddSampleIfNeeded("rdb-unlink-temp-file",latency);
1213         /* SIGUSR1 is whitelisted, so we have a way to kill a child without
1214          * tirggering an error conditon. */
1215         if (bysignal != SIGUSR1)
1216             server.lastbgsave_status = REDIS_ERR;
1217     }
1218     server.rdb_child_pid = -1;
1219     server.rdb_save_time_last = time(NULL)-server.rdb_save_time_start;
1220     server.rdb_save_time_start = -1;
1221     /* Possibly there are slaves waiting for a BGSAVE in order to be served
1222      * (the first stage of SYNC is a bulk transfer of dump.rdb) */
1223     updateSlavesWaitingBgsave(exitcode == 0 ? REDIS_OK : REDIS_ERR);
1224 }
1225 
1226 void saveCommand(redisClient *c) {
1227     if (server.rdb_child_pid != -1) {
1228         addReplyError(c,"Background save already in progress");
1229         return;
1230     }
1231     if (rdbSave(server.rdb_filename) == REDIS_OK) {
1232         addReply(c,shared.ok);
1233     } else {
1234         addReply(c,shared.err);
1235     }
1236 }
1237 
1238 void bgsaveCommand(redisClient *c) {
1239     if (server.rdb_child_pid != -1) {
1240         addReplyError(c,"Background save already in progress");
1241     } else if (server.aof_child_pid != -1) {
1242         addReplyError(c,"Can't BGSAVE while AOF log rewriting is in progress");
1243     } else if (rdbSaveBackground(server.rdb_filename) == REDIS_OK) {
1244         addReplyStatus(c,"Background saving started");
1245     } else {
1246         addReply(c,shared.err);
1247     }
1248 }
1249