From 84bcd3aa24eabed2a5295dc3450e6f45aa79049c Mon Sep 17 00:00:00 2001 From: antirez Date: Tue, 10 Apr 2012 15:47:10 +0200 Subject: [PATCH] It is now possible to enable/disable RDB checksum computation from redis.conf or via CONFIG SET/GET. Also CONFIG SET support added for rdbcompression as well. --- redis.conf | 9 +++++++++ src/config.c | 15 +++++++++++++++ src/rdb.c | 15 ++++++++++----- src/redis.c | 1 + src/redis.h | 1 + 5 files changed, 36 insertions(+), 5 deletions(-) diff --git a/redis.conf b/redis.conf index 1b79e09e..d7d29303 100644 --- a/redis.conf +++ b/redis.conf @@ -114,6 +114,15 @@ stop-writes-on-bgsave-error yes # the dataset will likely be bigger if you have compressible values or keys. rdbcompression yes +# Since verison 5 of RDB a CRC64 checksum is placed at the end of the file. +# This makes the format more resistant to corruption but there is a performance +# hit to pay (around 10%) when saving and loading RDB files, so you can disable it +# for maximum performances. +# +# RDB files created with checksum disabled have a checksum of zero that will +# tell the loading code to skip the check. +rdbchecksum yes + # The filename where to dump the DB dbfilename dump.rdb diff --git a/src/config.c b/src/config.c index 8dffe288..9899dfbc 100644 --- a/src/config.c +++ b/src/config.c @@ -210,6 +210,10 @@ void loadServerConfigFromString(char *config) { if ((server.rdb_compression = yesnotoi(argv[1])) == -1) { err = "argument must be 'yes' or 'no'"; goto loaderr; } + } else if (!strcasecmp(argv[0],"rdbchecksum") && argc == 2) { + if ((server.rdb_checksum = yesnotoi(argv[1])) == -1) { + err = "argument must be 'yes' or 'no'"; goto loaderr; + } } else if (!strcasecmp(argv[0],"activerehashing") && argc == 2) { if ((server.activerehashing = yesnotoi(argv[1])) == -1) { err = "argument must be 'yes' or 'no'"; goto loaderr; @@ -633,6 +637,16 @@ void configSetCommand(redisClient *c) { enableWatchdog(ll); else disableWatchdog(); + } else if (!strcasecmp(c->argv[2]->ptr,"rdbcompression")) { + int yn = yesnotoi(o->ptr); + + if (yn == -1) goto badfmt; + server.rdb_compression = yn; + } else if (!strcasecmp(c->argv[2]->ptr,"rdbchecksum")) { + int yn = yesnotoi(o->ptr); + + if (yn == -1) goto badfmt; + server.rdb_checksum = yn; } else { addReplyErrorFormat(c,"Unsupported CONFIG parameter: %s", (char*)c->argv[2]->ptr); @@ -734,6 +748,7 @@ void configGetCommand(redisClient *c) { server.stop_writes_on_bgsave_err); config_get_bool_field("daemonize", server.daemonize); config_get_bool_field("rdbcompression", server.rdb_compression); + config_get_bool_field("rdbchecksum", server.rdb_checksum); config_get_bool_field("activerehashing", server.activerehashing); /* Everything we can't handle with macros follows. */ diff --git a/src/rdb.c b/src/rdb.c index 1815dc24..8ffd2c28 100644 --- a/src/rdb.c +++ b/src/rdb.c @@ -614,7 +614,8 @@ int rdbSave(char *filename) { } rioInitWithFile(&rdb,fp); - rdb.update_cksum = rioGenericUpdateChecksum; + 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; @@ -649,7 +650,8 @@ int rdbSave(char *filename) { /* EOF opcode */ if (rdbSaveType(&rdb,REDIS_RDB_OPCODE_EOF) == -1) goto werr; - /* CRC64 checksum */ + /* 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); rioWrite(&rdb,&cksum,8); @@ -1026,7 +1028,8 @@ int rdbLoad(char *filename) { return REDIS_ERR; } rioInitWithFile(&rdb,fp); - rdb.update_cksum = rioGenericUpdateChecksum; + if (server.rdb_checksum) + rdb.update_cksum = rioGenericUpdateChecksum; if (rioRead(&rdb,buf,9) == 0) goto eoferr; buf[9] = '\0'; if (memcmp(buf,"REDIS",5) != 0) { @@ -1108,12 +1111,14 @@ int rdbLoad(char *filename) { decrRefCount(key); } /* Verify the checksum if RDB version is >= 5 */ - if (rdbver >= 5) { + if (rdbver >= 5 && server.rdb_checksum) { uint64_t cksum, expected = rdb.cksum; if (rioRead(&rdb,&cksum,8) == 0) goto eoferr; memrev64ifbe(&cksum); - if (cksum != expected) { + if (cksum == 0) { + redisLog(REDIS_WARNING,"RDB file was saved with checksum disabled: no check performed."); + } else if (cksum != expected) { redisLog(REDIS_WARNING,"Wrong RDB checksum. Aborting now."); exit(1); } diff --git a/src/redis.c b/src/redis.c index 84221add..ea5525dc 100644 --- a/src/redis.c +++ b/src/redis.c @@ -1061,6 +1061,7 @@ void initServerConfig() { server.aof_filename = zstrdup("appendonly.aof"); server.requirepass = NULL; server.rdb_compression = 1; + server.rdb_checksum = 1; server.activerehashing = 1; server.maxclients = REDIS_MAX_CLIENTS; server.bpop_blocked_clients = 0; diff --git a/src/redis.h b/src/redis.h index 52d39bc7..42a9b581 100644 --- a/src/redis.h +++ b/src/redis.h @@ -646,6 +646,7 @@ struct redisServer { int saveparamslen; /* Number of saving points */ char *rdb_filename; /* Name of RDB file */ int rdb_compression; /* Use compression in RDB? */ + int rdb_checksum; /* Use RDB checksum? */ time_t lastsave; /* Unix time of last save succeeede */ int lastbgsave_status; /* REDIS_OK or REDIS_ERR */ int stop_writes_on_bgsave_err; /* Don't allow writes if can't BGSAVE */