summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorantirez <antirez@gmail.com>2014-10-07 12:56:23 +0200
committerantirez <antirez@gmail.com>2014-10-07 12:56:23 +0200
commit8beb98574ab285c910c50c877d688a11960d5bd5 (patch)
tree69fef1e49c7bd87d8c24c15c01227fab8b3ca73e
parent034ca98678e1ba122d390675fde709538bffa91a (diff)
downloadredis-8beb98574ab285c910c50c877d688a11960d5bd5.tar.gz
RDB file creation refactored to target non-disk target.
-rw-r--r--src/rdb.c73
1 files changed, 46 insertions, 27 deletions
diff --git a/src/rdb.c b/src/rdb.c
index 4d789bc2b..d67dbd9de 100644
--- a/src/rdb.c
+++ b/src/rdb.c
@@ -627,45 +627,37 @@ 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();
- FILE *fp;
- rio rdb;
uint64_t cksum;
- snprintf(tmpfile,256,"temp-%d.rdb", (int) getpid());
- fp = fopen(tmpfile,"w");
- if (!fp) {
- redisLog(REDIS_WARNING, "Failed opening .rdb for saving: %s",
- strerror(errno));
- return REDIS_ERR;
- }
-
- rioInitWithFile(&rdb,fp);
if (server.rdb_checksum)
- rdb.update_cksum = rioGenericUpdateChecksum;
+ rdb->update_cksum = rioGenericUpdateChecksum;
snprintf(magic,sizeof(magic),"REDIS%04d",REDIS_RDB_VERSION);
- if (rdbWriteRaw(&rdb,magic,9) == -1) goto werr;
+ 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;
- }
+ 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;
+ 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) {
@@ -675,20 +667,48 @@ int rdbSave(char *filename) {
initStaticStringObject(key,keystr);
expire = getExpire(db,&key);
- if (rdbSaveKeyValuePair(&rdb,&key,o,expire,now) == -1) goto werr;
+ 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;
+ 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;
+ cksum = rdb->cksum;
memrev64ifbe(&cksum);
- if (rioWrite(&rdb,&cksum,8) == 0) goto werr;
+ 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;
+ int error;
+
+ snprintf(tmpfile,256,"temp-%d.rdb", (int) getpid());
+ fp = fopen(tmpfile,"w");
+ if (!fp) {
+ redisLog(REDIS_WARNING, "Failed opening .rdb for saving: %s",
+ strerror(errno));
+ return REDIS_ERR;
+ }
+
+ rioInitWithFile(&rdb,fp);
+ if (rdbSaveRio(&rdb,&error) == REDIS_ERR) {
+ errno = error;
+ 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;
}