@Test public void testMultiIndexEvenDistribution() { AllocationService strategy = createAllocationService( settingsBuilder() .put("cluster.routing.allocation.concurrent_recoveries", 10) .put("cluster.routing.allocation.allow_rebalance", "always") .put("cluster.routing.allocation.cluster_concurrent_rebalance", -1) .build()); final int numberOfIndices = 50; logger.info("Building initial routing table with " + numberOfIndices + " indices"); MetaData.Builder metaDataBuilder = MetaData.builder(); for (int i = 0; i < numberOfIndices; i++) { metaDataBuilder.put(IndexMetaData.builder("test" + i).numberOfShards(1).numberOfReplicas(0)); } MetaData metaData = metaDataBuilder.build(); RoutingTable.Builder routingTableBuilder = RoutingTable.builder(); for (int i = 0; i < numberOfIndices; i++) { routingTableBuilder.addAsNew(metaData.index("test" + i)); } RoutingTable routingTable = routingTableBuilder.build(); ClusterState clusterState = ClusterState.builder().metaData(metaData).routingTable(routingTable).build(); assertThat(routingTable.indicesRouting().size(), equalTo(numberOfIndices)); for (int i = 0; i < numberOfIndices; i++) { assertThat(routingTable.index("test" + i).shards().size(), equalTo(1)); assertThat(routingTable.index("test" + i).shard(0).size(), equalTo(1)); assertThat(routingTable.index("test" + i).shard(0).shards().size(), equalTo(1)); assertThat( routingTable.index("test" + i).shard(0).shards().get(0).state(), equalTo(UNASSIGNED)); assertThat( routingTable.index("test" + i).shard(0).shards().get(0).currentNodeId(), nullValue()); } logger.info("Adding " + (numberOfIndices / 2) + " nodes"); DiscoveryNodes.Builder nodesBuilder = DiscoveryNodes.builder(); List<DiscoveryNode> nodes = newArrayList(); for (int i = 0; i < (numberOfIndices / 2); i++) { nodesBuilder.put(newNode("node" + i)); } RoutingTable prevRoutingTable = routingTable; clusterState = ClusterState.builder(clusterState).nodes(nodesBuilder).build(); routingTable = strategy.reroute(clusterState).routingTable(); clusterState = ClusterState.builder(clusterState).routingTable(routingTable).build(); assertThat(prevRoutingTable != routingTable, equalTo(true)); for (int i = 0; i < numberOfIndices; i++) { assertThat(routingTable.index("test" + i).shards().size(), equalTo(1)); assertThat(routingTable.index("test" + i).shard(0).size(), equalTo(1)); assertThat(routingTable.index("test" + i).shard(0).shards().size(), equalTo(1)); assertThat( routingTable.index("test" + i).shard(0).shards().get(0).unassigned(), equalTo(false)); assertThat( routingTable.index("test" + i).shard(0).shards().get(0).state(), equalTo(INITIALIZING)); assertThat(routingTable.index("test" + i).shard(0).shards().get(0).primary(), equalTo(true)); // make sure we still have 2 shards initializing per node on the first 25 nodes String nodeId = routingTable.index("test" + i).shard(0).shards().get(0).currentNodeId(); int nodeIndex = Integer.parseInt(nodeId.substring("node".length())); assertThat(nodeIndex, lessThan(25)); } RoutingNodes routingNodes = clusterState.routingNodes(); Set<String> encounteredIndices = newHashSet(); for (RoutingNode routingNode : routingNodes) { assertThat(routingNode.numberOfShardsWithState(STARTED), equalTo(0)); assertThat(routingNode.size(), equalTo(2)); // make sure we still have 2 shards initializing per node on the only 25 nodes int nodeIndex = Integer.parseInt(routingNode.nodeId().substring("node".length())); assertThat(nodeIndex, lessThan(25)); // check that we don't have a shard associated with a node with the same index name (we have a // single shard) for (MutableShardRouting shardRoutingEntry : routingNode) { assertThat(encounteredIndices, not(hasItem(shardRoutingEntry.index()))); encounteredIndices.add(shardRoutingEntry.index()); } } logger.info("Adding additional " + (numberOfIndices / 2) + " nodes, nothing should change"); nodesBuilder = DiscoveryNodes.builder(clusterState.nodes()); for (int i = (numberOfIndices / 2); i < numberOfIndices; i++) { nodesBuilder.put(newNode("node" + i)); } prevRoutingTable = routingTable; clusterState = ClusterState.builder(clusterState).nodes(nodesBuilder).build(); routingTable = strategy.reroute(clusterState).routingTable(); clusterState = ClusterState.builder(clusterState).routingTable(routingTable).build(); assertThat(prevRoutingTable != routingTable, equalTo(false)); logger.info("Marking the shard as started"); prevRoutingTable = routingTable; routingTable = strategy .applyStartedShards(clusterState, routingNodes.shardsWithState(INITIALIZING)) .routingTable(); clusterState = ClusterState.builder(clusterState).routingTable(routingTable).build(); assertThat(prevRoutingTable != routingTable, equalTo(true)); int numberOfRelocatingShards = 0; int numberOfStartedShards = 0; for (int i = 0; i < numberOfIndices; i++) { assertThat(routingTable.index("test" + i).shards().size(), equalTo(1)); assertThat(routingTable.index("test" + i).shard(0).size(), equalTo(1)); assertThat(routingTable.index("test" + i).shard(0).shards().size(), equalTo(1)); assertThat( routingTable.index("test" + i).shard(0).shards().get(0).unassigned(), equalTo(false)); assertThat( routingTable.index("test" + i).shard(0).shards().get(0).state(), anyOf(equalTo(STARTED), equalTo(RELOCATING))); if (routingTable.index("test" + i).shard(0).shards().get(0).state() == STARTED) { numberOfStartedShards++; } else if (routingTable.index("test" + i).shard(0).shards().get(0).state() == RELOCATING) { numberOfRelocatingShards++; } assertThat(routingTable.index("test" + i).shard(0).shards().get(0).primary(), equalTo(true)); // make sure we still have 2 shards either relocating or started on the first 25 nodes (still) String nodeId = routingTable.index("test" + i).shard(0).shards().get(0).currentNodeId(); int nodeIndex = Integer.parseInt(nodeId.substring("node".length())); assertThat(nodeIndex, lessThan(25)); } assertThat(numberOfRelocatingShards, equalTo(25)); assertThat(numberOfStartedShards, equalTo(25)); }