mirror of
https://github.com/fluencelabs/redis
synced 2025-03-19 09:00:51 +00:00
Convert check-dump to Redis check-rdb mode
redis-check-dump is now named redis-check-rdb and it runs as a mode of redis-server instead of an independent binary. You can now use 'redis-server redis.conf --check-rdb' to check the RDB defined in redis.conf. Using argument --check-rdb checks the RDB and exits. We could potentially also allow the server to continue starting if the RDB check succeeds. This change also enables us to use RDB checking programatically from inside Redis for certain failure conditions.
This commit is contained in:
parent
9802ec3c83
commit
145473acc5
19
src/Makefile
19
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)
|
||||
|
@ -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 <dump.rdb>\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 */
|
24
src/redis.c
24
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 <dump.rdb>");
|
||||
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]);
|
||||
|
@ -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);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user