diff options
-rw-r--r-- | src/debug.c | 14 | ||||
-rw-r--r-- | src/server.h | 2 | ||||
-rw-r--r-- | src/ziplist.c | 60 | ||||
-rw-r--r-- | src/ziplist.h | 1 |
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[]); |