X-Git-Url: https://git.saurik.com/redis.git/blobdiff_plain/e12b27acf72ee7e40a6a39ffc7c109914c584cd9..b0d1d2684d15aeb201da6f8e1e23ba496d6907ad:/src/rdb.c?ds=inline diff --git a/src/rdb.c b/src/rdb.c index 62762bee..d019d94f 100644 --- a/src/rdb.c +++ b/src/rdb.c @@ -245,7 +245,7 @@ int rdbSaveDoubleValue(FILE *fp, double val) { return rdbWriteRaw(fp,buf,len); } -/* Save a Redis object. */ +/* Save a Redis object. Returns -1 on error, 0 on success. */ int rdbSaveObject(FILE *fp, robj *o) { int n, nwritten = 0; @@ -308,7 +308,7 @@ int rdbSaveObject(FILE *fp, robj *o) { if ((n = rdbSaveRawString(fp,o->ptr,l)) == -1) return -1; nwritten += n; - } else if (o->encoding == REDIS_ENCODING_RAW) { + } else if (o->encoding == REDIS_ENCODING_SKIPLIST) { zset *zs = o->ptr; dictIterator *di = dictGetIterator(zs->dict); dictEntry *de; @@ -327,7 +327,7 @@ int rdbSaveObject(FILE *fp, robj *o) { } dictReleaseIterator(di); } else { - redisPanic("Unknown sorted set enoding"); + redisPanic("Unknown sorted set encoding"); } } else if (o->type == REDIS_HASH) { /* Save a hash value */ @@ -425,12 +425,12 @@ int rdbSave(char *filename) { strerror(errno)); return REDIS_ERR; } - if (fwrite("REDIS0001",9,1,fp) == 0) goto werr; + if (fwrite("REDIS0002",9,1,fp) == 0) goto werr; for (j = 0; j < server.dbnum; j++) { redisDb *db = server.db+j; dict *d = db->dict; if (dictSize(d) == 0) continue; - di = dictGetIterator(d); + di = dictGetSafeIterator(d); if (!di) { fclose(fp); return REDIS_ERR; @@ -482,6 +482,7 @@ werr: int rdbSaveBackground(char *filename) { pid_t childpid; + long long start; if (server.bgsavechildpid != -1 || server.bgsavethread != (pthread_t) -1) return REDIS_ERR; @@ -493,6 +494,7 @@ int rdbSaveBackground(char *filename) { return dsRdbSaveBackground(filename); } + start = ustime(); if ((childpid = fork()) == 0) { int retval; @@ -503,6 +505,7 @@ int rdbSaveBackground(char *filename) { _exit((retval == REDIS_OK) ? 0 : 1); } else { /* Parent */ + server.stat_fork_time = ustime()-start; if (childpid == -1) { redisLog(REDIS_WARNING,"Can't save in background: fork: %s", strerror(errno)); @@ -756,11 +759,13 @@ robj *rdbLoadObject(int type, FILE *fp) { } else if (type == REDIS_ZSET) { /* Read list/set value */ size_t zsetlen; + size_t maxelelen = 0; zset *zs; if ((zsetlen = rdbLoadLen(fp,NULL)) == REDIS_RDB_LENERR) return NULL; o = createZsetObject(); zs = o->ptr; + /* Load every single element of the list/set */ while(zsetlen--) { robj *ele; @@ -770,10 +775,21 @@ robj *rdbLoadObject(int type, FILE *fp) { if ((ele = rdbLoadEncodedStringObject(fp)) == NULL) return NULL; ele = tryObjectEncoding(ele); if (rdbLoadDoubleValue(fp,&score) == -1) return NULL; + + /* Don't care about integer-encoded strings. */ + if (ele->encoding == REDIS_ENCODING_RAW && + sdslen(ele->ptr) > maxelelen) + maxelelen = sdslen(ele->ptr); + znode = zslInsert(zs->zsl,score,ele); dictAdd(zs->dict,ele,&znode->score); incrRefCount(ele); /* added to skiplist */ } + + /* Convert *after* loading, since sorted sets are not stored ordered. */ + if (zsetLength(o) <= server.zset_max_ziplist_entries && + maxelelen <= server.zset_max_ziplist_value) + zsetConvert(o,REDIS_ENCODING_ZIPLIST); } else if (type == REDIS_HASH) { size_t hashlen; @@ -861,9 +877,11 @@ robj *rdbLoadObject(int type, FILE *fp) { case REDIS_ZSET_ZIPLIST: o->type = REDIS_ZSET; o->encoding = REDIS_ENCODING_ZIPLIST; + if (zsetLength(o) > server.zset_max_ziplist_entries) + zsetConvert(o,REDIS_ENCODING_SKIPLIST); break; default: - redisPanic("Unknown enoding"); + redisPanic("Unknown encoding"); break; } } else { @@ -900,7 +918,7 @@ void stopLoading(void) { int rdbLoad(char *filename) { FILE *fp; uint32_t dbid; - int type, retval, rdbver; + int type, rdbver; redisDb *db = server.db+0; char buf[1024]; time_t expiretime, now = time(NULL); @@ -916,7 +934,7 @@ int rdbLoad(char *filename) { return REDIS_ERR; } rdbver = atoi(buf+5); - if (rdbver != 1) { + if (rdbver < 1 || rdbver > 2) { fclose(fp); redisLog(REDIS_WARNING,"Can't handle RDB format version %d",rdbver); return REDIS_ERR; @@ -963,11 +981,8 @@ int rdbLoad(char *filename) { continue; } /* Add the new object in the hash table */ - retval = dbAdd(db,key,val); - if (retval == REDIS_ERR) { - redisLog(REDIS_WARNING,"Loading DB, duplicated key (%s) found! Unrecoverable error, exiting now.", key->ptr); - exit(1); - } + dbAdd(db,key,val); + /* Set the expire time if needed */ if (expiretime != -1) setExpire(db,key,expiretime); @@ -1020,9 +1035,9 @@ void saveCommand(redisClient *c) { void bgsaveCommand(redisClient *c) { if (server.bgsavechildpid != -1 || server.bgsavethread != (pthread_t)-1) { addReplyError(c,"Background save already in progress"); - return; - } - if (rdbSaveBackground(server.dbfilename) == REDIS_OK) { + } else if (server.bgrewritechildpid != -1) { + addReplyError(c,"Can't BGSAVE while AOF log rewriting is in progress"); + } else if (rdbSaveBackground(server.dbfilename) == REDIS_OK) { addReplyStatus(c,"Background saving started"); } else { addReply(c,shared.err);