summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/debug.c14
-rw-r--r--src/server.h2
-rw-r--r--src/ziplist.c60
-rw-r--r--src/ziplist.h1
4 files changed, 53 insertions, 24 deletions
diff --git a/src/debug.c b/src/debug.c
index f4689d532..b8ad4e511 100644
--- a/src/debug.c
+++ b/src/debug.c
@@ -280,6 +280,8 @@ void debugCommand(client *c) {
blen++; addReplyStatus(c,
"sdslen <key> -- Show low level SDS string info representing key and value.");
blen++; addReplyStatus(c,
+ "ziplist <key> -- Show low level info about the ziplist encoding.");
+ blen++; addReplyStatus(c,
"populate <count> [prefix] -- Create <count> string keys named key:<num>. If a prefix is specified is used instead of the 'key' prefix.");
blen++; addReplyStatus(c,
"digest -- Outputs an hex signature representing the current DB content.");
@@ -418,6 +420,18 @@ void debugCommand(client *c) {
(long long) sdsavail(val->ptr),
(long long) getStringObjectSdsUsedMemory(val));
}
+ } else if (!strcasecmp(c->argv[1]->ptr,"ziplist") && c->argc == 3) {
+ robj *o;
+
+ if ((o = objectCommandLookupOrReply(c,c->argv[2],shared.nokeyerr))
+ == NULL) return;
+
+ if (o->encoding != OBJ_ENCODING_ZIPLIST) {
+ addReplyError(c,"Not an sds encoded string.");
+ } else {
+ ziplistRepr(o->ptr);
+ addReplyStatus(c,"Ziplist structure printed on stdout");
+ }
} else if (!strcasecmp(c->argv[1]->ptr,"populate") &&
(c->argc == 3 || c->argc == 4)) {
long keys, j;
diff --git a/src/server.h b/src/server.h
index 2a61ea419..7ff151de8 100644
--- a/src/server.h
+++ b/src/server.h
@@ -1655,6 +1655,8 @@ robj *lookupKeyWrite(redisDb *db, robj *key);
robj *lookupKeyReadOrReply(client *c, robj *key, robj *reply);
robj *lookupKeyWriteOrReply(client *c, robj *key, robj *reply);
robj *lookupKeyReadWithFlags(redisDb *db, robj *key, int flags);
+robj *objectCommandLookup(client *c, robj *key);
+robj *objectCommandLookupOrReply(client *c, robj *key, robj *reply);
#define LOOKUP_NONE 0
#define LOOKUP_NOTOUCH (1<<0)
void dbAdd(redisDb *db, robj *key, robj *val);
diff --git a/src/ziplist.c b/src/ziplist.c
index 7428d30e9..684f8ccf8 100644
--- a/src/ziplist.c
+++ b/src/ziplist.c
@@ -8,24 +8,31 @@
*
* ----------------------------------------------------------------------------
*
- * ZIPLIST OVERALL LAYOUT:
+ * ZIPLIST OVERALL LAYOUT
+ *
* The general layout of the ziplist is as follows:
- * <zlbytes><zltail><zllen><entry><entry><zlend>
*
- * <zlbytes> is an unsigned integer to hold the number of bytes that the
- * ziplist occupies. This value needs to be stored to be able to resize the
+ * <zlbytes> <zltail> <zllen> <entry> <entry> ... <entry> <zlend>
+ *
+ * All fields are stored in little endian.
+ *
+ * <uint32_t zlbytes> is an unsigned integer to hold the number of bytes that
+ * the ziplist occupies. This value needs to be stored to be able to resize the
* entire structure without the need to traverse it first.
*
- * <zltail> is the offset to the last entry in the list. This allows a pop
- * operation on the far side of the list without the need for full traversal.
+ * <uint32_t zltail> is the offset to the last entry in the list. This allows
+ * a pop operation on the far side of the list without the need for full
+ * traversal.
+ *
+ * <uint16_t zllen> is the number of entries. When this value is larger
+ * than 2^16-2, we need to traverse the entire list to know how many items it
+ * holds.
*
- * <zllen> is the number of entries.When this value is larger than 2**16-2,
- * we need to traverse the entire list to know how many items it holds.
+ * <uint8_t zlend> is a single byte special value, equal to 255, which
+ * indicates the end of the list.
*
- * <zlend> is a single byte special value, equal to 255, which indicates the
- * end of the list.
+ * ZIPLIST ENTRIES
*
- * ZIPLIST ENTRIES:
* Every entry in the ziplist is prefixed by a header that contains two pieces
* of information. First, the length of the previous entry is stored to be
* able to traverse the list from back to front. Second, the encoding with an
@@ -1029,7 +1036,7 @@ void ziplistRepr(unsigned char *zl) {
printf(
"{total bytes %d} "
- "{length %u}\n"
+ "{num entries %u}\n"
"{tail offset %u}\n",
intrev32ifbe(ZIPLIST_BYTES(zl)),
intrev16ifbe(ZIPLIST_LENGTH(zl)),
@@ -1038,16 +1045,15 @@ void ziplistRepr(unsigned char *zl) {
while(*p != ZIP_END) {
zipEntry(p, &entry);
printf(
- "{"
- "addr 0x%08lx, "
- "index %2d, "
- "offset %5ld, "
- "rl: %5u, "
- "hs %2u, "
- "pl: %5u, "
- "pls: %2u, "
- "payload %5u"
- "} ",
+ "{\n"
+ "\taddr 0x%08lx,\n"
+ "\tindex %2d,\n"
+ "\toffset %5ld,\n"
+ "\thdr+entry len: %5u,\n"
+ "\thdr len%2u,\n"
+ "\tprevrawlen: %5u,\n"
+ "\tprevrawlensize: %2u,\n"
+ "\tpayload %5u\n",
(long unsigned)p,
index,
(unsigned long) (p-zl),
@@ -1056,8 +1062,14 @@ void ziplistRepr(unsigned char *zl) {
entry.prevrawlen,
entry.prevrawlensize,
entry.len);
+ printf("\tbytes: ");
+ for (unsigned int i = 0; i < entry.headersize+entry.len; i++) {
+ printf("%02x|",p[i]);
+ }
+ printf("\n");
p += entry.headersize;
if (ZIP_IS_STR(entry.encoding)) {
+ printf("\t[str]");
if (entry.len > 40) {
if (fwrite(p,40,1,stdout) == 0) perror("fwrite");
printf("...");
@@ -1066,9 +1078,9 @@ void ziplistRepr(unsigned char *zl) {
fwrite(p,entry.len,1,stdout) == 0) perror("fwrite");
}
} else {
- printf("%lld", (long long) zipLoadInteger(p,entry.encoding));
+ printf("\t[int]%lld", (long long) zipLoadInteger(p,entry.encoding));
}
- printf("\n");
+ printf("\n}\n");
p += entry.len;
index++;
}
diff --git a/src/ziplist.h b/src/ziplist.h
index ae96823f9..964a47f6d 100644
--- a/src/ziplist.h
+++ b/src/ziplist.h
@@ -48,6 +48,7 @@ unsigned int ziplistCompare(unsigned char *p, unsigned char *s, unsigned int sle
unsigned char *ziplistFind(unsigned char *p, unsigned char *vstr, unsigned int vlen, unsigned int skip);
unsigned int ziplistLen(unsigned char *zl);
size_t ziplistBlobLen(unsigned char *zl);
+void ziplistRepr(unsigned char *zl);
#ifdef REDIS_TEST
int ziplistTest(int argc, char *argv[]);