summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatt Stancliff <matt@genges.com>2014-06-16 12:36:13 -0400
committerantirez <antirez@gmail.com>2014-06-25 15:03:41 +0200
commite14829de3025ffb0d3294e5e5a1553afd9f10b60 (patch)
treefa4841dedf1a823882614f3f553e9d9163852aea
parentf29b12d0bf368ef6a7e12baa0ce11dd7eaa149bf (diff)
downloadredis-e14829de3025ffb0d3294e5e5a1553afd9f10b60.tar.gz
Cluster: Add CLUSTER SLOTS command
CLUSTER SLOTS returns a Redis-formatted mapping from slot ranges to IP/Port pairs serving that slot range. The outer return elements group return values by slot ranges. The first two entires in each result are the min and max slots for the range. The third entry in each result is guaranteed to be either an IP/Port of the master for that slot range - OR - null if that slot range, for some reason, has no master The 4th and higher entries in each result are replica instances for the slot range. Output comparison: 127.0.0.1:7001> cluster nodes f853501ec8ae1618df0e0f0e86fd7abcfca36207 127.0.0.1:7001 myself,master - 0 0 2 connected 4096-8191 5a2caa782042187277647661ffc5da739b3e0805 127.0.0.1:7005 slave f853501ec8ae1618df0e0f0e86fd7abcfca36207 0 1402622415859 6 connected 6c70b49813e2ffc9dd4b8ec1e108276566fcf59f 127.0.0.1:7007 slave 26f4729ca0a5a992822667fc16b5220b13368f32 0 1402622415357 8 connected 2bd5a0e3bb7afb2b56a2120d3fef2f2e4333de1d 127.0.0.1:7006 slave 32adf4b8474fdc938189dba00dc8ed60ce635b0f 0 1402622419373 7 connected 5a9450e8279df36ff8e6bb1c139ce4d5268d1390 127.0.0.1:7000 master - 0 1402622418872 1 connected 0-4095 32adf4b8474fdc938189dba00dc8ed60ce635b0f 127.0.0.1:7002 master - 0 1402622419874 3 connected 8192-12287 5db7d05c245267afdfe48c83e7de899348d2bdb6 127.0.0.1:7004 slave 5a9450e8279df36ff8e6bb1c139ce4d5268d1390 0 1402622417867 5 connected 26f4729ca0a5a992822667fc16b5220b13368f32 127.0.0.1:7003 master - 0 1402622420877 4 connected 12288-16383 127.0.0.1:7001> cluster slots 1) 1) (integer) 0 2) (integer) 4095 3) 1) "127.0.0.1" 2) (integer) 7000 4) 1) "127.0.0.1" 2) (integer) 7004 2) 1) (integer) 12288 2) (integer) 16383 3) 1) "127.0.0.1" 2) (integer) 7003 4) 1) "127.0.0.1" 2) (integer) 7007 3) 1) (integer) 4096 2) (integer) 8191 3) 1) "127.0.0.1" 2) (integer) 7001 4) 1) "127.0.0.1" 2) (integer) 7005 4) 1) (integer) 8192 2) (integer) 12287 3) 1) "127.0.0.1" 2) (integer) 7002 4) 1) "127.0.0.1" 2) (integer) 7006
-rw-r--r--src/cluster.c71
1 files changed, 71 insertions, 0 deletions
diff --git a/src/cluster.c b/src/cluster.c
index c33e89486..252f19f05 100644
--- a/src/cluster.c
+++ b/src/cluster.c
@@ -3448,6 +3448,74 @@ int getSlotOrReply(redisClient *c, robj *o) {
return (int) slot;
}
+void clusterReplyMultiBulkSlots(redisClient *c) {
+ /* Format: 1) 1) start slot
+ * 2) end slot
+ * 3) 1) master IP
+ * 2) master port
+ * 4) 1) replica IP
+ * 2) replica port
+ * ... continued until done
+ */
+
+ int repliedRangeCount = 0;
+ void *slotreplylen = addDeferredMultiBulkLength(c);
+
+ dictEntry *de;
+ dictIterator *di = dictGetSafeIterator(server.cluster->nodes);
+ while((de = dictNext(di)) != NULL) {
+ clusterNode *node = dictGetVal(de);
+ int j = 0, start = -1;
+
+ /* If node is down or not a master, skip it. */
+ if (node->flags & REDIS_NODE_FAIL || !(node->flags & REDIS_NODE_MASTER))
+ continue;
+
+ for (j = 0; j < REDIS_CLUSTER_SLOTS; j++) {
+ int bit;
+
+ if ((bit = clusterNodeGetSlotBit(node,j)) != 0) {
+ if (start == -1) start = j;
+ }
+ if (start != -1 && (!bit || j == REDIS_CLUSTER_SLOTS-1)) {
+ if (bit && j == REDIS_CLUSTER_SLOTS-1) j++;
+
+ /* nested size: slots (2) + master (1) + slaves */
+ addReplyMultiBulkLen(c, 2 + 1 + node->numslaves);
+
+ /* If slot exists in output map, add to it's list.
+ * else, create a new output map for this slot */
+ if (start == j-1) {
+ addReplyLongLong(c, start); /* only one slot; low==high */
+ addReplyLongLong(c, start);
+ } else {
+ addReplyLongLong(c, start); /* low */
+ addReplyLongLong(c, j-1); /* high */
+ }
+ start = -1;
+
+ /* First node reply position is always the master */
+ addReplyMultiBulkLen(c, 2);
+ addReplyBulkCString(c, node->ip);
+ addReplyLongLong(c, node->port);
+
+ /* Remaining nodes in reply are replicas for slot range */
+ int i;
+ for (i = 0; i < node->numslaves; i++) {
+ /* This loop is copy/pasted from clusterGenNodeDescription()
+ * with modifications for per-slot node aggregation */
+ addReplyMultiBulkLen(c, 2);
+ addReplyBulkCString(c, node->slaves[i]->ip);
+ addReplyLongLong(c, node->slaves[i]->port);
+ }
+ repliedRangeCount++;
+ }
+ }
+ }
+ dictReleaseIterator(di);
+ setDeferredMultiBulkLength(c, slotreplylen, repliedRangeCount);
+}
+
void clusterCommand(redisClient *c) {
if (server.cluster_enabled == 0) {
addReplyError(c,"This instance has cluster support disabled");
@@ -3479,6 +3547,9 @@ void clusterCommand(redisClient *c) {
o = createObject(REDIS_STRING,ci);
addReplyBulk(c,o);
decrRefCount(o);
+ } else if (!strcasecmp(c->argv[1]->ptr,"slots") && c->argc == 2) {
+ /* CLUSTER SLOTS */
+ clusterReplyMultiBulkSlots(c);
} else if (!strcasecmp(c->argv[1]->ptr,"flushslots") && c->argc == 2) {
/* CLUSTER FLUSHSLOTS */
if (dictSize(server.db[0].dict) != 0) {