From 8beb98574ab285c910c50c877d688a11960d5bd5 Mon Sep 17 00:00:00 2001 From: antirez Date: Tue, 7 Oct 2014 12:56:23 +0200 Subject: [PATCH] RDB file creation refactored to target non-disk target. --- src/rdb.c | 109 ++++++++++++++++++++++++++++++++---------------------- 1 file changed, 64 insertions(+), 45 deletions(-) diff --git a/src/rdb.c b/src/rdb.c index 4d789bc2b..d67dbd9de 100644 --- a/src/rdb.c +++ b/src/rdb.c @@ -627,17 +627,74 @@ int rdbSaveKeyValuePair(rio *rdb, robj *key, robj *val, return 1; } -/* Save the DB on disk. Return REDIS_ERR on error, REDIS_OK on success */ -int rdbSave(char *filename) { +/* Produces a dump of the database in RDB format sending it to the specified + * Redis I/O channel. On success REDIS_OK is returned, otherwise REDIS_ERR + * is returned and part of the output, or all the output, can be + * missing because of I/O errors. + * + * When the function returns REDIS_ERR and if 'error' is not NULL, the + * integer pointed by 'error' is set to the value of errno just after the I/O + * error. */ +int rdbSaveRio(rio *rdb, int *error) { dictIterator *di = NULL; dictEntry *de; - char tmpfile[256]; char magic[10]; int j; long long now = mstime(); + uint64_t cksum; + + if (server.rdb_checksum) + rdb->update_cksum = rioGenericUpdateChecksum; + snprintf(magic,sizeof(magic),"REDIS%04d",REDIS_RDB_VERSION); + if (rdbWriteRaw(rdb,magic,9) == -1) goto werr; + + for (j = 0; j < server.dbnum; j++) { + redisDb *db = server.db+j; + dict *d = db->dict; + if (dictSize(d) == 0) continue; + di = dictGetSafeIterator(d); + if (!di) return REDIS_ERR; + + /* Write the SELECT DB opcode */ + if (rdbSaveType(rdb,REDIS_RDB_OPCODE_SELECTDB) == -1) goto werr; + if (rdbSaveLen(rdb,j) == -1) goto werr; + + /* Iterate this DB writing every entry */ + while((de = dictNext(di)) != NULL) { + sds keystr = dictGetKey(de); + robj key, *o = dictGetVal(de); + long long expire; + + initStaticStringObject(key,keystr); + expire = getExpire(db,&key); + if (rdbSaveKeyValuePair(rdb,&key,o,expire,now) == -1) goto werr; + } + dictReleaseIterator(di); + } + di = NULL; /* So that we don't release it again on error. */ + + /* EOF opcode */ + if (rdbSaveType(rdb,REDIS_RDB_OPCODE_EOF) == -1) goto werr; + + /* CRC64 checksum. It will be zero if checksum computation is disabled, the + * loading code skips the check in this case. */ + cksum = rdb->cksum; + memrev64ifbe(&cksum); + if (rioWrite(rdb,&cksum,8) == 0) goto werr; + return REDIS_OK; + +werr: + if (error) *error = errno; + if (di) dictReleaseIterator(di); + return REDIS_ERR; +} + +/* Save the DB on disk. Return REDIS_ERR on error, REDIS_OK on success. */ +int rdbSave(char *filename) { + char tmpfile[256]; FILE *fp; rio rdb; - uint64_t cksum; + int error; snprintf(tmpfile,256,"temp-%d.rdb", (int) getpid()); fp = fopen(tmpfile,"w"); @@ -648,47 +705,10 @@ int rdbSave(char *filename) { } rioInitWithFile(&rdb,fp); - if (server.rdb_checksum) - rdb.update_cksum = rioGenericUpdateChecksum; - snprintf(magic,sizeof(magic),"REDIS%04d",REDIS_RDB_VERSION); - if (rdbWriteRaw(&rdb,magic,9) == -1) goto werr; - - for (j = 0; j < server.dbnum; j++) { - redisDb *db = server.db+j; - dict *d = db->dict; - if (dictSize(d) == 0) continue; - di = dictGetSafeIterator(d); - if (!di) { - fclose(fp); - return REDIS_ERR; - } - - /* Write the SELECT DB opcode */ - if (rdbSaveType(&rdb,REDIS_RDB_OPCODE_SELECTDB) == -1) goto werr; - if (rdbSaveLen(&rdb,j) == -1) goto werr; - - /* Iterate this DB writing every entry */ - while((de = dictNext(di)) != NULL) { - sds keystr = dictGetKey(de); - robj key, *o = dictGetVal(de); - long long expire; - - initStaticStringObject(key,keystr); - expire = getExpire(db,&key); - if (rdbSaveKeyValuePair(&rdb,&key,o,expire,now) == -1) goto werr; - } - dictReleaseIterator(di); + if (rdbSaveRio(&rdb,&error) == REDIS_ERR) { + errno = error; + goto werr; } - di = NULL; /* So that we don't release it again on error. */ - - /* EOF opcode */ - if (rdbSaveType(&rdb,REDIS_RDB_OPCODE_EOF) == -1) goto werr; - - /* CRC64 checksum. It will be zero if checksum computation is disabled, the - * loading code skips the check in this case. */ - cksum = rdb.cksum; - memrev64ifbe(&cksum); - if (rioWrite(&rdb,&cksum,8) == 0) goto werr; /* Make sure data will not remain on the OS's output buffers */ if (fflush(fp) == EOF) goto werr; @@ -712,7 +732,6 @@ werr: fclose(fp); unlink(tmpfile); redisLog(REDIS_WARNING,"Write error saving DB on disk: %s", strerror(errno)); - if (di) dictReleaseIterator(di); return REDIS_ERR; }