]> git.saurik.com Git - redis.git/commitdiff
redis-check-dump now is RDB version 6 ready.
authorantirez <antirez@gmail.com>
Tue, 24 Apr 2012 17:05:27 +0000 (19:05 +0200)
committerantirez <antirez@gmail.com>
Tue, 24 Apr 2012 17:35:36 +0000 (19:35 +0200)
src/Makefile
src/redis-check-dump.c

index a6e8e2f94f44a36afc48136949ce122c834d055c..082b375798f02c5ea1c1b2d0ab2f90e383c37a01 100644 (file)
@@ -102,7 +102,7 @@ REDIS_CLI_OBJ= anet.o sds.o adlist.o redis-cli.o zmalloc.o release.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
+REDIS_CHECK_DUMP_OBJ= redis-check-dump.o lzf_c.o lzf_d.o crc64.o
 REDIS_CHECK_AOF_NAME= redis-check-aof
 REDIS_CHECK_AOF_OBJ= redis-check-aof.o
 
index 42fe5181087a19be3ec0914fabc82dcaa0d38d49..5eac925ae98a358b12a5d6c74a4b8fee2deb9238 100644 (file)
@@ -108,6 +108,9 @@ static double R_Zero, R_PosInf, R_NegInf, R_Nan;
 /* store string types for output */
 static char types[256][16];
 
+/* Prototypes */
+uint64_t crc64(uint64_t crc, const unsigned char *s, uint64_t l);
+
 /* when number of bytes to read is negative, do a peek */
 int readBytes(void *target, long num) {
     char peek = (num < 0) ? 1 : 0;
@@ -137,10 +140,10 @@ int processHeader() {
     }
 
     dump_version = (int)strtol(buf + 5, NULL, 10);
-    if (dump_version < 1 || dump_version > 4) {
+    if (dump_version < 1 || dump_version > 6) {
         ERROR("Unknown RDB format version: %d\n", dump_version);
     }
-    return 1;
+    return dump_version;
 }
 
 int loadType(entry *e) {
@@ -557,7 +560,16 @@ void printErrorStack(entry *e) {
 void process() {
     uint64_t num_errors = 0, num_valid_ops = 0, num_valid_bytes = 0;
     entry entry;
-    processHeader();
+    int dump_version = processHeader();
+
+    /* Exclude the final checksum for RDB >= 5. Will be checked at the end. */
+    if (dump_version >= 5) {
+        if (positions[0].size < 8) {
+            printf("RDB version >= 5 but no room for checksum.\n");
+            exit(1);
+        }
+        positions[0].size -= 8;;
+    }
 
     level = 1;
     while(positions[0].offset < positions[0].size) {
@@ -622,6 +634,26 @@ void process() {
         num_errors++;
     }
 
+    /* Verify checksum */
+    if (dump_version >= 5) {
+        uint64_t crc = crc64(0,positions[0].data,positions[0].size);
+        uint64_t crc2;
+        unsigned char *p = (unsigned char*)positions[0].data+positions[0].size;
+        crc2 = ((uint64_t)p[0] << 0) |
+               ((uint64_t)p[1] << 8) |
+               ((uint64_t)p[2] << 16) |
+               ((uint64_t)p[3] << 24) |
+               ((uint64_t)p[4] << 32) |
+               ((uint64_t)p[5] << 40) |
+               ((uint64_t)p[6] << 48) |
+               ((uint64_t)p[7] << 56);
+        if (crc != crc2) {
+            SHIFT_ERROR(positions[0].offset, "RDB CRC64 does not match.");
+        } else {
+            printf("CRC64 checksum is OK\n");
+        }
+    }
+
     /* print summary on errors */
     if (num_errors) {
         printf("\n");