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