2  * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com> 
   5  * Redistribution and use in source and binary forms, with or without 
   6  * modification, are permitted provided that the following conditions are met: 
   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. 
  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. 
  31 #include "lzf.h"    /* LZF compression library */ 
  33 #include "endianconv.h" 
  36 #include <sys/types.h> 
  38 #include <sys/resource.h> 
  40 #include <arpa/inet.h> 
  43 static int rdbWriteRaw(rio 
*rdb
, void *p
, size_t len
) { 
  44     if (rdb 
&& rioWrite(rdb
,p
,len
) == 0) 
  49 int rdbSaveType(rio 
*rdb
, unsigned char type
) { 
  50     return rdbWriteRaw(rdb
,&type
,1); 
  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
) { 
  58     if (rioRead(rdb
,&type
,1) == 0) return -1; 
  62 time_t rdbLoadTime(rio 
*rdb
) { 
  64     if (rioRead(rdb
,&t32
,4) == 0) return -1; 
  68 int rdbSaveMillisecondTime(rio 
*rdb
, long long t
) { 
  69     int64_t t64 
= (int64_t) t
; 
  70     return rdbWriteRaw(rdb
,&t64
,8); 
  73 long long rdbLoadMillisecondTime(rio 
*rdb
) { 
  75     if (rioRead(rdb
,&t64
,8) == 0) return -1; 
  76     return (long long)t64
; 
  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
) { 
  87         /* Save a 6 bit len */ 
  88         buf
[0] = (len
&0xFF)|(REDIS_RDB_6BITLEN
<<6); 
  89         if (rdbWriteRaw(rdb
,buf
,1) == -1) return -1; 
  91     } else if (len 
< (1<<14)) { 
  92         /* Save a 14 bit len */ 
  93         buf
[0] = ((len
>>8)&0xFF)|(REDIS_RDB_14BITLEN
<<6); 
  95         if (rdbWriteRaw(rdb
,buf
,2) == -1) return -1; 
  98         /* Save a 32 bit len */ 
  99         buf
[0] = (REDIS_RDB_32BITLEN
<<6); 
 100         if (rdbWriteRaw(rdb
,buf
,1) == -1) return -1; 
 102         if (rdbWriteRaw(rdb
,&len
,4) == -4) return -1; 
 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]; 
 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; 
 123     } else if (type 
== REDIS_RDB_6BITLEN
) { 
 124         /* Read a 6 bit len. */ 
 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]; 
 131         /* Read a 32 bit len. */ 
 132         if (rioRead(rdb
,&len
,4) == 0) return REDIS_RDB_LENERR
; 
 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
; 
 146     } else if (value 
>= -(1<<15) && value 
<= (1<<15)-1) { 
 147         enc
[0] = (REDIS_RDB_ENCVAL
<<6)|REDIS_RDB_ENC_INT16
; 
 149         enc
[2] = (value
>>8)&0xFF; 
 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
; 
 154         enc
[2] = (value
>>8)&0xFF; 
 155         enc
[3] = (value
>>16)&0xFF; 
 156         enc
[4] = (value
>>24)&0xFF; 
 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]; 
 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
) { 
 175         if (rioRead(rdb
,enc
,2) == 0) return NULL
; 
 176         v 
= enc
[0]|(enc
[1]<<8); 
 178     } else if (enctype 
== REDIS_RDB_ENC_INT32
) { 
 180         if (rioRead(rdb
,enc
,4) == 0) return NULL
; 
 181         v 
= enc
[0]|(enc
[1]<<8)|(enc
[2]<<16)|(enc
[3]<<24); 
 184         val 
= 0; /* anti-warning */ 
 185         redisPanic("Unknown RDB integer encoding type"); 
 188         return createStringObjectFromLongLong(val
); 
 190         return createObject(REDIS_STRING
,sdsfromlonglong(val
)); 
 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
) { 
 198     char *endptr
, buf
[32]; 
 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
); 
 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; 
 209     return rdbEncodeInteger(value
,enc
); 
 212 int rdbSaveLzfStringObject(rio 
*rdb
, unsigned char *s
, size_t len
) { 
 213     size_t comprlen
, outlen
; 
 218     /* We require at least four bytes compression for this to be worth it */ 
 219     if (len 
<= 4) return 0; 
 221     if ((out 
= zmalloc(outlen
+1)) == NULL
) return 0; 
 222     comprlen 
= lzf_compress(s
, len
, out
, outlen
); 
 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
; 
 232     if ((n 
= rdbSaveLen(rdb
,comprlen
)) == -1) goto writeerr
; 
 235     if ((n 
= rdbSaveLen(rdb
,len
)) == -1) goto writeerr
; 
 238     if ((n 
= rdbWriteRaw(rdb
,out
,comprlen
)) == -1) goto writeerr
; 
 249 robj 
*rdbLoadLzfStringObject(rio 
*rdb
) { 
 250     unsigned int len
, clen
; 
 251     unsigned char *c 
= NULL
; 
 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
; 
 261     return createObject(REDIS_STRING
,val
); 
 268 /* Save a string objet 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
) { 
 274     /* Try integer encoding */ 
 276         unsigned char buf
[5]; 
 277         if ((enclen 
= rdbTryIntegerEncoding((char*)s
,len
,buf
)) > 0) { 
 278             if (rdbWriteRaw(rdb
,buf
,enclen
) == -1) return -1; 
 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; 
 289         /* Return value of 0 means data can't be compressed, save the old way */ 
 293     if ((n 
= rdbSaveLen(rdb
,len
)) == -1) return -1; 
 296         if (rdbWriteRaw(rdb
,s
,len
) == -1) return -1; 
 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]; 
 306     int enclen 
= rdbEncodeInteger(value
,buf
); 
 308         return rdbWriteRaw(rdb
,buf
,enclen
); 
 310         /* Encode as string */ 
 311         enclen 
= ll2string((char*)buf
,32,value
); 
 312         redisAssert(enclen 
< 32); 
 313         if ((n 
= rdbSaveLen(rdb
,enclen
)) == -1) return -1; 
 315         if ((n 
= rdbWriteRaw(rdb
,buf
,enclen
)) == -1) return -1; 
 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 alrady integer encoded. */ 
 325     if (obj
->encoding 
== REDIS_ENCODING_INT
) { 
 326         return rdbSaveLongLongAsStringObject(rdb
,(long)obj
->ptr
); 
 328         redisAssertWithInfo(NULL
,obj
,obj
->encoding 
== REDIS_ENCODING_RAW
); 
 329         return rdbSaveRawString(rdb
,obj
->ptr
,sdslen(obj
->ptr
)); 
 333 robj 
*rdbGenericLoadStringObject(rio 
*rdb
, int encode
) { 
 338     len 
= rdbLoadLen(rdb
,&isencoded
); 
 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
); 
 348             redisPanic("Unknown RDB encoding type"); 
 352     if (len 
== REDIS_RDB_LENERR
) return NULL
; 
 353     val 
= sdsnewlen(NULL
,len
); 
 354     if (len 
&& rioRead(rdb
,val
,len
) == 0) { 
 358     return createObject(REDIS_STRING
,val
); 
 361 robj 
*rdbLoadStringObject(rio 
*rdb
) { 
 362     return rdbGenericLoadStringObject(rdb
,0); 
 365 robj 
*rdbLoadEncodedStringObject(rio 
*rdb
) { 
 366     return rdbGenericLoadStringObject(rdb
,1); 
 369 /* Save a double value. Doubles are saved as strings prefixed by an unsigned 
 370  * 8 bit integer specifing the length of the representation. 
 371  * This 8 bit integer has special values in order to specify the following 
 377 int rdbSaveDoubleValue(rio 
*rdb
, double val
) { 
 378     unsigned char buf
[128]; 
 384     } else if (!isfinite(val
)) { 
 386         buf
[0] = (val 
< 0) ? 255 : 254; 
 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. 
 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
),(long long)val
); 
 404             snprintf((char*)buf
+1,sizeof(buf
)-1,"%.17g",val
); 
 405         buf
[0] = strlen((char*)buf
+1); 
 408     return rdbWriteRaw(rdb
,buf
,len
); 
 411 /* For information about double serialization check rdbSaveDoubleValue() */ 
 412 int rdbLoadDoubleValue(rio 
*rdb
, double *val
) { 
 416     if (rioRead(rdb
,&len
,1) == 0) return -1; 
 418     case 255: *val 
= R_NegInf
; return 0; 
 419     case 254: *val 
= R_PosInf
; return 0; 
 420     case 253: *val 
= R_Nan
; return 0; 
 422         if (rioRead(rdb
,buf
,len
) == 0) return -1; 
 424         sscanf(buf
, "%lg", val
); 
 429 /* Save the object type of object "o". */ 
 430 int rdbSaveObjectType(rio 
*rdb
, robj 
*o
) { 
 433         return rdbSaveType(rdb
,REDIS_RDB_TYPE_STRING
); 
 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
); 
 440             redisPanic("Unknown list encoding"); 
 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
); 
 447             redisPanic("Unknown set encoding"); 
 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
); 
 454             redisPanic("Unknown sorted set encoding"); 
 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
); 
 461             redisPanic("Unknown hash encoding"); 
 463         redisPanic("Unknown object type"); 
 465     return -1; /* avoid warning */ 
 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
) { 
 472     if ((type 
= rdbLoadType(rdb
)) == -1) return -1; 
 473     if (!rdbIsObjectType(type
)) return -1; 
 477 /* Save a Redis object. Returns -1 on error, 0 on success. */ 
 478 int rdbSaveObject(rio 
*rdb
, robj 
*o
) { 
 481     if (o
->type 
== REDIS_STRING
) { 
 482         /* Save a string value */ 
 483         if ((n 
= rdbSaveStringObject(rdb
,o
)) == -1) return -1; 
 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
); 
 490             if ((n 
= rdbSaveRawString(rdb
,o
->ptr
,l
)) == -1) return -1; 
 492         } else if (o
->encoding 
== REDIS_ENCODING_LINKEDLIST
) { 
 497             if ((n 
= rdbSaveLen(rdb
,listLength(list
))) == -1) return -1; 
 500             listRewind(list
,&li
); 
 501             while((ln 
= listNext(&li
))) { 
 502                 robj 
*eleobj 
= listNodeValue(ln
); 
 503                 if ((n 
= rdbSaveStringObject(rdb
,eleobj
)) == -1) return -1; 
 507             redisPanic("Unknown list encoding"); 
 509     } else if (o
->type 
== REDIS_SET
) { 
 510         /* Save a set value */ 
 511         if (o
->encoding 
== REDIS_ENCODING_HT
) { 
 513             dictIterator 
*di 
= dictGetIterator(set
); 
 516             if ((n 
= rdbSaveLen(rdb
,dictSize(set
))) == -1) return -1; 
 519             while((de 
= dictNext(di
)) != NULL
) { 
 520                 robj 
*eleobj 
= dictGetKey(de
); 
 521                 if ((n 
= rdbSaveStringObject(rdb
,eleobj
)) == -1) return -1; 
 524             dictReleaseIterator(di
); 
 525         } else if (o
->encoding 
== REDIS_ENCODING_INTSET
) { 
 526             size_t l 
= intsetBlobLen((intset
*)o
->ptr
); 
 528             if ((n 
= rdbSaveRawString(rdb
,o
->ptr
,l
)) == -1) return -1; 
 531             redisPanic("Unknown set encoding"); 
 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
); 
 538             if ((n 
= rdbSaveRawString(rdb
,o
->ptr
,l
)) == -1) return -1; 
 540         } else if (o
->encoding 
== REDIS_ENCODING_SKIPLIST
) { 
 542             dictIterator 
*di 
= dictGetIterator(zs
->dict
); 
 545             if ((n 
= rdbSaveLen(rdb
,dictSize(zs
->dict
))) == -1) return -1; 
 548             while((de 
= dictNext(di
)) != NULL
) { 
 549                 robj 
*eleobj 
= dictGetKey(de
); 
 550                 double *score 
= dictGetVal(de
); 
 552                 if ((n 
= rdbSaveStringObject(rdb
,eleobj
)) == -1) return -1; 
 554                 if ((n 
= rdbSaveDoubleValue(rdb
,*score
)) == -1) return -1; 
 557             dictReleaseIterator(di
); 
 559             redisPanic("Unknown sorted set encoding"); 
 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
); 
 566             if ((n 
= rdbSaveRawString(rdb
,o
->ptr
,l
)) == -1) return -1; 
 569         } else if (o
->encoding 
== REDIS_ENCODING_HT
) { 
 570             dictIterator 
*di 
= dictGetIterator(o
->ptr
); 
 573             if ((n 
= rdbSaveLen(rdb
,dictSize((dict
*)o
->ptr
))) == -1) return -1; 
 576             while((de 
= dictNext(di
)) != NULL
) { 
 577                 robj 
*key 
= dictGetKey(de
); 
 578                 robj 
*val 
= dictGetVal(de
); 
 580                 if ((n 
= rdbSaveStringObject(rdb
,key
)) == -1) return -1; 
 582                 if ((n 
= rdbSaveStringObject(rdb
,val
)) == -1) return -1; 
 585             dictReleaseIterator(di
); 
 588             redisPanic("Unknown hash encoding"); 
 592         redisPanic("Unknown object type"); 
 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); 
 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 actaully 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
) 
 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; 
 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; 
 629 /* Save the DB on disk. Return REDIS_ERR on error, REDIS_OK on success */ 
 630 int rdbSave(char *filename
) { 
 631     dictIterator 
*di 
= NULL
; 
 636     long long now 
= mstime(); 
 641     snprintf(tmpfile
,256,"temp-%d.rdb", (int) getpid()); 
 642     fp 
= fopen(tmpfile
,"w"); 
 644         redisLog(REDIS_WARNING
, "Failed opening .rdb for saving: %s", 
 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
; 
 655     for (j 
= 0; j 
< server
.dbnum
; j
++) { 
 656         redisDb 
*db 
= server
.db
+j
; 
 658         if (dictSize(d
) == 0) continue; 
 659         di 
= dictGetSafeIterator(d
); 
 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
; 
 669         /* Iterate this DB writing every entry */ 
 670         while((de 
= dictNext(di
)) != NULL
) { 
 671             sds keystr 
= dictGetKey(de
); 
 672             robj key
, *o 
= dictGetVal(de
); 
 675             initStaticStringObject(key
,keystr
); 
 676             expire 
= getExpire(db
,&key
); 
 677             if (rdbSaveKeyValuePair(&rdb
,&key
,o
,expire
,now
) == -1) goto werr
; 
 679         dictReleaseIterator(di
); 
 681     di 
= NULL
; /* So that we don't release it again on error. */ 
 684     if (rdbSaveType(&rdb
,REDIS_RDB_OPCODE_EOF
) == -1) goto werr
; 
 686     /* CRC64 checksum. It will be zero if checksum computation is disabled, the 
 687      * loading code skips the check in this case. */ 
 689     memrev64ifbe(&cksum
); 
 690     rioWrite(&rdb
,&cksum
,8); 
 692     /* Make sure data will not remain on the OS's output buffers */ 
 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
)); 
 704     redisLog(REDIS_NOTICE
,"DB saved on disk"); 
 706     server
.lastsave 
= time(NULL
); 
 707     server
.lastbgsave_status 
= REDIS_OK
; 
 713     redisLog(REDIS_WARNING
,"Write error saving DB on disk: %s", strerror(errno
)); 
 714     if (di
) dictReleaseIterator(di
); 
 718 int rdbSaveBackground(char *filename
) { 
 722     if (server
.rdb_child_pid 
!= -1) return REDIS_ERR
; 
 724     server
.dirty_before_bgsave 
= server
.dirty
; 
 727     if ((childpid 
= fork()) == 0) { 
 731         if (server
.ipfd 
> 0) close(server
.ipfd
); 
 732         if (server
.sofd 
> 0) close(server
.sofd
); 
 733         retval 
= rdbSave(filename
); 
 734         exitFromChild((retval 
== REDIS_OK
) ? 0 : 1); 
 737         server
.stat_fork_time 
= ustime()-start
; 
 738         if (childpid 
== -1) { 
 739             redisLog(REDIS_WARNING
,"Can't save in background: fork: %s", 
 743         redisLog(REDIS_NOTICE
,"Background saving started by pid %d",childpid
); 
 744         server
.rdb_save_time_start 
= time(NULL
); 
 745         server
.rdb_child_pid 
= childpid
; 
 746         updateDictResizePolicy(); 
 749     return REDIS_OK
; /* unreached */ 
 752 void rdbRemoveTempFile(pid_t childpid
) { 
 755     snprintf(tmpfile
,256,"temp-%d.rdb", (int) childpid
); 
 759 /* Load a Redis object of the specified type from the specified file. 
 760  * On success a newly allocated object is returned, otherwise NULL. */ 
 761 robj 
*rdbLoadObject(int rdbtype
, rio 
*rdb
) { 
 766     redisLog(REDIS_DEBUG
,"LOADING OBJECT %d (at %d)\n",rdbtype
,rioTell(rdb
)); 
 767     if (rdbtype 
== REDIS_RDB_TYPE_STRING
) { 
 768         /* Read string value */ 
 769         if ((o 
= rdbLoadEncodedStringObject(rdb
)) == NULL
) return NULL
; 
 770         o 
= tryObjectEncoding(o
); 
 771     } else if (rdbtype 
== REDIS_RDB_TYPE_LIST
) { 
 772         /* Read list value */ 
 773         if ((len 
= rdbLoadLen(rdb
,NULL
)) == REDIS_RDB_LENERR
) return NULL
; 
 775         /* Use a real list when there are too many entries */ 
 776         if (len 
> server
.list_max_ziplist_entries
) { 
 777             o 
= createListObject(); 
 779             o 
= createZiplistObject(); 
 782         /* Load every single element of the list */ 
 784             if ((ele 
= rdbLoadEncodedStringObject(rdb
)) == NULL
) return NULL
; 
 786             /* If we are using a ziplist and the value is too big, convert 
 787              * the object to a real list. */ 
 788             if (o
->encoding 
== REDIS_ENCODING_ZIPLIST 
&& 
 789                 ele
->encoding 
== REDIS_ENCODING_RAW 
&& 
 790                 sdslen(ele
->ptr
) > server
.list_max_ziplist_value
) 
 791                     listTypeConvert(o
,REDIS_ENCODING_LINKEDLIST
); 
 793             if (o
->encoding 
== REDIS_ENCODING_ZIPLIST
) { 
 794                 dec 
= getDecodedObject(ele
); 
 795                 o
->ptr 
= ziplistPush(o
->ptr
,dec
->ptr
,sdslen(dec
->ptr
),REDIS_TAIL
); 
 799                 ele 
= tryObjectEncoding(ele
); 
 800                 listAddNodeTail(o
->ptr
,ele
); 
 803     } else if (rdbtype 
== REDIS_RDB_TYPE_SET
) { 
 804         /* Read list/set value */ 
 805         if ((len 
= rdbLoadLen(rdb
,NULL
)) == REDIS_RDB_LENERR
) return NULL
; 
 807         /* Use a regular set when there are too many entries. */ 
 808         if (len 
> server
.set_max_intset_entries
) { 
 809             o 
= createSetObject(); 
 810             /* It's faster to expand the dict to the right size asap in order 
 811              * to avoid rehashing */ 
 812             if (len 
> DICT_HT_INITIAL_SIZE
) 
 813                 dictExpand(o
->ptr
,len
); 
 815             o 
= createIntsetObject(); 
 818         /* Load every single element of the list/set */ 
 819         for (i 
= 0; i 
< len
; i
++) { 
 821             if ((ele 
= rdbLoadEncodedStringObject(rdb
)) == NULL
) return NULL
; 
 822             ele 
= tryObjectEncoding(ele
); 
 824             if (o
->encoding 
== REDIS_ENCODING_INTSET
) { 
 825                 /* Fetch integer value from element */ 
 826                 if (isObjectRepresentableAsLongLong(ele
,&llval
) == REDIS_OK
) { 
 827                     o
->ptr 
= intsetAdd(o
->ptr
,llval
,NULL
); 
 829                     setTypeConvert(o
,REDIS_ENCODING_HT
); 
 830                     dictExpand(o
->ptr
,len
); 
 834             /* This will also be called when the set was just converted 
 835              * to regular hash table encoded set */ 
 836             if (o
->encoding 
== REDIS_ENCODING_HT
) { 
 837                 dictAdd((dict
*)o
->ptr
,ele
,NULL
); 
 842     } else if (rdbtype 
== REDIS_RDB_TYPE_ZSET
) { 
 843         /* Read list/set value */ 
 845         size_t maxelelen 
= 0; 
 848         if ((zsetlen 
= rdbLoadLen(rdb
,NULL
)) == REDIS_RDB_LENERR
) return NULL
; 
 849         o 
= createZsetObject(); 
 852         /* Load every single element of the list/set */ 
 856             zskiplistNode 
*znode
; 
 858             if ((ele 
= rdbLoadEncodedStringObject(rdb
)) == NULL
) return NULL
; 
 859             ele 
= tryObjectEncoding(ele
); 
 860             if (rdbLoadDoubleValue(rdb
,&score
) == -1) return NULL
; 
 862             /* Don't care about integer-encoded strings. */ 
 863             if (ele
->encoding 
== REDIS_ENCODING_RAW 
&& 
 864                 sdslen(ele
->ptr
) > maxelelen
) 
 865                     maxelelen 
= sdslen(ele
->ptr
); 
 867             znode 
= zslInsert(zs
->zsl
,score
,ele
); 
 868             dictAdd(zs
->dict
,ele
,&znode
->score
); 
 869             incrRefCount(ele
); /* added to skiplist */ 
 872         /* Convert *after* loading, since sorted sets are not stored ordered. */ 
 873         if (zsetLength(o
) <= server
.zset_max_ziplist_entries 
&& 
 874             maxelelen 
<= server
.zset_max_ziplist_value
) 
 875                 zsetConvert(o
,REDIS_ENCODING_ZIPLIST
); 
 876     } else if (rdbtype 
== REDIS_RDB_TYPE_HASH
) { 
 880         len 
= rdbLoadLen(rdb
, NULL
); 
 881         if (len 
== REDIS_RDB_LENERR
) return NULL
; 
 883         o 
= createHashObject(); 
 885         /* Too many entries? Use an hash table. */ 
 886         if (len 
> server
.hash_max_ziplist_entries
) 
 887             hashTypeConvert(o
, REDIS_ENCODING_HT
); 
 889         /* Load every field and value into the ziplist */ 
 890         while (o
->encoding 
== REDIS_ENCODING_ZIPLIST 
&& len 
> 0) { 
 894             /* Load raw strings */ 
 895             field 
= rdbLoadStringObject(rdb
); 
 896             if (field 
== NULL
) return NULL
; 
 897             redisAssert(field
->encoding 
== REDIS_ENCODING_RAW
); 
 898             value 
= rdbLoadStringObject(rdb
); 
 899             if (value 
== NULL
) return NULL
; 
 900             redisAssert(field
->encoding 
== REDIS_ENCODING_RAW
); 
 902             /* Add pair to ziplist */ 
 903             o
->ptr 
= ziplistPush(o
->ptr
, field
->ptr
, sdslen(field
->ptr
), ZIPLIST_TAIL
); 
 904             o
->ptr 
= ziplistPush(o
->ptr
, value
->ptr
, sdslen(value
->ptr
), ZIPLIST_TAIL
); 
 905             /* Convert to hash table if size threshold is exceeded */ 
 906             if (sdslen(field
->ptr
) > server
.hash_max_ziplist_value 
|| 
 907                 sdslen(value
->ptr
) > server
.hash_max_ziplist_value
) 
 911                 hashTypeConvert(o
, REDIS_ENCODING_HT
); 
 918         /* Load remaining fields and values into the hash table */ 
 919         while (o
->encoding 
== REDIS_ENCODING_HT 
&& len 
> 0) { 
 923             /* Load encoded strings */ 
 924             field 
= rdbLoadEncodedStringObject(rdb
); 
 925             if (field 
== NULL
) return NULL
; 
 926             value 
= rdbLoadEncodedStringObject(rdb
); 
 927             if (value 
== NULL
) return NULL
; 
 929             field 
= tryObjectEncoding(field
); 
 930             value 
= tryObjectEncoding(value
); 
 932             /* Add pair to hash table */ 
 933             ret 
= dictAdd((dict
*)o
->ptr
, field
, value
); 
 934             redisAssert(ret 
== REDIS_OK
); 
 937         /* All pairs should be read by now */ 
 938         redisAssert(len 
== 0); 
 940     } else if (rdbtype 
== REDIS_RDB_TYPE_HASH_ZIPMAP  
|| 
 941                rdbtype 
== REDIS_RDB_TYPE_LIST_ZIPLIST 
|| 
 942                rdbtype 
== REDIS_RDB_TYPE_SET_INTSET   
|| 
 943                rdbtype 
== REDIS_RDB_TYPE_ZSET_ZIPLIST 
|| 
 944                rdbtype 
== REDIS_RDB_TYPE_HASH_ZIPLIST
) 
 946         robj 
*aux 
= rdbLoadStringObject(rdb
); 
 948         if (aux 
== NULL
) return NULL
; 
 949         o 
= createObject(REDIS_STRING
,NULL
); /* string is just placeholder */ 
 950         o
->ptr 
= zmalloc(sdslen(aux
->ptr
)); 
 951         memcpy(o
->ptr
,aux
->ptr
,sdslen(aux
->ptr
)); 
 954         /* Fix the object encoding, and make sure to convert the encoded 
 955          * data type into the base type if accordingly to the current 
 956          * configuration there are too many elements in the encoded data 
 957          * type. Note that we only check the length and not max element 
 958          * size as this is an O(N) scan. Eventually everything will get 
 961             case REDIS_RDB_TYPE_HASH_ZIPMAP
: 
 962                 /* Convert to ziplist encoded hash. This must be deprecated 
 963                  * when loading dumps created by Redis 2.4 gets deprecated. */ 
 965                     unsigned char *zl 
= ziplistNew(); 
 966                     unsigned char *zi 
= zipmapRewind(o
->ptr
); 
 967                     unsigned char *fstr
, *vstr
; 
 968                     unsigned int flen
, vlen
; 
 969                     unsigned int maxlen 
= 0; 
 971                     while ((zi 
= zipmapNext(zi
, &fstr
, &flen
, &vstr
, &vlen
)) != NULL
) { 
 972                         if (flen 
> maxlen
) maxlen 
= flen
; 
 973                         if (vlen 
> maxlen
) maxlen 
= vlen
; 
 974                         zl 
= ziplistPush(zl
, fstr
, flen
, ZIPLIST_TAIL
); 
 975                         zl 
= ziplistPush(zl
, vstr
, vlen
, ZIPLIST_TAIL
); 
 980                     o
->type 
= REDIS_HASH
; 
 981                     o
->encoding 
= REDIS_ENCODING_ZIPLIST
; 
 983                     if (hashTypeLength(o
) > server
.hash_max_ziplist_entries 
|| 
 984                         maxlen 
> server
.hash_max_ziplist_value
) 
 986                         hashTypeConvert(o
, REDIS_ENCODING_HT
); 
 990             case REDIS_RDB_TYPE_LIST_ZIPLIST
: 
 991                 o
->type 
= REDIS_LIST
; 
 992                 o
->encoding 
= REDIS_ENCODING_ZIPLIST
; 
 993                 if (ziplistLen(o
->ptr
) > server
.list_max_ziplist_entries
) 
 994                     listTypeConvert(o
,REDIS_ENCODING_LINKEDLIST
); 
 996             case REDIS_RDB_TYPE_SET_INTSET
: 
 998                 o
->encoding 
= REDIS_ENCODING_INTSET
; 
 999                 if (intsetLen(o
->ptr
) > server
.set_max_intset_entries
) 
1000                     setTypeConvert(o
,REDIS_ENCODING_HT
); 
1002             case REDIS_RDB_TYPE_ZSET_ZIPLIST
: 
1003                 o
->type 
= REDIS_ZSET
; 
1004                 o
->encoding 
= REDIS_ENCODING_ZIPLIST
; 
1005                 if (zsetLength(o
) > server
.zset_max_ziplist_entries
) 
1006                     zsetConvert(o
,REDIS_ENCODING_SKIPLIST
); 
1008             case REDIS_RDB_TYPE_HASH_ZIPLIST
: 
1009                 o
->type 
= REDIS_HASH
; 
1010                 o
->encoding 
= REDIS_ENCODING_ZIPLIST
; 
1011                 if (hashTypeLength(o
) > server
.hash_max_ziplist_entries
) 
1012                     hashTypeConvert(o
, REDIS_ENCODING_HT
); 
1015                 redisPanic("Unknown encoding"); 
1019         redisPanic("Unknown object type"); 
1024 /* Mark that we are loading in the global state and setup the fields 
1025  * needed to provide loading stats. */ 
1026 void startLoading(FILE *fp
) { 
1031     server
.loading_start_time 
= time(NULL
); 
1032     if (fstat(fileno(fp
), &sb
) == -1) { 
1033         server
.loading_total_bytes 
= 1; /* just to avoid division by zero */ 
1035         server
.loading_total_bytes 
= sb
.st_size
; 
1039 /* Refresh the loading progress info */ 
1040 void loadingProgress(off_t pos
) { 
1041     server
.loading_loaded_bytes 
= pos
; 
1042     if (server
.stat_peak_memory 
< zmalloc_used_memory()) 
1043         server
.stat_peak_memory 
= zmalloc_used_memory(); 
1046 /* Loading finished */ 
1047 void stopLoading(void) { 
1051 int rdbLoad(char *filename
) { 
1054     redisDb 
*db 
= server
.db
+0; 
1056     long long expiretime
, now 
= mstime(); 
1061     fp 
= fopen(filename
,"r"); 
1066     rioInitWithFile(&rdb
,fp
); 
1067     if (server
.rdb_checksum
) 
1068         rdb
.update_cksum 
= rioGenericUpdateChecksum
; 
1069     if (rioRead(&rdb
,buf
,9) == 0) goto eoferr
; 
1071     if (memcmp(buf
,"REDIS",5) != 0) { 
1073         redisLog(REDIS_WARNING
,"Wrong signature trying to load DB from file"); 
1077     rdbver 
= atoi(buf
+5); 
1078     if (rdbver 
< 1 || rdbver 
> REDIS_RDB_VERSION
) { 
1080         redisLog(REDIS_WARNING
,"Can't handle RDB format version %d",rdbver
); 
1090         /* Serve the clients from time to time */ 
1091         if (!(loops
++ % 1000)) { 
1092             loadingProgress(rioTell(&rdb
)); 
1093             aeProcessEvents(server
.el
, AE_FILE_EVENTS
|AE_DONT_WAIT
); 
1097         if ((type 
= rdbLoadType(&rdb
)) == -1) goto eoferr
; 
1098         if (type 
== REDIS_RDB_OPCODE_EXPIRETIME
) { 
1099             if ((expiretime 
= rdbLoadTime(&rdb
)) == -1) goto eoferr
; 
1100             /* We read the time so we need to read the object type again. */ 
1101             if ((type 
= rdbLoadType(&rdb
)) == -1) goto eoferr
; 
1102             /* the EXPIRETIME opcode specifies time in seconds, so convert 
1103              * into milliesconds. */ 
1105         } else if (type 
== REDIS_RDB_OPCODE_EXPIRETIME_MS
) { 
1106             /* Milliseconds precision expire times introduced with RDB 
1108             if ((expiretime 
= rdbLoadMillisecondTime(&rdb
)) == -1) goto eoferr
; 
1109             /* We read the time so we need to read the object type again. */ 
1110             if ((type 
= rdbLoadType(&rdb
)) == -1) goto eoferr
; 
1113         if (type 
== REDIS_RDB_OPCODE_EOF
) 
1116         /* Handle SELECT DB opcode as a special case */ 
1117         if (type 
== REDIS_RDB_OPCODE_SELECTDB
) { 
1118             if ((dbid 
= rdbLoadLen(&rdb
,NULL
)) == REDIS_RDB_LENERR
) 
1120             if (dbid 
>= (unsigned)server
.dbnum
) { 
1121                 redisLog(REDIS_WARNING
,"FATAL: Data file was created with a Redis server configured to handle more than %d databases. Exiting\n", server
.dbnum
); 
1124             db 
= server
.db
+dbid
; 
1128         if ((key 
= rdbLoadStringObject(&rdb
)) == NULL
) goto eoferr
; 
1130         if ((val 
= rdbLoadObject(type
,&rdb
)) == NULL
) goto eoferr
; 
1131         /* Check if the key already expired. This function is used when loading 
1132          * an RDB file from disk, either at startup, or when an RDB was 
1133          * received from the master. In the latter case, the master is 
1134          * responsible for key expiry. If we would expire keys here, the 
1135          * snapshot taken by the master may not be reflected on the slave. */ 
1136         if (server
.masterhost 
== NULL 
&& expiretime 
!= -1 && expiretime 
< now
) { 
1141         /* Add the new object in the hash table */ 
1144         /* Set the expire time if needed */ 
1145         if (expiretime 
!= -1) setExpire(db
,key
,expiretime
); 
1149     /* Verify the checksum if RDB version is >= 5 */ 
1150     if (rdbver 
>= 5 && server
.rdb_checksum
) { 
1151         uint64_t cksum
, expected 
= rdb
.cksum
; 
1153         if (rioRead(&rdb
,&cksum
,8) == 0) goto eoferr
; 
1154         memrev64ifbe(&cksum
); 
1156             redisLog(REDIS_WARNING
,"RDB file was saved with checksum disabled: no check performed."); 
1157         } else if (cksum 
!= expected
) { 
1158             redisLog(REDIS_WARNING
,"Wrong RDB checksum. Aborting now."); 
1167 eoferr
: /* unexpected end of file is handled here with a fatal exit */ 
1168     redisLog(REDIS_WARNING
,"Short read or OOM loading DB. Unrecoverable error, aborting now."); 
1170     return REDIS_ERR
; /* Just to avoid warning */ 
1173 /* A background saving child (BGSAVE) terminated its work. Handle this. */ 
1174 void backgroundSaveDoneHandler(int exitcode
, int bysignal
) { 
1175     if (!bysignal 
&& exitcode 
== 0) { 
1176         redisLog(REDIS_NOTICE
, 
1177             "Background saving terminated with success"); 
1178         server
.dirty 
= server
.dirty 
- server
.dirty_before_bgsave
; 
1179         server
.lastsave 
= time(NULL
); 
1180         server
.lastbgsave_status 
= REDIS_OK
; 
1181     } else if (!bysignal 
&& exitcode 
!= 0) { 
1182         redisLog(REDIS_WARNING
, "Background saving error"); 
1183         server
.lastbgsave_status 
= REDIS_ERR
; 
1185         redisLog(REDIS_WARNING
, 
1186             "Background saving terminated by signal %d", bysignal
); 
1187         rdbRemoveTempFile(server
.rdb_child_pid
); 
1188         server
.lastbgsave_status 
= REDIS_ERR
; 
1190     server
.rdb_child_pid 
= -1; 
1191     server
.rdb_save_time_last 
= time(NULL
)-server
.rdb_save_time_start
; 
1192     server
.rdb_save_time_start 
= -1; 
1193     /* Possibly there are slaves waiting for a BGSAVE in order to be served 
1194      * (the first stage of SYNC is a bulk transfer of dump.rdb) */ 
1195     updateSlavesWaitingBgsave(exitcode 
== 0 ? REDIS_OK 
: REDIS_ERR
); 
1198 void saveCommand(redisClient 
*c
) { 
1199     if (server
.rdb_child_pid 
!= -1) { 
1200         addReplyError(c
,"Background save already in progress"); 
1203     if (rdbSave(server
.rdb_filename
) == REDIS_OK
) { 
1204         addReply(c
,shared
.ok
); 
1206         addReply(c
,shared
.err
); 
1210 void bgsaveCommand(redisClient 
*c
) { 
1211     if (server
.rdb_child_pid 
!= -1) { 
1212         addReplyError(c
,"Background save already in progress"); 
1213     } else if (server
.aof_child_pid 
!= -1) { 
1214         addReplyError(c
,"Can't BGSAVE while AOF log rewriting is in progress"); 
1215     } else if (rdbSaveBackground(server
.rdb_filename
) == REDIS_OK
) { 
1216         addReplyStatus(c
,"Background saving started"); 
1218         addReply(c
,shared
.err
);