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