diff --git a/src/Makefile b/src/Makefile index 295600c4..271ab34d 100644 --- a/src/Makefile +++ b/src/Makefile @@ -117,17 +117,16 @@ endif REDIS_SERVER_NAME=redis-server REDIS_SENTINEL_NAME=redis-sentinel -REDIS_SERVER_OBJ=adlist.o quicklist.o ae.o anet.o dict.o redis.o sds.o zmalloc.o lzf_c.o lzf_d.o pqsort.o zipmap.o sha1.o ziplist.o release.o networking.o util.o object.o db.o replication.o rdb.o t_string.o t_list.o t_set.o t_zset.o t_hash.o config.o aof.o pubsub.o multi.o debug.o sort.o intset.o syncio.o cluster.o crc16.o endianconv.o slowlog.o scripting.o bio.o rio.o rand.o memtest.o crc64.o bitops.o sentinel.o notify.o setproctitle.o blocked.o hyperloglog.o latency.o sparkline.o +REDIS_SERVER_OBJ=adlist.o quicklist.o ae.o anet.o dict.o redis.o sds.o zmalloc.o lzf_c.o lzf_d.o pqsort.o zipmap.o sha1.o ziplist.o release.o networking.o util.o object.o db.o replication.o rdb.o t_string.o t_list.o t_set.o t_zset.o t_hash.o config.o aof.o pubsub.o multi.o debug.o sort.o intset.o syncio.o cluster.o crc16.o endianconv.o slowlog.o scripting.o bio.o rio.o rand.o memtest.o crc64.o bitops.o sentinel.o notify.o setproctitle.o blocked.o hyperloglog.o latency.o sparkline.o redis-check-rdb.o REDIS_CLI_NAME=redis-cli REDIS_CLI_OBJ=anet.o sds.o adlist.o redis-cli.o zmalloc.o release.o anet.o ae.o crc64.o REDIS_BENCHMARK_NAME=redis-benchmark REDIS_BENCHMARK_OBJ=ae.o anet.o redis-benchmark.o sds.o adlist.o zmalloc.o redis-benchmark.o -REDIS_CHECK_DUMP_NAME=redis-check-dump -REDIS_CHECK_DUMP_OBJ=redis-check-dump.o lzf_c.o lzf_d.o crc64.o +REDIS_CHECK_RDB_NAME=redis-check-rdb REDIS_CHECK_AOF_NAME=redis-check-aof REDIS_CHECK_AOF_OBJ=redis-check-aof.o -all: $(REDIS_SERVER_NAME) $(REDIS_SENTINEL_NAME) $(REDIS_CLI_NAME) $(REDIS_BENCHMARK_NAME) $(REDIS_CHECK_DUMP_NAME) $(REDIS_CHECK_AOF_NAME) +all: $(REDIS_SERVER_NAME) $(REDIS_SENTINEL_NAME) $(REDIS_CLI_NAME) $(REDIS_BENCHMARK_NAME) $(REDIS_CHECK_RDB_NAME) $(REDIS_CHECK_AOF_NAME) @echo "" @echo "Hint: It's a good idea to run 'make test' ;)" @echo "" @@ -178,6 +177,10 @@ $(REDIS_SERVER_NAME): $(REDIS_SERVER_OBJ) $(REDIS_SENTINEL_NAME): $(REDIS_SERVER_NAME) $(REDIS_INSTALL) $(REDIS_SERVER_NAME) $(REDIS_SENTINEL_NAME) +# redis-check-rdb +$(REDIS_CHECK_RDB_NAME): $(REDIS_SERVER_NAME) + $(REDIS_INSTALL) $(REDIS_SERVER_NAME) $(REDIS_CHECK_RDB_NAME) + # redis-cli $(REDIS_CLI_NAME): $(REDIS_CLI_OBJ) $(REDIS_LD) -o $@ $^ ../deps/hiredis/libhiredis.a ../deps/linenoise/linenoise.o $(FINAL_LIBS) @@ -186,10 +189,6 @@ $(REDIS_CLI_NAME): $(REDIS_CLI_OBJ) $(REDIS_BENCHMARK_NAME): $(REDIS_BENCHMARK_OBJ) $(REDIS_LD) -o $@ $^ ../deps/hiredis/libhiredis.a $(FINAL_LIBS) -# redis-check-dump -$(REDIS_CHECK_DUMP_NAME): $(REDIS_CHECK_DUMP_OBJ) - $(REDIS_LD) -o $@ $^ $(FINAL_LIBS) - # redis-check-aof $(REDIS_CHECK_AOF_NAME): $(REDIS_CHECK_AOF_OBJ) $(REDIS_LD) -o $@ $^ $(FINAL_LIBS) @@ -201,7 +200,7 @@ $(REDIS_CHECK_AOF_NAME): $(REDIS_CHECK_AOF_OBJ) $(REDIS_CC) -c $< clean: - rm -rf $(REDIS_SERVER_NAME) $(REDIS_SENTINEL_NAME) $(REDIS_CLI_NAME) $(REDIS_BENCHMARK_NAME) $(REDIS_CHECK_DUMP_NAME) $(REDIS_CHECK_AOF_NAME) *.o *.gcda *.gcno *.gcov redis.info lcov-html + rm -rf $(REDIS_SERVER_NAME) $(REDIS_SENTINEL_NAME) $(REDIS_CLI_NAME) $(REDIS_BENCHMARK_NAME) $(REDIS_CHECK_RDB_NAME) $(REDIS_CHECK_AOF_NAME) *.o *.gcda *.gcno *.gcov redis.info lcov-html .PHONY: clean @@ -257,6 +256,6 @@ install: all $(REDIS_INSTALL) $(REDIS_SERVER_NAME) $(INSTALL_BIN) $(REDIS_INSTALL) $(REDIS_BENCHMARK_NAME) $(INSTALL_BIN) $(REDIS_INSTALL) $(REDIS_CLI_NAME) $(INSTALL_BIN) - $(REDIS_INSTALL) $(REDIS_CHECK_DUMP_NAME) $(INSTALL_BIN) + $(REDIS_INSTALL) $(REDIS_CHECK_RDB_NAME) $(INSTALL_BIN) $(REDIS_INSTALL) $(REDIS_CHECK_AOF_NAME) $(INSTALL_BIN) @ln -sf $(REDIS_SERVER_NAME) $(INSTALL_BIN)/$(REDIS_SENTINEL_NAME) diff --git a/src/redis-check-dump.c b/src/redis-check-rdb.c similarity index 94% rename from src/redis-check-dump.c rename to src/redis-check-rdb.c index 54646200..893a8185 100644 --- a/src/redis-check-dump.c +++ b/src/redis-check-rdb.c @@ -133,18 +133,13 @@ typedef struct { char success; } entry; -/* Global vars that are actually used as constants. The following double - * values are used for double on-disk serialization, and are initialized - * at runtime to avoid strange compiler optimizations. */ -static double R_Zero, R_PosInf, R_NegInf, R_Nan; - #define MAX_TYPES_NUM 256 #define MAX_TYPE_NAME_LEN 16 /* store string types for output */ static char types[MAX_TYPES_NUM][MAX_TYPE_NAME_LEN]; /* Return true if 't' is a valid object type. */ -int checkType(unsigned char t) { +static int checkType(unsigned char t) { /* In case a new object type is added, update the following * condition as necessary. */ return @@ -154,7 +149,7 @@ int checkType(unsigned char t) { } /* when number of bytes to read is negative, do a peek */ -int readBytes(void *target, long num) { +static int readBytes(void *target, long num) { char peek = (num < 0) ? 1 : 0; num = (num < 0) ? -num : num; @@ -188,7 +183,7 @@ int processHeader(void) { return dump_version; } -int loadType(entry *e) { +static int loadType(entry *e) { uint32_t offset = CURR_OFFSET; /* this byte needs to qualify as type */ @@ -208,7 +203,7 @@ int loadType(entry *e) { return 0; } -int peekType() { +static int peekType() { unsigned char t; if (readBytes(&t, -1) && (checkType(t))) return t; @@ -216,7 +211,7 @@ int peekType() { } /* discard time, just consume the bytes */ -int processTime(int type) { +static int processTime(int type) { uint32_t offset = CURR_OFFSET; unsigned char t[8]; int timelen = (type == REDIS_EXPIRETIME_MS) ? 8 : 4; @@ -231,7 +226,7 @@ int processTime(int type) { return 0; } -uint32_t loadLength(int *isencoded) { +static uint32_t loadLength(int *isencoded) { unsigned char buf[2]; uint32_t len; int type; @@ -257,7 +252,7 @@ uint32_t loadLength(int *isencoded) { } } -char *loadIntegerObject(int enctype) { +static char *loadIntegerObject(int enctype) { uint32_t offset = CURR_OFFSET; unsigned char enc[4]; long long val; @@ -289,7 +284,7 @@ char *loadIntegerObject(int enctype) { return buf; } -char* loadLzfStringObject() { +static char* loadLzfStringObject() { unsigned int slen, clen; char *c, *s; @@ -313,7 +308,7 @@ char* loadLzfStringObject() { } /* returns NULL when not processable, char* when valid */ -char* loadStringObject() { +static char* loadStringObject() { uint32_t offset = CURR_OFFSET; int isencoded; uint32_t len; @@ -336,7 +331,7 @@ char* loadStringObject() { if (len == REDIS_RDB_LENERR) return NULL; - char *buf = malloc(sizeof(char) * (len+1)); + char *buf = zmalloc(sizeof(char) * (len+1)); if (buf == NULL) return NULL; buf[len] = '\0'; if (!readBytes(buf, len)) { @@ -346,7 +341,7 @@ char* loadStringObject() { return buf; } -int processStringObject(char** store) { +static int processStringObject(char** store) { unsigned long offset = CURR_OFFSET; char *key = loadStringObject(); if (key == NULL) { @@ -363,7 +358,7 @@ int processStringObject(char** store) { return 1; } -double* loadDoubleValue() { +static double* loadDoubleValue() { char buf[256]; unsigned char len; double* val; @@ -386,7 +381,7 @@ double* loadDoubleValue() { } } -int processDoubleValue(double** store) { +static int processDoubleValue(double** store) { unsigned long offset = CURR_OFFSET; double *val = loadDoubleValue(); if (val == NULL) { @@ -403,7 +398,7 @@ int processDoubleValue(double** store) { return 1; } -int loadPair(entry *e) { +static int loadPair(entry *e) { uint32_t offset = CURR_OFFSET; uint32_t i; @@ -486,7 +481,7 @@ int loadPair(entry *e) { return 1; } -entry loadEntry() { +static entry loadEntry() { entry e = { NULL, -1, 0 }; uint32_t length, offset[4]; @@ -544,7 +539,7 @@ entry loadEntry() { return e; } -void printCentered(int indent, int width, char* body) { +static void printCentered(int indent, int width, char* body) { char head[256], tail[256]; memset(head, '\0', 256); memset(tail, '\0', 256); @@ -554,21 +549,21 @@ void printCentered(int indent, int width, char* body) { printf("%s %s %s\n", head, body, tail); } -void printValid(uint64_t ops, uint64_t bytes) { +static void printValid(uint64_t ops, uint64_t bytes) { char body[80]; sprintf(body, "Processed %llu valid opcodes (in %llu bytes)", (unsigned long long) ops, (unsigned long long) bytes); printCentered(4, 80, body); } -void printSkipped(uint64_t bytes, uint64_t offset) { +static void printSkipped(uint64_t bytes, uint64_t offset) { char body[80]; sprintf(body, "Skipped %llu bytes (resuming at 0x%08llx)", (unsigned long long) bytes, (unsigned long long) offset); printCentered(4, 80, body); } -void printErrorStack(entry *e) { +static void printErrorStack(entry *e) { unsigned int i; char body[64]; @@ -708,24 +703,18 @@ void process(void) { } } -int main(int argc, char **argv) { - /* expect the first argument to be the dump file */ - if (argc <= 1) { - printf("Usage: %s \n", argv[0]); - exit(0); - } - +int redis_check_rdb(char *rdbfilename) { int fd; off_t size; struct stat stat; void *data; - fd = open(argv[1], O_RDONLY); + fd = open(rdbfilename, O_RDONLY); if (fd < 1) { - ERROR("Cannot open file: %s\n", argv[1]); + ERROR("Cannot open file: %s\n", rdbfilename); } if (fstat(fd, &stat) == -1) { - ERROR("Cannot stat: %s\n", argv[1]); + ERROR("Cannot stat: %s\n", rdbfilename); } else { size = stat.st_size; } @@ -736,7 +725,7 @@ int main(int argc, char **argv) { data = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0); if (data == MAP_FAILED) { - ERROR("Cannot mmap: %s\n", argv[1]); + ERROR("Cannot mmap: %s\n", rdbfilename); } /* Initialize static vars */ diff --git a/src/redis.c b/src/redis.c index 13df8d28..24739cc3 100644 --- a/src/redis.c +++ b/src/redis.c @@ -3550,6 +3550,17 @@ int checkForSentinelMode(int argc, char **argv) { return 0; } +/* Returns 1 if there is --check-rdb among the arguments or if + * argv[0] is exactly "redis-check-rdb". */ +int checkForCheckRDBMode(int argc, char **argv) { + int j; + + if (strstr(argv[0],"redis-check-rdb") != NULL) return 1; + for (j = 1; j < argc; j++) + if (!strcmp(argv[j],"--check-rdb")) return 1; + return 0; +} + /* Function called at startup to load RDB or AOF file in memory. */ void loadDataFromDisk(void) { long long start = ustime(); @@ -3766,6 +3777,11 @@ int main(int argc, char **argv) { while(j != argc) { if (argv[j][0] == '-' && argv[j][1] == '-') { /* Option name */ + if (!strcmp(argv[j], "--check-rdb")) { + /* Argument has no options, need to skip for parsing. */ + j++; + continue; + } if (sdslen(options)) options = sdscat(options,"\n"); options = sdscat(options,argv[j]+2); options = sdscat(options," "); @@ -3791,9 +3807,17 @@ int main(int argc, char **argv) { redisLog(REDIS_WARNING, "Warning: no config file specified, using the default config. In order to specify a config file use %s /path/to/%s.conf", argv[0], server.sentinel_mode ? "sentinel" : "redis"); } + if (checkForCheckRDBMode(argc, argv)) { + redisLog(REDIS_WARNING, "Checking RDB file %s", server.rdb_filename); + redisLog(REDIS_WARNING, "To check different RDB file: " + "redis-check-rdb --dbfilename "); + exit(redis_check_rdb(server.rdb_filename)); + } + server.supervised = redisIsSupervised(server.supervised_mode); int background = server.daemonize && !server.supervised; if (background) daemonize(); + initServer(); if (background || server.pidfile) createPidFile(); redisSetProcTitle(argv[0]); diff --git a/src/redis.h b/src/redis.h index 0c191d06..87bb811b 100644 --- a/src/redis.h +++ b/src/redis.h @@ -1380,6 +1380,9 @@ void sentinelTimer(void); char *sentinelHandleConfiguration(char **argv, int argc); void sentinelIsRunning(void); +/* redis-check-rdb */ +int redis_check_rdb(char *rdbfilename); + /* Scripting */ void scriptingInit(void);