]> git.saurik.com Git - redis.git/commitdiff
Dump ziplist hex value on failed assertion.
authorantirez <antirez@gmail.com>
Mon, 11 Jun 2012 21:44:34 +0000 (23:44 +0200)
committerantirez <antirez@gmail.com>
Mon, 11 Jun 2012 22:41:48 +0000 (00:41 +0200)
The ziplist -> hashtable conversion code is triggered every time an hash
value must be promoted to a full hash table because the number or size of
elements reached the threshold.

If a problem in the ziplist causes the same field to be present
multiple times, the assertion of successful addition of the element
inside the hash table will fail, crashing server with a failed
assertion, but providing little information about the problem.

This code adds a new logging function to perform the hex dump of binary
data, and makes sure that the ziplist -> hashtable conversion code uses
this new logging facility to dump the content of the ziplist when the
assertion fails.

This change was originally made in order to investigate issue #547.

src/debug.c
src/redis.h
src/t_hash.c

index 4687fb6c072ff17e81070da0cd8f9f699ee7138a..e56862882a3612133072e006daee2d250c599480 100644 (file)
@@ -686,6 +686,30 @@ void sigsegvHandler(int sig, siginfo_t *info, void *secret) {
 }
 #endif /* HAVE_BACKTRACE */
 
+/* ==================== Logging functions for debugging ===================== */
+
+void redisLogHexDump(int level, char *descr, void *value, size_t len) {
+    char buf[65], *b;
+    unsigned char *v = value;
+    char charset[] = "0123456789abcdef";
+
+    redisLog(level,"%s (hexdump):", descr);
+    b = buf;
+    while(len) {
+        b[0] = charset[(*v)>>4];
+        b[1] = charset[(*v)&0xf];
+        b[2] = '\0';
+        b += 2;
+        len--;
+        v++;
+        if (b-buf == 64 || len == 0) {
+            redisLogRaw(level|REDIS_LOG_RAW,buf);
+            b = buf;
+        }
+    }
+    redisLogRaw(level|REDIS_LOG_RAW,"\n");
+}
+
 /* =========================== Software Watchdog ============================ */
 #include <sys/time.h>
 
index 273fc2414a8fce5d57fa8e53f866a4f6c926d60d..4ce5311b92727651ba2d868d920db35505e84419 100644 (file)
@@ -1274,4 +1274,5 @@ sds genRedisInfoString(char *section);
 void enableWatchdog(int period);
 void disableWatchdog(void);
 void watchdogScheduleSignal(int period);
+void redisLogHexDump(int level, char *descr, void *value, size_t len);
 #endif
index 5b7a347abbcd75379ac1e314862f8c83ff3c4c97..aa021b03814b60bd35a036c3a72877898b6e92f2 100644 (file)
@@ -403,7 +403,11 @@ void hashTypeConvertZiplist(robj *o, int enc) {
             value = hashTypeCurrentObject(hi, REDIS_HASH_VALUE);
             value = tryObjectEncoding(value);
             ret = dictAdd(dict, field, value);
-            redisAssert(ret == DICT_OK);
+            if (ret != DICT_OK) {
+                redisLogHexDump(REDIS_WARNING,"ziplist with dup elements dump",
+                    o->ptr,ziplistBlobLen(o->ptr));
+                redisAssert(ret == DICT_OK);
+            }
         }
 
         hashTypeReleaseIterator(hi);