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.
}
#endif /* HAVE_BACKTRACE */
}
#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>
/* =========================== Software Watchdog ============================ */
#include <sys/time.h>
void enableWatchdog(int period);
void disableWatchdog(void);
void watchdogScheduleSignal(int period);
void enableWatchdog(int period);
void disableWatchdog(void);
void watchdogScheduleSignal(int period);
+void redisLogHexDump(int level, char *descr, void *value, size_t len);
value = hashTypeCurrentObject(hi, REDIS_HASH_VALUE);
value = tryObjectEncoding(value);
ret = dictAdd(dict, field, value);
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);
}
hashTypeReleaseIterator(hi);