]> git.saurik.com Git - redis.git/blobdiff - src/redis-check-dump.c
New client info field added to CLIENT LIST output: multi, containing the length of...
[redis.git] / src / redis-check-dump.c
index 0b002790db1258d627bb132dc6bd16d6028d5b21..42fe5181087a19be3ec0914fabc82dcaa0d38d49 100644 (file)
 #define REDIS_SET 2
 #define REDIS_ZSET 3
 #define REDIS_HASH 4
+#define REDIS_HASH_ZIPMAP 9
+#define REDIS_LIST_ZIPLIST 10
+#define REDIS_SET_INTSET 11
+#define REDIS_ZSET_ZIPLIST 12
+#define REDIS_HASH_ZIPLIST 13
 
 /* Objects encoding. Some kind of objects like Strings and Hashes can be
  * internally represented in multiple ways. The 'encoding' field of the object
@@ -65,8 +70,8 @@
 /* data type to hold offset in file and size */
 typedef struct {
     void *data;
-    unsigned long size;
-    unsigned long offset;
+    size_t size;
+    size_t offset;
 } pos;
 
 static unsigned char level = 0;
@@ -77,8 +82,8 @@ static pos positions[16];
 /* Hold a stack of errors */
 typedef struct {
     char error[16][1024];
-    unsigned long offset[16];
-    unsigned int level;
+    size_t offset[16];
+    size_t level;
 } errors_t;
 static errors_t errors;
 
@@ -112,7 +117,7 @@ int readBytes(void *target, long num) {
     if (p.offset + num > p.size) {
         return 0;
     } else {
-        memcpy(target, (void*)((unsigned long)p.data + p.offset), num);
+        memcpy(target, (void*)((size_t)p.data + p.offset), num);
         if (!peek) positions[level].offset += num;
     }
     return 1;
@@ -132,7 +137,7 @@ int processHeader() {
     }
 
     dump_version = (int)strtol(buf + 5, NULL, 10);
-    if (dump_version != 1) {
+    if (dump_version < 1 || dump_version > 4) {
         ERROR("Unknown RDB format version: %d\n", dump_version);
     }
     return 1;
@@ -144,7 +149,7 @@ int loadType(entry *e) {
     /* this byte needs to qualify as type */
     unsigned char t;
     if (readBytes(&t, 1)) {
-        if (t <= 4 || t >= 253) {
+        if (t <= 4 || (t >=9 && t <= 12) || t >= 253) {
             e->type = t;
             return 1;
         } else {
@@ -160,7 +165,8 @@ int loadType(entry *e) {
 
 int peekType() {
     unsigned char t;
-    if (readBytes(&t, -1) && (t <= 4 || t >= 253)) return t;
+    if (readBytes(&t, -1) && (t <= 4 || (t >=9 && t <= 12) || t >= 253))
+        return t;
     return -1;
 }
 
@@ -375,6 +381,11 @@ int loadPair(entry *e) {
 
     switch(e->type) {
     case REDIS_STRING:
+    case REDIS_HASH_ZIPMAP:
+    case REDIS_LIST_ZIPLIST:
+    case REDIS_SET_INTSET:
+    case REDIS_ZSET_ZIPLIST:
+    case REDIS_HASH_ZIPLIST:
         if (!processStringObject(NULL)) {
             SHIFT_ERROR(offset, "Error reading entry value");
             return 0;
@@ -494,15 +505,17 @@ void printCentered(int indent, int width, char* body) {
     printf("%s %s %s\n", head, body, tail);
 }
 
-void printValid(int ops, int bytes) {
+void printValid(uint64_t ops, uint64_t bytes) {
     char body[80];
-    sprintf(body, "Processed %d valid opcodes (in %d bytes)", ops, bytes);
+    sprintf(body, "Processed %llu valid opcodes (in %llu bytes)",
+        (unsigned long long) ops, (unsigned long long) bytes);
     printCentered(4, 80, body);
 }
 
-void printSkipped(int bytes, int offset) {
+void printSkipped(uint64_t bytes, uint64_t offset) {
     char body[80];
-    sprintf(body, "Skipped %d bytes (resuming at 0x%08x)", bytes, offset);
+    sprintf(body, "Skipped %llu bytes (resuming at 0x%08llx)",
+        (unsigned long long) bytes, (unsigned long long) offset);
     printCentered(4, 80, body);
 }
 
@@ -536,12 +549,13 @@ void printErrorStack(entry *e) {
 
     /* display error stack */
     for (i = 0; i < errors.level; i++) {
-        printf("0x%08lx - %s\n", errors.offset[i], errors.error[i]);
+        printf("0x%08lx - %s\n",
+            (unsigned long) errors.offset[i], errors.error[i]);
     }
 }
 
 void process() {
-    int i, num_errors = 0, num_valid_ops = 0, num_valid_bytes = 0;
+    uint64_t num_errors = 0, num_valid_ops = 0, num_valid_bytes = 0;
     entry entry;
     processHeader();
 
@@ -558,7 +572,9 @@ void process() {
             num_valid_bytes = 0;
 
             /* search for next valid entry */
-            unsigned long offset = positions[0].offset + 1;
+            uint64_t offset = positions[0].offset + 1;
+            int i = 0;
+
             while (!entry.success && offset < positions[0].size) {
                 positions[1].offset = offset;
 
@@ -586,6 +602,7 @@ void process() {
             /* advance position */
             positions[0] = positions[1];
         }
+        free(entry.key);
     }
 
     /* because there is another potential error,
@@ -606,9 +623,10 @@ void process() {
     }
 
     /* print summary on errors */
-    if (num_errors > 0) {
+    if (num_errors) {
         printf("\n");
-        printf("Total unprocessable opcodes: %d\n", num_errors);
+        printf("Total unprocessable opcodes: %llu\n",
+            (unsigned long long) num_errors);
     }
 }
 
@@ -620,7 +638,7 @@ int main(int argc, char **argv) {
     }
 
     int fd;
-    unsigned long size;
+    off_t size;
     struct stat stat;
     void *data;
 
@@ -634,6 +652,10 @@ int main(int argc, char **argv) {
         size = stat.st_size;
     }
 
+    if (sizeof(size_t) == sizeof(int32_t) && size >= INT_MAX) {
+        ERROR("Cannot check dump files >2GB on a 32-bit platform\n");
+    }
+
     data = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
     if (data == MAP_FAILED) {
         ERROR("Cannot mmap: %s\n", argv[1]);