You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by il...@apache.org on 2020/11/24 18:08:11 UTC
[lucene-solr] branch jira/solr-15004 updated: Reformat to correct
tab length (+ some other IntelliJ magic)
This is an automated email from the ASF dual-hosted git repository.
ilan pushed a commit to branch jira/solr-15004
in repository https://gitbox.apache.org/repos/asf/lucene-solr.git
The following commit(s) were added to refs/heads/jira/solr-15004 by this push:
new 8b06bbb Reformat to correct tab length (+ some other IntelliJ magic)
8b06bbb is described below
commit 8b06bbbd35c4dd8049a9a59a221a8098047b2551
Author: Ilan Ginzburg <ig...@salesforce.com>
AuthorDate: Tue Nov 24 19:05:55 2020 +0100
Reformat to correct tab length (+ some other IntelliJ magic)
---
.../impl/AffinityPlacementFactoryTest.java | 610 ++++++++++-----------
.../placement/impl/AttributeFetcherForTest.java | 130 ++---
.../solr/cluster/placement/impl/Builders.java | 516 ++++++++---------
.../placement/impl/ClusterAbstractionsForTest.java | 600 ++++++++++----------
.../cluster/placement/impl/PluginTestHelper.java | 116 ++--
5 files changed, 996 insertions(+), 976 deletions(-)
diff --git a/solr/core/src/test/org/apache/solr/cluster/placement/impl/AffinityPlacementFactoryTest.java b/solr/core/src/test/org/apache/solr/cluster/placement/impl/AffinityPlacementFactoryTest.java
index 5a6911e..3981b09 100644
--- a/solr/core/src/test/org/apache/solr/cluster/placement/impl/AffinityPlacementFactoryTest.java
+++ b/solr/core/src/test/org/apache/solr/cluster/placement/impl/AffinityPlacementFactoryTest.java
@@ -41,332 +41,332 @@ import java.util.stream.StreamSupport;
* Unit test for {@link AffinityPlacementFactory}
*/
public class AffinityPlacementFactoryTest extends Assert {
- private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
-
- private static PlacementPlugin plugin;
-
- @BeforeClass
- public static void setupPlugin() {
- PlacementPluginConfig config = PlacementPluginConfigImpl.createConfigFromProperties(
- Map.of("minimalFreeDiskGB", 10L, "deprioritizedFreeDiskGB", 50L));
- plugin = new AffinityPlacementFactory().createPluginInstance(config);
- }
-
- @Test
- public void testBasicPlacementNewCollection() throws Exception {
- testBasicPlacementInternal(false);
- }
-
- @Test
- public void testBasicPlacementExistingCollection() throws Exception {
- testBasicPlacementInternal(true);
+ private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+
+ private static PlacementPlugin plugin;
+
+ @BeforeClass
+ public static void setupPlugin() {
+ PlacementPluginConfig config = PlacementPluginConfigImpl.createConfigFromProperties(
+ Map.of("minimalFreeDiskGB", 10L, "deprioritizedFreeDiskGB", 50L));
+ plugin = new AffinityPlacementFactory().createPluginInstance(config);
+ }
+
+ @Test
+ public void testBasicPlacementNewCollection() throws Exception {
+ testBasicPlacementInternal(false);
+ }
+
+ @Test
+ public void testBasicPlacementExistingCollection() throws Exception {
+ testBasicPlacementInternal(true);
+ }
+
+ @Test
+ public void testBasicPlacementNewCollection2() throws Exception {
+ testBasicInternal2(false);
+ }
+
+ @Test
+ public void testBasicPlacementExistingCollection2() throws Exception {
+ testBasicInternal2(true);
+ }
+
+ private void testBasicInternal2(boolean hasExistingCollection) throws Exception {
+ String collectionName = "testCollection";
+
+ Builders.ClusterBuilder clusterBuilder = Builders.newClusterBuilder().initializeNodes(2);
+ LinkedList<Builders.NodeBuilder> nodeBuilders = clusterBuilder.getNodeBuilders();
+ nodeBuilders.get(0).setCoreCount(1).setFreeDiskGB(100L);
+ nodeBuilders.get(1).setCoreCount(10).setFreeDiskGB(100L);
+
+ Builders.CollectionBuilder collectionBuilder = Builders.newCollectionBuilder(collectionName);
+
+ if (hasExistingCollection) {
+ // Existing collection has replicas for its shards and is visible in the cluster state
+ collectionBuilder.initializeShardsReplicas(1, 1, 0, 0, nodeBuilders);
+ clusterBuilder.addCollection(collectionBuilder);
+ } else {
+ // New collection to create has the shards defined but no replicas and is not present in cluster state
+ collectionBuilder.initializeShardsReplicas(1, 0, 0, 0, List.of());
}
- @Test
- public void testBasicPlacementNewCollection2() throws Exception {
- testBasicInternal2(false);
+ Cluster cluster = clusterBuilder.build();
+ AttributeFetcher attributeFetcher = clusterBuilder.buildAttributeFetcher();
+
+ SolrCollection solrCollection = collectionBuilder.build();
+ List<Node> liveNodes = clusterBuilder.buildLiveNodes();
+
+ // Place a new replica for the (only) existing shard of the collection
+ PlacementRequestImpl placementRequest = new PlacementRequestImpl(solrCollection,
+ Set.of(solrCollection.shards().iterator().next().getShardName()), new HashSet<>(liveNodes),
+ 1, 0, 0);
+
+ PlacementPlan pp = plugin.computePlacement(cluster, placementRequest, attributeFetcher, new PlacementPlanFactoryImpl());
+
+ assertEquals(1, pp.getReplicaPlacements().size());
+ ReplicaPlacement rp = pp.getReplicaPlacements().iterator().next();
+ assertEquals(hasExistingCollection ? liveNodes.get(1) : liveNodes.get(0), rp.getNode());
+ }
+
+ /**
+ * When this test places a replica for a new collection, it should pick the node with less cores.<p>
+ * <p>
+ * When it places a replica for an existing collection, it should pick the node with more cores that doesn't already have a replica for the shard.
+ */
+ private void testBasicPlacementInternal(boolean hasExistingCollection) throws Exception {
+ String collectionName = "testCollection";
+
+ Node node1 = new ClusterAbstractionsForTest.NodeImpl("node1");
+ Node node2 = new ClusterAbstractionsForTest.NodeImpl("node2");
+ Set<Node> liveNodes = Set.of(node1, node2);
+
+ ClusterAbstractionsForTest.SolrCollectionImpl solrCollection;
+ // Make sure new collections are not visible in the cluster state and existing ones are
+ final Map<String, SolrCollection> clusterCollections;
+ if (hasExistingCollection) {
+ // An existing collection with a single replica on node 1. Note that new collections already exist by the time the plugin is called, but are empty
+ solrCollection = PluginTestHelper.createCollection(collectionName, Map.of(), 1, 1, 0, 0, Set.of(node1));
+ clusterCollections = Map.of(solrCollection.getName(), solrCollection);
+ } else {
+ // A new collection has the shards defined ok but no replicas
+ solrCollection = PluginTestHelper.createCollection(collectionName, Map.of(), 1, 0, 0, 0, Set.of());
+ clusterCollections = Map.of();
}
- @Test
- public void testBasicPlacementExistingCollection2() throws Exception {
- testBasicInternal2(true);
+ Cluster cluster = new ClusterAbstractionsForTest.ClusterImpl(liveNodes, clusterCollections);
+ // Place a new replica for the (only) existing shard of the collection
+ PlacementRequestImpl placementRequest = new PlacementRequestImpl(solrCollection, Set.of(solrCollection.shards().iterator().next().getShardName()), liveNodes, 1, 0, 0);
+ // More cores on node2
+ Map<Node, Integer> nodeToCoreCount = Map.of(node1, 1, node2, 10);
+ // A lot of free disk on the two nodes
+ final Map<Node, Long> nodeToFreeDisk = Map.of(node1, 100L, node2, 100L);
+ AttributeValues attributeValues = new AttributeValuesImpl(nodeToCoreCount, Map.of(), nodeToFreeDisk, Map.of(), Map.of(), Map.of(), Map.of(), Map.of());
+ AttributeFetcher attributeFetcher = new AttributeFetcherForTest(attributeValues);
+ PlacementPlanFactory placementPlanFactory = new PlacementPlanFactoryImpl();
+
+ PlacementPlan pp = plugin.computePlacement(cluster, placementRequest, attributeFetcher, placementPlanFactory);
+
+
+ assertEquals(1, pp.getReplicaPlacements().size());
+ ReplicaPlacement rp = pp.getReplicaPlacements().iterator().next();
+ assertEquals(hasExistingCollection ? node2 : node1, rp.getNode());
+ }
+
+ @Test
+ public void testAvailabilityZones() throws Exception {
+ String collectionName = "testCollection";
+ int NUM_NODES = 6;
+ Builders.ClusterBuilder clusterBuilder = Builders.newClusterBuilder().initializeNodes(NUM_NODES);
+ for (int i = 0; i < NUM_NODES; i++) {
+ Builders.NodeBuilder nodeBuilder = clusterBuilder.getNodeBuilders().get(i);
+ nodeBuilder.setCoreCount(0);
+ nodeBuilder.setFreeDiskGB(100L);
+ if (i < NUM_NODES / 2) {
+ nodeBuilder.setSysprop(AffinityPlacementFactory.AVAILABILITY_ZONE_SYSPROP, "az1");
+ } else {
+ nodeBuilder.setSysprop(AffinityPlacementFactory.AVAILABILITY_ZONE_SYSPROP, "az2");
+ }
}
- private void testBasicInternal2(boolean hasExistingCollection) throws Exception {
- String collectionName = "testCollection";
-
- Builders.ClusterBuilder clusterBuilder = Builders.newClusterBuilder().initializeNodes(2);
- LinkedList<Builders.NodeBuilder> nodeBuilders = clusterBuilder.getNodeBuilders();
- nodeBuilders.get(0).setCoreCount(1).setFreeDiskGB(100L);
- nodeBuilders.get(1).setCoreCount(10).setFreeDiskGB(100L);
-
- Builders.CollectionBuilder collectionBuilder = Builders.newCollectionBuilder(collectionName);
-
- if (hasExistingCollection) {
- // Existing collection has replicas for its shards and is visible in the cluster state
- collectionBuilder.initializeShardsReplicas(1, 1, 0, 0, nodeBuilders);
- clusterBuilder.addCollection(collectionBuilder);
- } else {
- // New collection to create has the shards defined but no replicas and is not present in cluster state
- collectionBuilder.initializeShardsReplicas(1, 0, 0, 0, List.of());
- }
-
- Cluster cluster = clusterBuilder.build();
- AttributeFetcher attributeFetcher = clusterBuilder.buildAttributeFetcher();
-
- SolrCollection solrCollection = collectionBuilder.build();
- List<Node> liveNodes = clusterBuilder.buildLiveNodes();
+ Builders.CollectionBuilder collectionBuilder = Builders.newCollectionBuilder(collectionName);
+ collectionBuilder.initializeShardsReplicas(2, 0, 0, 0, clusterBuilder.getNodeBuilders());
+ clusterBuilder.addCollection(collectionBuilder);
- // Place a new replica for the (only) existing shard of the collection
- PlacementRequestImpl placementRequest = new PlacementRequestImpl(solrCollection,
- Set.of(solrCollection.shards().iterator().next().getShardName()), new HashSet<>(liveNodes),
- 1, 0, 0);
+ Cluster cluster = clusterBuilder.build();
- PlacementPlan pp = plugin.computePlacement(cluster, placementRequest, attributeFetcher, new PlacementPlanFactoryImpl());
+ SolrCollection solrCollection = cluster.getCollection(collectionName);
- assertEquals(1, pp.getReplicaPlacements().size());
- ReplicaPlacement rp = pp.getReplicaPlacements().iterator().next();
- assertEquals(hasExistingCollection ? liveNodes.get(1) : liveNodes.get(0), rp.getNode());
- }
-
- /**
- * When this test places a replica for a new collection, it should pick the node with less cores.<p>
- *
- * When it places a replica for an existing collection, it should pick the node with more cores that doesn't already have a replica for the shard.
- */
- private void testBasicPlacementInternal(boolean hasExistingCollection) throws Exception {
- String collectionName = "testCollection";
-
- Node node1 = new ClusterAbstractionsForTest.NodeImpl("node1");
- Node node2 = new ClusterAbstractionsForTest.NodeImpl("node2");
- Set<Node> liveNodes = Set.of(node1, node2);
-
- ClusterAbstractionsForTest.SolrCollectionImpl solrCollection;
- // Make sure new collections are not visible in the cluster state and existing ones are
- final Map<String, SolrCollection> clusterCollections;
- if (hasExistingCollection) {
- // An existing collection with a single replica on node 1. Note that new collections already exist by the time the plugin is called, but are empty
- solrCollection = PluginTestHelper.createCollection(collectionName, Map.of(), 1, 1, 0, 0, Set.of(node1));
- clusterCollections = Map.of(solrCollection.getName(), solrCollection);
- } else {
- // A new collection has the shards defined ok but no replicas
- solrCollection = PluginTestHelper.createCollection(collectionName, Map.of(), 1, 0, 0, 0, Set.of());
- clusterCollections = Map.of();
- }
-
- Cluster cluster = new ClusterAbstractionsForTest.ClusterImpl(liveNodes, clusterCollections);
- // Place a new replica for the (only) existing shard of the collection
- PlacementRequestImpl placementRequest = new PlacementRequestImpl(solrCollection, Set.of(solrCollection.shards().iterator().next().getShardName()), liveNodes, 1, 0, 0);
- // More cores on node2
- Map<Node, Integer> nodeToCoreCount = Map.of(node1, 1, node2, 10);
- // A lot of free disk on the two nodes
- final Map<Node, Long> nodeToFreeDisk = Map.of(node1, 100L, node2, 100L);
- AttributeValues attributeValues = new AttributeValuesImpl(nodeToCoreCount, Map.of(), nodeToFreeDisk, Map.of(), Map.of(), Map.of(), Map.of(), Map.of());
- AttributeFetcher attributeFetcher = new AttributeFetcherForTest(attributeValues);
- PlacementPlanFactory placementPlanFactory = new PlacementPlanFactoryImpl();
-
- PlacementPlan pp = plugin.computePlacement(cluster, placementRequest, attributeFetcher, placementPlanFactory);
-
-
- assertEquals(1, pp.getReplicaPlacements().size());
- ReplicaPlacement rp = pp.getReplicaPlacements().iterator().next();
- assertEquals(hasExistingCollection ? node2 : node1, rp.getNode());
- }
+ PlacementRequestImpl placementRequest = new PlacementRequestImpl(solrCollection,
+ StreamSupport.stream(solrCollection.shards().spliterator(), false)
+ .map(Shard::getShardName).collect(Collectors.toSet()),
+ cluster.getLiveNodes(), 2, 2, 2);
- @Test
- public void testAvailabilityZones() throws Exception {
- String collectionName = "testCollection";
- int NUM_NODES = 6;
- Builders.ClusterBuilder clusterBuilder = Builders.newClusterBuilder().initializeNodes(NUM_NODES);
- for (int i = 0; i < NUM_NODES; i++) {
- Builders.NodeBuilder nodeBuilder = clusterBuilder.getNodeBuilders().get(i);
- nodeBuilder.setCoreCount(0);
- nodeBuilder.setFreeDiskGB(100L);
- if (i < NUM_NODES / 2) {
- nodeBuilder.setSysprop(AffinityPlacementFactory.AVAILABILITY_ZONE_SYSPROP, "az1");
- } else {
- nodeBuilder.setSysprop(AffinityPlacementFactory.AVAILABILITY_ZONE_SYSPROP, "az2");
- }
- }
-
- Builders.CollectionBuilder collectionBuilder = Builders.newCollectionBuilder(collectionName);
- collectionBuilder.initializeShardsReplicas(2, 0, 0, 0, clusterBuilder.getNodeBuilders());
- clusterBuilder.addCollection(collectionBuilder);
-
- Cluster cluster = clusterBuilder.build();
-
- SolrCollection solrCollection = cluster.getCollection(collectionName);
-
- PlacementRequestImpl placementRequest = new PlacementRequestImpl(solrCollection,
- StreamSupport.stream(solrCollection.shards().spliterator(), false)
- .map(Shard::getShardName).collect(Collectors.toSet()),
- cluster.getLiveNodes(), 2, 2, 2);
-
- PlacementPlanFactory placementPlanFactory = new PlacementPlanFactoryImpl();
- AttributeFetcher attributeFetcher = clusterBuilder.buildAttributeFetcher();
- PlacementPlan pp = plugin.computePlacement(cluster, placementRequest, attributeFetcher, placementPlanFactory);
- // 2 shards, 6 replicas
- assertEquals(12, pp.getReplicaPlacements().size());
+ PlacementPlanFactory placementPlanFactory = new PlacementPlanFactoryImpl();
+ AttributeFetcher attributeFetcher = clusterBuilder.buildAttributeFetcher();
+ PlacementPlan pp = plugin.computePlacement(cluster, placementRequest, attributeFetcher, placementPlanFactory);
+ // 2 shards, 6 replicas
+ assertEquals(12, pp.getReplicaPlacements().size());
// List<ReplicaPlacement> placements = new ArrayList<>(pp.getReplicaPlacements());
// Collections.sort(placements, Comparator
// .comparing((ReplicaPlacement p) -> p.getNode().getName())
// .thenComparing((ReplicaPlacement p) -> p.getShardName())
// .thenComparing((ReplicaPlacement p) -> p.getReplicaType())
// );
- // shard -> AZ -> replica count
- Map<Replica.ReplicaType, Map<String, Map<String, AtomicInteger>>> replicas = new HashMap<>();
- AttributeValues attributeValues = attributeFetcher.fetchAttributes();
- for (ReplicaPlacement rp : pp.getReplicaPlacements()) {
- Optional<String> azOptional = attributeValues.getSystemProperty(rp.getNode(), AffinityPlacementFactory.AVAILABILITY_ZONE_SYSPROP);
- if (!azOptional.isPresent()) {
- fail("missing AZ sysprop for node " + rp.getNode());
- }
- String az = azOptional.get();
- replicas.computeIfAbsent(rp.getReplicaType(), type -> new HashMap<>())
- .computeIfAbsent(rp.getShardName(), shard -> new HashMap<>())
- .computeIfAbsent(az, zone -> new AtomicInteger()).incrementAndGet();
- }
- replicas.forEach((type, perTypeReplicas) -> {
- perTypeReplicas.forEach((shard, azCounts) -> {
- assertEquals("number of AZs", 2, azCounts.size());
- azCounts.forEach((az, count) -> {
- assertTrue("too few replicas shard=" + shard + ", type=" + type + ", az=" + az,
- count.get() >= 1);
- });
- });
- });
+ // shard -> AZ -> replica count
+ Map<Replica.ReplicaType, Map<String, Map<String, AtomicInteger>>> replicas = new HashMap<>();
+ AttributeValues attributeValues = attributeFetcher.fetchAttributes();
+ for (ReplicaPlacement rp : pp.getReplicaPlacements()) {
+ Optional<String> azOptional = attributeValues.getSystemProperty(rp.getNode(), AffinityPlacementFactory.AVAILABILITY_ZONE_SYSPROP);
+ if (!azOptional.isPresent()) {
+ fail("missing AZ sysprop for node " + rp.getNode());
+ }
+ String az = azOptional.get();
+ replicas.computeIfAbsent(rp.getReplicaType(), type -> new HashMap<>())
+ .computeIfAbsent(rp.getShardName(), shard -> new HashMap<>())
+ .computeIfAbsent(az, zone -> new AtomicInteger()).incrementAndGet();
}
-
- @Test
- public void testReplicaType() throws Exception {
- String collectionName = "testCollection";
- int NUM_NODES = 6;
- Builders.ClusterBuilder clusterBuilder = Builders.newClusterBuilder().initializeNodes(NUM_NODES);
- for (int i = 0; i < NUM_NODES; i++) {
- Builders.NodeBuilder nodeBuilder = clusterBuilder.getNodeBuilders().get(i);
- nodeBuilder.setCoreCount(0);
- nodeBuilder.setFreeDiskGB(100L);
- if (i < NUM_NODES / 2) {
- nodeBuilder.setSysprop(AffinityPlacementFactory.REPLICA_TYPE_SYSPROP, "Nrt,Tlog");
- nodeBuilder.setSysprop("group", "one");
- } else {
- nodeBuilder.setSysprop(AffinityPlacementFactory.REPLICA_TYPE_SYSPROP, "Pull, foobar");
- nodeBuilder.setSysprop("group", "two");
- }
- }
-
- Builders.CollectionBuilder collectionBuilder = Builders.newCollectionBuilder(collectionName);
- collectionBuilder.initializeShardsReplicas(2, 0, 0, 0, clusterBuilder.getNodeBuilders());
- clusterBuilder.addCollection(collectionBuilder);
-
- Cluster cluster = clusterBuilder.build();
-
- SolrCollection solrCollection = cluster.getCollection(collectionName);
-
- PlacementRequestImpl placementRequest = new PlacementRequestImpl(solrCollection,
- StreamSupport.stream(solrCollection.shards().spliterator(), false)
- .map(Shard::getShardName).collect(Collectors.toSet()),
- cluster.getLiveNodes(), 2, 2, 2);
-
- PlacementPlanFactory placementPlanFactory = new PlacementPlanFactoryImpl();
- AttributeFetcher attributeFetcher = clusterBuilder.buildAttributeFetcher();
- PlacementPlan pp = plugin.computePlacement(cluster, placementRequest, attributeFetcher, placementPlanFactory);
- // 2 shards, 6 replicas
- assertEquals(12, pp.getReplicaPlacements().size());
- // shard -> group -> replica count
- Map<Replica.ReplicaType, Map<String, Map<String, AtomicInteger>>> replicas = new HashMap<>();
- AttributeValues attributeValues = attributeFetcher.fetchAttributes();
- for (ReplicaPlacement rp : pp.getReplicaPlacements()) {
- Optional<String> groupOptional = attributeValues.getSystemProperty(rp.getNode(), "group");
- if (!groupOptional.isPresent()) {
- fail("missing group sysprop for node " + rp.getNode());
- }
- String group = groupOptional.get();
- if (group.equals("one")) {
- assertTrue("wrong replica type in group one",
- (rp.getReplicaType() == Replica.ReplicaType.NRT) || rp.getReplicaType() == Replica.ReplicaType.TLOG);
- } else {
- assertEquals("wrong replica type in group two", Replica.ReplicaType.PULL, rp.getReplicaType());
- }
- replicas.computeIfAbsent(rp.getReplicaType(), type -> new HashMap<>())
- .computeIfAbsent(rp.getShardName(), shard -> new HashMap<>())
- .computeIfAbsent(group, g -> new AtomicInteger()).incrementAndGet();
- }
- replicas.forEach((type, perTypeReplicas) -> {
- perTypeReplicas.forEach((shard, groupCounts) -> {
- assertEquals("number of groups", 1, groupCounts.size());
- groupCounts.forEach((group, count) -> {
- assertTrue("too few replicas shard=" + shard + ", type=" + type + ", group=" + group,
- count.get() >= 1);
- });
- });
+ replicas.forEach((type, perTypeReplicas) -> {
+ perTypeReplicas.forEach((shard, azCounts) -> {
+ assertEquals("number of AZs", 2, azCounts.size());
+ azCounts.forEach((az, count) -> {
+ assertTrue("too few replicas shard=" + shard + ", type=" + type + ", az=" + az,
+ count.get() >= 1);
});
-
+ });
+ });
+ }
+
+ @Test
+ public void testReplicaType() throws Exception {
+ String collectionName = "testCollection";
+ int NUM_NODES = 6;
+ Builders.ClusterBuilder clusterBuilder = Builders.newClusterBuilder().initializeNodes(NUM_NODES);
+ for (int i = 0; i < NUM_NODES; i++) {
+ Builders.NodeBuilder nodeBuilder = clusterBuilder.getNodeBuilders().get(i);
+ nodeBuilder.setCoreCount(0);
+ nodeBuilder.setFreeDiskGB(100L);
+ if (i < NUM_NODES / 2) {
+ nodeBuilder.setSysprop(AffinityPlacementFactory.REPLICA_TYPE_SYSPROP, "Nrt,Tlog");
+ nodeBuilder.setSysprop("group", "one");
+ } else {
+ nodeBuilder.setSysprop(AffinityPlacementFactory.REPLICA_TYPE_SYSPROP, "Pull, foobar");
+ nodeBuilder.setSysprop("group", "two");
+ }
}
- @Test
- //@Ignore
- public void testScalability() throws Exception {
- log.info("==== numNodes ====");
- runTestScalability(1000, 100, 40, 40, 20);
- runTestScalability(2000, 100, 40, 40, 20);
- runTestScalability(5000, 100, 40, 40, 20);
- runTestScalability(10000, 100, 40, 40, 20);
- runTestScalability(20000, 100, 40, 40, 20);
- log.info("==== numShards ====");
- runTestScalability(5000, 100, 40, 40, 20);
- runTestScalability(5000, 200, 40, 40, 20);
- runTestScalability(5000, 500, 40, 40, 20);
- runTestScalability(5000, 1000, 40, 40, 20);
- runTestScalability(5000, 2000, 40, 40, 20);
- log.info("==== numReplicas ====");
- runTestScalability(5000, 100, 100, 0, 0);
- runTestScalability(5000, 100, 200, 0, 0);
- runTestScalability(5000, 100, 500, 0, 0);
- runTestScalability(5000, 100, 1000, 0, 0);
- runTestScalability(5000, 100, 2000, 0, 0);
+ Builders.CollectionBuilder collectionBuilder = Builders.newCollectionBuilder(collectionName);
+ collectionBuilder.initializeShardsReplicas(2, 0, 0, 0, clusterBuilder.getNodeBuilders());
+ clusterBuilder.addCollection(collectionBuilder);
+
+ Cluster cluster = clusterBuilder.build();
+
+ SolrCollection solrCollection = cluster.getCollection(collectionName);
+
+ PlacementRequestImpl placementRequest = new PlacementRequestImpl(solrCollection,
+ StreamSupport.stream(solrCollection.shards().spliterator(), false)
+ .map(Shard::getShardName).collect(Collectors.toSet()),
+ cluster.getLiveNodes(), 2, 2, 2);
+
+ PlacementPlanFactory placementPlanFactory = new PlacementPlanFactoryImpl();
+ AttributeFetcher attributeFetcher = clusterBuilder.buildAttributeFetcher();
+ PlacementPlan pp = plugin.computePlacement(cluster, placementRequest, attributeFetcher, placementPlanFactory);
+ // 2 shards, 6 replicas
+ assertEquals(12, pp.getReplicaPlacements().size());
+ // shard -> group -> replica count
+ Map<Replica.ReplicaType, Map<String, Map<String, AtomicInteger>>> replicas = new HashMap<>();
+ AttributeValues attributeValues = attributeFetcher.fetchAttributes();
+ for (ReplicaPlacement rp : pp.getReplicaPlacements()) {
+ Optional<String> groupOptional = attributeValues.getSystemProperty(rp.getNode(), "group");
+ if (!groupOptional.isPresent()) {
+ fail("missing group sysprop for node " + rp.getNode());
+ }
+ String group = groupOptional.get();
+ if (group.equals("one")) {
+ assertTrue("wrong replica type in group one",
+ (rp.getReplicaType() == Replica.ReplicaType.NRT) || rp.getReplicaType() == Replica.ReplicaType.TLOG);
+ } else {
+ assertEquals("wrong replica type in group two", Replica.ReplicaType.PULL, rp.getReplicaType());
+ }
+ replicas.computeIfAbsent(rp.getReplicaType(), type -> new HashMap<>())
+ .computeIfAbsent(rp.getShardName(), shard -> new HashMap<>())
+ .computeIfAbsent(group, g -> new AtomicInteger()).incrementAndGet();
}
-
- private void runTestScalability(int numNodes, int numShards,
- int nrtReplicas, int tlogReplicas,
- int pullReplicas) throws Exception {
-
- int REPLICAS_PER_SHARD = nrtReplicas + tlogReplicas + pullReplicas;
- int TOTAL_REPLICAS = numShards * REPLICAS_PER_SHARD;
-
- String collectionName = "testCollection";
-
- final Set<Node> liveNodes = new HashSet<>();
- final Map<Node, Long> nodeToFreeDisk = new HashMap<>();
- final Map<Node, Integer> nodeToCoreCount = new HashMap<>();
- for (int i = 0; i < numNodes; i++) {
- Node node = new ClusterAbstractionsForTest.NodeImpl("node_" + i);
- liveNodes.add(node);
- nodeToFreeDisk.put(node, Long.valueOf(numNodes));
- nodeToCoreCount.put(node, 0);
- }
- ClusterAbstractionsForTest.SolrCollectionImpl solrCollection =
- PluginTestHelper.createCollection(collectionName, Map.of(), numShards, 0, 0, 0, Set.of());
-
- Cluster cluster = new ClusterAbstractionsForTest.ClusterImpl(liveNodes, Map.of());
- PlacementRequestImpl placementRequest = new PlacementRequestImpl(solrCollection,
- // XXX awkward!
- // StreamSupport.stream(solrCollection.shards().spliterator(), false)
- // .map(Shard::getShardName).collect(Collectors.toSet()),
- solrCollection.getShardNames(),
- liveNodes, nrtReplicas, tlogReplicas, pullReplicas);
-
- AttributeValues attributeValues = new AttributeValuesImpl(nodeToCoreCount, Map.of(), nodeToFreeDisk, Map.of(), Map.of(), Map.of(), Map.of(), Map.of());
- AttributeFetcher attributeFetcher = new AttributeFetcherForTest(attributeValues);
- PlacementPlanFactory placementPlanFactory = new PlacementPlanFactoryImpl();
-
- long start = System.nanoTime();
- PlacementPlan pp = plugin.computePlacement(cluster, placementRequest, attributeFetcher, placementPlanFactory);
- long end = System.nanoTime();
- log.info("ComputePlacement: {} nodes, {} shards, {} total replicas, elapsed time {} ms.", numNodes, numShards, TOTAL_REPLICAS, TimeUnit.NANOSECONDS.toMillis(end - start)); //nowarn
- assertEquals("incorrect number of calculated placements", TOTAL_REPLICAS,
- pp.getReplicaPlacements().size());
- // check that replicas are correctly placed
- Map<Node, AtomicInteger> replicasPerNode = new HashMap<>();
- Map<Node, Set<String>> shardsPerNode = new HashMap<>();
- Map<String, AtomicInteger> replicasPerShard = new HashMap<>();
- Map<Replica.ReplicaType, AtomicInteger> replicasByType = new HashMap<>();
- for (ReplicaPlacement placement : pp.getReplicaPlacements()) {
- replicasPerNode.computeIfAbsent(placement.getNode(), n -> new AtomicInteger()).incrementAndGet();
- shardsPerNode.computeIfAbsent(placement.getNode(), n -> new HashSet<>()).add(placement.getShardName());
- replicasByType.computeIfAbsent(placement.getReplicaType(), t -> new AtomicInteger()).incrementAndGet();
- replicasPerShard.computeIfAbsent(placement.getShardName(), s -> new AtomicInteger()).incrementAndGet();
- }
- int perNode = TOTAL_REPLICAS > numNodes ? TOTAL_REPLICAS / numNodes : 1;
- replicasPerNode.forEach((node, count) -> {
- assertEquals(count.get(), perNode);
- });
- shardsPerNode.forEach((node, names) -> {
- assertEquals(names.size(), perNode);
- });
-
- replicasPerShard.forEach((shard, count) -> {
- assertEquals(count.get(), REPLICAS_PER_SHARD);
+ replicas.forEach((type, perTypeReplicas) -> {
+ perTypeReplicas.forEach((shard, groupCounts) -> {
+ assertEquals("number of groups", 1, groupCounts.size());
+ groupCounts.forEach((group, count) -> {
+ assertTrue("too few replicas shard=" + shard + ", type=" + type + ", group=" + group,
+ count.get() >= 1);
});
+ });
+ });
+
+ }
+
+ @Test
+ //@Ignore
+ public void testScalability() throws Exception {
+ log.info("==== numNodes ====");
+ runTestScalability(1000, 100, 40, 40, 20);
+ runTestScalability(2000, 100, 40, 40, 20);
+ runTestScalability(5000, 100, 40, 40, 20);
+ runTestScalability(10000, 100, 40, 40, 20);
+ runTestScalability(20000, 100, 40, 40, 20);
+ log.info("==== numShards ====");
+ runTestScalability(5000, 100, 40, 40, 20);
+ runTestScalability(5000, 200, 40, 40, 20);
+ runTestScalability(5000, 500, 40, 40, 20);
+ runTestScalability(5000, 1000, 40, 40, 20);
+ runTestScalability(5000, 2000, 40, 40, 20);
+ log.info("==== numReplicas ====");
+ runTestScalability(5000, 100, 100, 0, 0);
+ runTestScalability(5000, 100, 200, 0, 0);
+ runTestScalability(5000, 100, 500, 0, 0);
+ runTestScalability(5000, 100, 1000, 0, 0);
+ runTestScalability(5000, 100, 2000, 0, 0);
+ }
+
+ private void runTestScalability(int numNodes, int numShards,
+ int nrtReplicas, int tlogReplicas,
+ int pullReplicas) throws Exception {
+
+ int REPLICAS_PER_SHARD = nrtReplicas + tlogReplicas + pullReplicas;
+ int TOTAL_REPLICAS = numShards * REPLICAS_PER_SHARD;
+
+ String collectionName = "testCollection";
+
+ final Set<Node> liveNodes = new HashSet<>();
+ final Map<Node, Long> nodeToFreeDisk = new HashMap<>();
+ final Map<Node, Integer> nodeToCoreCount = new HashMap<>();
+ for (int i = 0; i < numNodes; i++) {
+ Node node = new ClusterAbstractionsForTest.NodeImpl("node_" + i);
+ liveNodes.add(node);
+ nodeToFreeDisk.put(node, Long.valueOf(numNodes));
+ nodeToCoreCount.put(node, 0);
+ }
+ ClusterAbstractionsForTest.SolrCollectionImpl solrCollection =
+ PluginTestHelper.createCollection(collectionName, Map.of(), numShards, 0, 0, 0, Set.of());
+
+ Cluster cluster = new ClusterAbstractionsForTest.ClusterImpl(liveNodes, Map.of());
+ PlacementRequestImpl placementRequest = new PlacementRequestImpl(solrCollection,
+ // XXX awkward!
+ // StreamSupport.stream(solrCollection.shards().spliterator(), false)
+ // .map(Shard::getShardName).collect(Collectors.toSet()),
+ solrCollection.getShardNames(),
+ liveNodes, nrtReplicas, tlogReplicas, pullReplicas);
+
+ AttributeValues attributeValues = new AttributeValuesImpl(nodeToCoreCount, Map.of(), nodeToFreeDisk, Map.of(), Map.of(), Map.of(), Map.of(), Map.of());
+ AttributeFetcher attributeFetcher = new AttributeFetcherForTest(attributeValues);
+ PlacementPlanFactory placementPlanFactory = new PlacementPlanFactoryImpl();
+
+ long start = System.nanoTime();
+ PlacementPlan pp = plugin.computePlacement(cluster, placementRequest, attributeFetcher, placementPlanFactory);
+ long end = System.nanoTime();
+ log.info("ComputePlacement: {} nodes, {} shards, {} total replicas, elapsed time {} ms.", numNodes, numShards, TOTAL_REPLICAS, TimeUnit.NANOSECONDS.toMillis(end - start)); //nowarn
+ assertEquals("incorrect number of calculated placements", TOTAL_REPLICAS,
+ pp.getReplicaPlacements().size());
+ // check that replicas are correctly placed
+ Map<Node, AtomicInteger> replicasPerNode = new HashMap<>();
+ Map<Node, Set<String>> shardsPerNode = new HashMap<>();
+ Map<String, AtomicInteger> replicasPerShard = new HashMap<>();
+ Map<Replica.ReplicaType, AtomicInteger> replicasByType = new HashMap<>();
+ for (ReplicaPlacement placement : pp.getReplicaPlacements()) {
+ replicasPerNode.computeIfAbsent(placement.getNode(), n -> new AtomicInteger()).incrementAndGet();
+ shardsPerNode.computeIfAbsent(placement.getNode(), n -> new HashSet<>()).add(placement.getShardName());
+ replicasByType.computeIfAbsent(placement.getReplicaType(), t -> new AtomicInteger()).incrementAndGet();
+ replicasPerShard.computeIfAbsent(placement.getShardName(), s -> new AtomicInteger()).incrementAndGet();
}
+ int perNode = TOTAL_REPLICAS > numNodes ? TOTAL_REPLICAS / numNodes : 1;
+ replicasPerNode.forEach((node, count) -> {
+ assertEquals(count.get(), perNode);
+ });
+ shardsPerNode.forEach((node, names) -> {
+ assertEquals(names.size(), perNode);
+ });
+
+ replicasPerShard.forEach((shard, count) -> {
+ assertEquals(count.get(), REPLICAS_PER_SHARD);
+ });
+ }
}
diff --git a/solr/core/src/test/org/apache/solr/cluster/placement/impl/AttributeFetcherForTest.java b/solr/core/src/test/org/apache/solr/cluster/placement/impl/AttributeFetcherForTest.java
index 58005f7..f053d1b 100644
--- a/solr/core/src/test/org/apache/solr/cluster/placement/impl/AttributeFetcherForTest.java
+++ b/solr/core/src/test/org/apache/solr/cluster/placement/impl/AttributeFetcherForTest.java
@@ -25,69 +25,69 @@ import java.util.Set;
public class AttributeFetcherForTest implements AttributeFetcher {
- private final AttributeValues attributeValues;
-
- AttributeFetcherForTest(AttributeValues attributeValues) {
- this.attributeValues = attributeValues;
- }
-
- @Override
- public AttributeFetcher requestNodeCoreCount() {
- return this;
- }
-
- @Override
- public AttributeFetcher requestNodeDiskType() {
- return this;
- }
-
- @Override
- public AttributeFetcher requestNodeFreeDisk() {
- return this;
- }
-
- @Override
- public AttributeFetcher requestNodeTotalDisk() {
- return this;
- }
-
- @Override
- public AttributeFetcher requestNodeHeapUsage() {
- return this;
- }
-
- @Override
- public AttributeFetcher requestNodeSystemLoadAverage() {
- return this;
- }
-
- @Override
- public AttributeFetcher requestNodeSystemProperty(String name) {
- return this;
- }
-
- @Override
- public AttributeFetcher requestNodeEnvironmentVariable(String name) {
- throw new UnsupportedOperationException("Not yet implemented...");
- }
-
- @Override
- public AttributeFetcher requestNodeMetric(String metricName, NodeMetricRegistry registry) {
- return this;
- }
-
- @Override
- public AttributeFetcher fetchFrom(Set<Node> nodes) {
- return this;
- }
-
- @Override
- public AttributeFetcher requestMetric(String scope, String metricName) {
- throw new UnsupportedOperationException("Not yet implemented...");
- }
-
- @Override
- public AttributeValues fetchAttributes() {
- return attributeValues;
- }
+ private final AttributeValues attributeValues;
+
+ AttributeFetcherForTest(AttributeValues attributeValues) {
+ this.attributeValues = attributeValues;
+ }
+
+ @Override
+ public AttributeFetcher requestNodeCoreCount() {
+ return this;
+ }
+
+ @Override
+ public AttributeFetcher requestNodeDiskType() {
+ return this;
+ }
+
+ @Override
+ public AttributeFetcher requestNodeFreeDisk() {
+ return this;
+ }
+
+ @Override
+ public AttributeFetcher requestNodeTotalDisk() {
+ return this;
+ }
+
+ @Override
+ public AttributeFetcher requestNodeHeapUsage() {
+ return this;
+ }
+
+ @Override
+ public AttributeFetcher requestNodeSystemLoadAverage() {
+ return this;
+ }
+
+ @Override
+ public AttributeFetcher requestNodeSystemProperty(String name) {
+ return this;
+ }
+
+ @Override
+ public AttributeFetcher requestNodeEnvironmentVariable(String name) {
+ throw new UnsupportedOperationException("Not yet implemented...");
+ }
+
+ @Override
+ public AttributeFetcher requestNodeMetric(String metricName, NodeMetricRegistry registry) {
+ return this;
+ }
+
+ @Override
+ public AttributeFetcher fetchFrom(Set<Node> nodes) {
+ return this;
+ }
+
+ @Override
+ public AttributeFetcher requestMetric(String scope, String metricName) {
+ throw new UnsupportedOperationException("Not yet implemented...");
+ }
+
+ @Override
+ public AttributeValues fetchAttributes() {
+ return attributeValues;
+ }
}
diff --git a/solr/core/src/test/org/apache/solr/cluster/placement/impl/Builders.java b/solr/core/src/test/org/apache/solr/cluster/placement/impl/Builders.java
index bbbbc0e..1d964b2 100644
--- a/solr/core/src/test/org/apache/solr/cluster/placement/impl/Builders.java
+++ b/solr/core/src/test/org/apache/solr/cluster/placement/impl/Builders.java
@@ -12,318 +12,318 @@ import java.util.*;
*/
public class Builders {
- public static ClusterBuilder newClusterBuilder() {
- return new ClusterBuilder();
+ public static ClusterBuilder newClusterBuilder() {
+ return new ClusterBuilder();
+ }
+
+ public static CollectionBuilder newCollectionBuilder(String collectionName) {
+ return new CollectionBuilder(collectionName);
+ }
+
+ static class ClusterBuilder {
+ private LinkedList<NodeBuilder> nodeBuilders = new LinkedList<>();
+ private LinkedList<CollectionBuilder> collectionBuilders = new LinkedList<>();
+
+ ClusterBuilder initializeNodes(int countNodes) {
+ nodeBuilders = new LinkedList<>();
+ for (int n = 0; n < countNodes; n++) {
+ nodeBuilders.add(new NodeBuilder().setNodeName("node" + n)); // Default name, can be changed
+ }
+ return this;
}
- public static CollectionBuilder newCollectionBuilder(String collectionName) {
- return new CollectionBuilder(collectionName);
+ LinkedList<NodeBuilder> getNodeBuilders() {
+ return nodeBuilders;
}
- static class ClusterBuilder {
- private LinkedList<NodeBuilder> nodeBuilders = new LinkedList<>();
- private LinkedList<CollectionBuilder> collectionBuilders = new LinkedList<>();
-
- ClusterBuilder initializeNodes(int countNodes) {
- nodeBuilders = new LinkedList<>();
- for (int n = 0; n < countNodes; n++) {
- nodeBuilders.add(new NodeBuilder().setNodeName("node" + n)); // Default name, can be changed
- }
- return this;
- }
+ ClusterBuilder addCollection(CollectionBuilder collectionBuilder) {
+ collectionBuilders.add(collectionBuilder);
+ return this;
+ }
- LinkedList<NodeBuilder> getNodeBuilders() {
- return nodeBuilders;
- }
+ Cluster build() {
+ // TODO if converting all tests to use builders change ClusterImpl ctor to use list of nodes
+ return new ClusterAbstractionsForTest.ClusterImpl(new HashSet<>(buildLiveNodes()), buildClusterCollections());
+ }
- ClusterBuilder addCollection(CollectionBuilder collectionBuilder) {
- collectionBuilders.add(collectionBuilder);
- return this;
- }
+ List<Node> buildLiveNodes() {
+ List<Node> liveNodes = new LinkedList<>();
+ for (NodeBuilder nodeBuilder : nodeBuilders) {
+ liveNodes.add(nodeBuilder.build());
+ }
- Cluster build() {
- // TODO if converting all tests to use builders change ClusterImpl ctor to use list of nodes
- return new ClusterAbstractionsForTest.ClusterImpl(new HashSet<>(buildLiveNodes()), buildClusterCollections());
- }
+ return liveNodes;
+ }
- List<Node> buildLiveNodes() {
- List<Node> liveNodes = new LinkedList<>();
- for (NodeBuilder nodeBuilder : nodeBuilders) {
- liveNodes.add(nodeBuilder.build());
- }
+ Map<String, SolrCollection> buildClusterCollections() {
+ Map<String, SolrCollection> clusterCollections = new LinkedHashMap<>();
+ for (CollectionBuilder collectionBuilder : collectionBuilders) {
+ SolrCollection solrCollection = collectionBuilder.build();
+ clusterCollections.put(solrCollection.getName(), solrCollection);
+ }
- return liveNodes;
- }
+ return clusterCollections;
+ }
- Map<String, SolrCollection> buildClusterCollections() {
- Map<String, SolrCollection> clusterCollections = new LinkedHashMap<>();
- for (CollectionBuilder collectionBuilder : collectionBuilders) {
- SolrCollection solrCollection = collectionBuilder.build();
- clusterCollections.put(solrCollection.getName(), solrCollection);
- }
+ AttributeFetcher buildAttributeFetcher() {
+ Map<Node, Integer> nodeToCoreCount = new HashMap<>();
+ Map<Node, Long> nodeToFreeDisk = new HashMap<>();
+ Map<String, Map<Node, String>> sysprops = new HashMap<>();
+ Map<String, Map<Node, Double>> metrics = new HashMap<>();
- return clusterCollections;
- }
+ // TODO And a few more missing and will be added...
- AttributeFetcher buildAttributeFetcher() {
- Map<Node, Integer> nodeToCoreCount = new HashMap<>();
- Map<Node, Long> nodeToFreeDisk = new HashMap<>();
- Map<String, Map<Node, String>> sysprops = new HashMap<>();
- Map<String, Map<Node, Double>> metrics = new HashMap<>();
-
- // TODO And a few more missing and will be added...
-
- // Slight redoing of work twice (building Node instances) but let's favor readability over tricks (I could think
- // of many) to reuse the nodes computed in build() or build the AttributeFetcher at the same time.
- for (NodeBuilder nodeBuilder : nodeBuilders) {
- Node node = nodeBuilder.build();
-
- if (nodeBuilder.getCoreCount() != null) {
- nodeToCoreCount.put(node, nodeBuilder.getCoreCount());
- }
- if (nodeBuilder.getFreeDiskGB() != null) {
- nodeToFreeDisk.put(node, nodeBuilder.getFreeDiskGB());
- }
- if (nodeBuilder.getSysprops() != null) {
- nodeBuilder.getSysprops().forEach((name, value) -> {
- sysprops.computeIfAbsent(name, n -> new HashMap<>())
- .put(node, value);
- });
- }
- if (nodeBuilder.getMetrics() != null) {
- nodeBuilder.getMetrics().forEach((name, value) -> {
- metrics.computeIfAbsent(name, n -> new HashMap<>())
- .put(node, value);
- });
- }
- }
+ // Slight redoing of work twice (building Node instances) but let's favor readability over tricks (I could think
+ // of many) to reuse the nodes computed in build() or build the AttributeFetcher at the same time.
+ for (NodeBuilder nodeBuilder : nodeBuilders) {
+ Node node = nodeBuilder.build();
- AttributeValues attributeValues = new AttributeValuesImpl(nodeToCoreCount, Map.of(), nodeToFreeDisk, Map.of(), Map.of(), Map.of(), sysprops, metrics);
- return new AttributeFetcherForTest(attributeValues);
+ if (nodeBuilder.getCoreCount() != null) {
+ nodeToCoreCount.put(node, nodeBuilder.getCoreCount());
+ }
+ if (nodeBuilder.getFreeDiskGB() != null) {
+ nodeToFreeDisk.put(node, nodeBuilder.getFreeDiskGB());
+ }
+ if (nodeBuilder.getSysprops() != null) {
+ nodeBuilder.getSysprops().forEach((name, value) -> {
+ sysprops.computeIfAbsent(name, n -> new HashMap<>())
+ .put(node, value);
+ });
+ }
+ if (nodeBuilder.getMetrics() != null) {
+ nodeBuilder.getMetrics().forEach((name, value) -> {
+ metrics.computeIfAbsent(name, n -> new HashMap<>())
+ .put(node, value);
+ });
}
+ }
+
+ AttributeValues attributeValues = new AttributeValuesImpl(nodeToCoreCount, Map.of(), nodeToFreeDisk, Map.of(), Map.of(), Map.of(), sysprops, metrics);
+ return new AttributeFetcherForTest(attributeValues);
}
+ }
- static class CollectionBuilder {
- private final String collectionName;
- private LinkedList<ShardBuilder> shardBuilders = new LinkedList<>();
- private Map<String, String> customProperties = new HashMap<>();
+ static class CollectionBuilder {
+ private final String collectionName;
+ private LinkedList<ShardBuilder> shardBuilders = new LinkedList<>();
+ private Map<String, String> customProperties = new HashMap<>();
- private CollectionBuilder(String collectionName) {
- this.collectionName = collectionName;
- }
+ private CollectionBuilder(String collectionName) {
+ this.collectionName = collectionName;
+ }
- private CollectionBuilder addCustomProperty(String name, String value) {
- customProperties.put(name, value);
- return this;
- }
+ private CollectionBuilder addCustomProperty(String name, String value) {
+ customProperties.put(name, value);
+ return this;
+ }
- /**
- * Initializes shard and replica builders for the collection based on passed parameters. Replicas are assigned round
- * robin to the nodes. The shard leader is the first NRT replica of each shard (or first TLOG is no NRT).
- * Shard and replica configuration can be modified afterwards, the returned builder hierarchy is a convenient starting point.
- */
- CollectionBuilder initializeShardsReplicas(int countShards, int countNrtReplicas, int countTlogReplicas,
- int countPullReplicas, List<NodeBuilder> nodes) {
- Iterator<NodeBuilder> nodeIterator = nodes.iterator();
-
- shardBuilders = new LinkedList<>();
-
- for (int s = 0; s < countShards; s++) {
- String shardName = "shard" + (s + 1);
-
- LinkedList<ReplicaBuilder> replicas = new LinkedList<>();
- ReplicaBuilder leader = null;
-
- // Iterate on requested counts, NRT then TLOG then PULL. Leader chosen as first NRT (or first TLOG if no NRT)
- List<Pair<Replica.ReplicaType, Integer>> replicaTypes = List.of(
- new Pair<>(Replica.ReplicaType.NRT, countNrtReplicas),
- new Pair<>(Replica.ReplicaType.TLOG, countTlogReplicas),
- new Pair<>(Replica.ReplicaType.PULL, countPullReplicas));
-
- for (Pair<Replica.ReplicaType, Integer> tc : replicaTypes) {
- Replica.ReplicaType type = tc.first();
- int count = tc.second();
- String replicaPrefix = collectionName + "_" + shardName + "_replica_" + type.getSuffixChar();
- for (int r = 0; r < count; r++) {
- String replicaName = replicaPrefix + r;
- String coreName = replicaName + "_c";
- if (!nodeIterator.hasNext()) {
- nodeIterator = nodes.iterator();
- }
- // If the nodes set is empty, this call will fail
- final NodeBuilder node = nodeIterator.next();
-
- ReplicaBuilder replicaBuilder = new ReplicaBuilder();
- replicaBuilder.setReplicaName(replicaName).setCoreName(coreName).setReplicaType(type)
- .setReplicaState(Replica.ReplicaState.ACTIVE).setReplicaNode(node);
- replicas.add(replicaBuilder);
-
- if (leader == null && type != Replica.ReplicaType.PULL) {
- leader = replicaBuilder;
- }
- }
- }
-
- ShardBuilder shardBuilder = new ShardBuilder();
- shardBuilder.setShardName(shardName).setReplicaBuilders(replicas).setLeader(leader);
- shardBuilders.add(shardBuilder);
+ /**
+ * Initializes shard and replica builders for the collection based on passed parameters. Replicas are assigned round
+ * robin to the nodes. The shard leader is the first NRT replica of each shard (or first TLOG is no NRT).
+ * Shard and replica configuration can be modified afterwards, the returned builder hierarchy is a convenient starting point.
+ */
+ CollectionBuilder initializeShardsReplicas(int countShards, int countNrtReplicas, int countTlogReplicas,
+ int countPullReplicas, List<NodeBuilder> nodes) {
+ Iterator<NodeBuilder> nodeIterator = nodes.iterator();
+
+ shardBuilders = new LinkedList<>();
+
+ for (int s = 0; s < countShards; s++) {
+ String shardName = "shard" + (s + 1);
+
+ LinkedList<ReplicaBuilder> replicas = new LinkedList<>();
+ ReplicaBuilder leader = null;
+
+ // Iterate on requested counts, NRT then TLOG then PULL. Leader chosen as first NRT (or first TLOG if no NRT)
+ List<Pair<Replica.ReplicaType, Integer>> replicaTypes = List.of(
+ new Pair<>(Replica.ReplicaType.NRT, countNrtReplicas),
+ new Pair<>(Replica.ReplicaType.TLOG, countTlogReplicas),
+ new Pair<>(Replica.ReplicaType.PULL, countPullReplicas));
+
+ for (Pair<Replica.ReplicaType, Integer> tc : replicaTypes) {
+ Replica.ReplicaType type = tc.first();
+ int count = tc.second();
+ String replicaPrefix = collectionName + "_" + shardName + "_replica_" + type.getSuffixChar();
+ for (int r = 0; r < count; r++) {
+ String replicaName = replicaPrefix + r;
+ String coreName = replicaName + "_c";
+ if (!nodeIterator.hasNext()) {
+ nodeIterator = nodes.iterator();
}
+ // If the nodes set is empty, this call will fail
+ final NodeBuilder node = nodeIterator.next();
- return this;
- }
-
- SolrCollection build() {
- ClusterAbstractionsForTest.SolrCollectionImpl solrCollection = new ClusterAbstractionsForTest.SolrCollectionImpl(collectionName, customProperties);
+ ReplicaBuilder replicaBuilder = new ReplicaBuilder();
+ replicaBuilder.setReplicaName(replicaName).setCoreName(coreName).setReplicaType(type)
+ .setReplicaState(Replica.ReplicaState.ACTIVE).setReplicaNode(node);
+ replicas.add(replicaBuilder);
- final LinkedHashMap<String, Shard> shards = new LinkedHashMap<>();
-
- for (ShardBuilder shardBuilder : shardBuilders) {
- Shard shard = shardBuilder.build(solrCollection);
- shards.put(shard.getShardName(), shard);
+ if (leader == null && type != Replica.ReplicaType.PULL) {
+ leader = replicaBuilder;
}
-
- solrCollection.setShards(shards);
- return solrCollection;
+ }
}
- }
- static class ShardBuilder {
- private String shardName;
- private LinkedList<ReplicaBuilder> replicaBuilders = new LinkedList<>();
- private ReplicaBuilder leaderReplicaBuilder;
+ ShardBuilder shardBuilder = new ShardBuilder();
+ shardBuilder.setShardName(shardName).setReplicaBuilders(replicas).setLeader(leader);
+ shardBuilders.add(shardBuilder);
+ }
- ShardBuilder setShardName(String shardName) {
- this.shardName = shardName;
- return this;
- }
+ return this;
+ }
- ShardBuilder setReplicaBuilders(LinkedList<ReplicaBuilder> replicaBuilders) {
- this.replicaBuilders = replicaBuilders;
- return this;
- }
+ SolrCollection build() {
+ ClusterAbstractionsForTest.SolrCollectionImpl solrCollection = new ClusterAbstractionsForTest.SolrCollectionImpl(collectionName, customProperties);
- ShardBuilder setLeader(ReplicaBuilder leaderReplicaBuilder) {
- this.leaderReplicaBuilder = leaderReplicaBuilder;
- return this;
- }
+ final LinkedHashMap<String, Shard> shards = new LinkedHashMap<>();
- Shard build(SolrCollection collection) {
- ClusterAbstractionsForTest.ShardImpl shard = new ClusterAbstractionsForTest.ShardImpl(shardName, collection, Shard.ShardState.ACTIVE);
+ for (ShardBuilder shardBuilder : shardBuilders) {
+ Shard shard = shardBuilder.build(solrCollection);
+ shards.put(shard.getShardName(), shard);
+ }
- final LinkedHashMap<String, Replica> replicas = new LinkedHashMap<>();
- Replica leader = null;
+ solrCollection.setShards(shards);
+ return solrCollection;
+ }
+ }
- for (ReplicaBuilder replicaBuilder : replicaBuilders) {
- Replica replica = replicaBuilder.build(shard);
- replicas.put(replica.getReplicaName(), replica);
+ static class ShardBuilder {
+ private String shardName;
+ private LinkedList<ReplicaBuilder> replicaBuilders = new LinkedList<>();
+ private ReplicaBuilder leaderReplicaBuilder;
- if (leaderReplicaBuilder == replicaBuilder) {
- leader = replica;
- }
- }
+ ShardBuilder setShardName(String shardName) {
+ this.shardName = shardName;
+ return this;
+ }
- shard.setReplicas(replicas, leader);
- return shard;
- }
+ ShardBuilder setReplicaBuilders(LinkedList<ReplicaBuilder> replicaBuilders) {
+ this.replicaBuilders = replicaBuilders;
+ return this;
}
- static class ReplicaBuilder {
- private String replicaName;
- private String coreName;
- private Replica.ReplicaType replicaType;
- private Replica.ReplicaState replicaState;
- private NodeBuilder replicaNode;
+ ShardBuilder setLeader(ReplicaBuilder leaderReplicaBuilder) {
+ this.leaderReplicaBuilder = leaderReplicaBuilder;
+ return this;
+ }
- ReplicaBuilder setReplicaName(String replicaName) {
- this.replicaName = replicaName;
- return this;
- }
+ Shard build(SolrCollection collection) {
+ ClusterAbstractionsForTest.ShardImpl shard = new ClusterAbstractionsForTest.ShardImpl(shardName, collection, Shard.ShardState.ACTIVE);
- ReplicaBuilder setCoreName(String coreName) {
- this.coreName = coreName;
- return this;
- }
+ final LinkedHashMap<String, Replica> replicas = new LinkedHashMap<>();
+ Replica leader = null;
- ReplicaBuilder setReplicaType(Replica.ReplicaType replicaType) {
- this.replicaType = replicaType;
- return this;
- }
+ for (ReplicaBuilder replicaBuilder : replicaBuilders) {
+ Replica replica = replicaBuilder.build(shard);
+ replicas.put(replica.getReplicaName(), replica);
- ReplicaBuilder setReplicaState(Replica.ReplicaState replicaState) {
- this.replicaState = replicaState;
- return this;
+ if (leaderReplicaBuilder == replicaBuilder) {
+ leader = replica;
}
+ }
- ReplicaBuilder setReplicaNode(NodeBuilder replicaNode) {
- this.replicaNode = replicaNode;
- return this;
- }
+ shard.setReplicas(replicas, leader);
+ return shard;
+ }
+ }
+
+ static class ReplicaBuilder {
+ private String replicaName;
+ private String coreName;
+ private Replica.ReplicaType replicaType;
+ private Replica.ReplicaState replicaState;
+ private NodeBuilder replicaNode;
+
+ ReplicaBuilder setReplicaName(String replicaName) {
+ this.replicaName = replicaName;
+ return this;
+ }
- Replica build(Shard shard) {
- return new ClusterAbstractionsForTest.ReplicaImpl(replicaName, coreName, shard, replicaType, replicaState, replicaNode.build());
- }
+ ReplicaBuilder setCoreName(String coreName) {
+ this.coreName = coreName;
+ return this;
}
- static class NodeBuilder {
- private String nodeName = null;
- private Integer coreCount = null;
- private Long freeDiskGB = null;
- private Map<String, String> sysprops = null;
- private Map<String, Double> metrics = null;
+ ReplicaBuilder setReplicaType(Replica.ReplicaType replicaType) {
+ this.replicaType = replicaType;
+ return this;
+ }
- NodeBuilder setNodeName(String nodeName) {
- this.nodeName = nodeName;
- return this;
- }
+ ReplicaBuilder setReplicaState(Replica.ReplicaState replicaState) {
+ this.replicaState = replicaState;
+ return this;
+ }
- NodeBuilder setCoreCount(Integer coreCount) {
- this.coreCount = coreCount;
- return this;
- }
+ ReplicaBuilder setReplicaNode(NodeBuilder replicaNode) {
+ this.replicaNode = replicaNode;
+ return this;
+ }
- NodeBuilder setFreeDiskGB(Long freeDiskGB) {
- this.freeDiskGB = freeDiskGB;
- return this;
- }
+ Replica build(Shard shard) {
+ return new ClusterAbstractionsForTest.ReplicaImpl(replicaName, coreName, shard, replicaType, replicaState, replicaNode.build());
+ }
+ }
+
+ static class NodeBuilder {
+ private String nodeName = null;
+ private Integer coreCount = null;
+ private Long freeDiskGB = null;
+ private Map<String, String> sysprops = null;
+ private Map<String, Double> metrics = null;
+
+ NodeBuilder setNodeName(String nodeName) {
+ this.nodeName = nodeName;
+ return this;
+ }
- NodeBuilder setSysprop(String key, String value) {
- if (sysprops == null) {
- sysprops = new HashMap<>();
- }
- String name = AttributeFetcherImpl.getSystemPropertySnitchTag(key);
- sysprops.put(name, value);
- return this;
- }
+ NodeBuilder setCoreCount(Integer coreCount) {
+ this.coreCount = coreCount;
+ return this;
+ }
- NodeBuilder setMetric(AttributeFetcher.NodeMetricRegistry registry, String key, Double value) {
- if (metrics == null) {
- metrics = new HashMap<>();
- }
- String name = AttributeFetcherImpl.getMetricSnitchTag(key, registry);
- metrics.put(name, value);
- return this;
- }
+ NodeBuilder setFreeDiskGB(Long freeDiskGB) {
+ this.freeDiskGB = freeDiskGB;
+ return this;
+ }
- Integer getCoreCount() {
- return coreCount;
- }
+ NodeBuilder setSysprop(String key, String value) {
+ if (sysprops == null) {
+ sysprops = new HashMap<>();
+ }
+ String name = AttributeFetcherImpl.getSystemPropertySnitchTag(key);
+ sysprops.put(name, value);
+ return this;
+ }
- Long getFreeDiskGB() {
- return freeDiskGB;
- }
+ NodeBuilder setMetric(AttributeFetcher.NodeMetricRegistry registry, String key, Double value) {
+ if (metrics == null) {
+ metrics = new HashMap<>();
+ }
+ String name = AttributeFetcherImpl.getMetricSnitchTag(key, registry);
+ metrics.put(name, value);
+ return this;
+ }
- Map<String, String> getSysprops() {
- return sysprops;
- }
+ Integer getCoreCount() {
+ return coreCount;
+ }
- Map<String, Double> getMetrics() {
- return metrics;
- }
+ Long getFreeDiskGB() {
+ return freeDiskGB;
+ }
- Node build() {
- // It is ok to build a new instance each time, that instance does the right thing with equals() and hashCode()
- return new ClusterAbstractionsForTest.NodeImpl(nodeName);
- }
+ Map<String, String> getSysprops() {
+ return sysprops;
+ }
+
+ Map<String, Double> getMetrics() {
+ return metrics;
+ }
+
+ Node build() {
+ // It is ok to build a new instance each time, that instance does the right thing with equals() and hashCode()
+ return new ClusterAbstractionsForTest.NodeImpl(nodeName);
}
+ }
}
diff --git a/solr/core/src/test/org/apache/solr/cluster/placement/impl/ClusterAbstractionsForTest.java b/solr/core/src/test/org/apache/solr/cluster/placement/impl/ClusterAbstractionsForTest.java
index da82240..bd14d0d 100644
--- a/solr/core/src/test/org/apache/solr/cluster/placement/impl/ClusterAbstractionsForTest.java
+++ b/solr/core/src/test/org/apache/solr/cluster/placement/impl/ClusterAbstractionsForTest.java
@@ -28,295 +28,315 @@ import java.util.stream.Collectors;
*/
class ClusterAbstractionsForTest {
- static class ClusterImpl implements Cluster {
- private final Set<Node> liveNodes = new HashSet<>();
- private final Map<String, SolrCollection> collections = new HashMap<>();
-
- ClusterImpl(Set<Node> liveNodes, Map<String, SolrCollection> collections) {
- this.liveNodes.addAll(liveNodes);
- this.collections.putAll(collections);
- }
-
- @Override
- public Set<Node> getLiveNodes() {
- return liveNodes;
- }
-
- @Override
- public SolrCollection getCollection(String collectionName) {
- return collections.get(collectionName);
- }
-
- @Override
- @Nonnull
- public Iterator<SolrCollection> iterator() {
- return collections.values().iterator();
- }
-
- @Override
- public Iterable<SolrCollection> collections() {
- return ClusterImpl.this::iterator;
- }
-
- // for unit tests
-
- ClusterImpl addNode(Node node) {
- liveNodes.add(node);
- return this;
- }
-
- ClusterImpl removeNode(Node node) {
- liveNodes.remove(node);
- return this;
- }
-
- ClusterImpl putCollection(SolrCollection collection) {
- collections.put(collection.getName(), collection);
- return this;
- }
-
- ClusterImpl removeCollection(String name) {
- collections.remove(name);
- return this;
- }
-
- ClusterImpl removeAllCollections() {
- collections.clear();
- return this;
- }
- }
-
-
- static class NodeImpl implements Node {
- public final String nodeName;
-
- /**
- * Transforms a collection of node names into a set of {@link Node} instances.
- */
- static Set<Node> getNodes(Collection<String> nodeNames) {
- return nodeNames.stream().map(NodeImpl::new).collect(Collectors.toSet());
- }
-
- NodeImpl(String nodeName) {
- this.nodeName = nodeName;
- }
-
- @Override
- public String getName() {
- return nodeName;
- }
-
- @Override
- public String toString() {
- return getClass().getSimpleName() + "(" + getName() + ")";
- }
-
- /**
- * This class ends up as a key in Maps in {@link org.apache.solr.cluster.placement.AttributeValues}.
- * It is important to implement this method comparing node names given that new instances of {@link Node} are created
- * with names equal to existing instances (See {@link Builders.NodeBuilder#build()}).
- */
- public boolean equals(Object obj) {
- if (obj == null) { return false; }
- if (obj == this) { return true; }
- if (obj.getClass() != getClass()) { return false; }
- NodeImpl other = (NodeImpl) obj;
- return Objects.equals(this.nodeName, other.nodeName);
- }
-
- public int hashCode() {
- return Objects.hashCode(nodeName);
- }
- }
-
-
- static class SolrCollectionImpl implements SolrCollection {
- private final String collectionName;
- /** Map from {@link Shard#getShardName()} to {@link Shard} */
- private Map<String, Shard> shards;
- private final Map<String, String> customProperties;
-
- SolrCollectionImpl(String collectionName, Map<String, String> customProperties) {
- this.collectionName = collectionName;
- this.customProperties = customProperties;
- }
-
- /**
- * Setting the shards has to happen (in tests) after creating the collection because shards reference the collection
- */
- void setShards(Map<String, Shard> shards) {
- this.shards = shards;
- }
-
- Set<String> getShardNames() {
- return shards.keySet();
- }
-
- @Override
- public String getName() {
- return collectionName;
- }
-
- @Override
- public Shard getShard(String name) {
- return shards.get(name);
- }
-
- @Override
- @Nonnull
- public Iterator<Shard> iterator() {
- return shards.values().iterator();
- }
-
- @Override
- public Iterable<Shard> shards() {
- return SolrCollectionImpl.this::iterator;
- }
-
- @Override
- public String getCustomProperty(String customPropertyName) {
- return customProperties.get(customPropertyName);
- }
- }
-
-
- static class ShardImpl implements Shard {
- private final String shardName;
- private final SolrCollection collection;
- private final ShardState shardState;
- private Map<String, Replica> replicas;
- private Replica leader;
-
- ShardImpl(String shardName, SolrCollection collection, ShardState shardState) {
- this.shardName = shardName;
- this.collection = collection;
- this.shardState = shardState;
- }
-
- /**
- * Setting the replicas has to happen (in tests) after creating the shard because replicas reference the shard
- */
- void setReplicas(Map<String, Replica> replicas, Replica leader) {
- this.replicas = replicas;
- this.leader = leader;
- }
-
- @Override
- public String getShardName() {
- return shardName;
- }
-
- @Override
- public SolrCollection getCollection() {
- return collection;
- }
-
- @Override
- public Replica getReplica(String name) {
- return replicas.get(name);
- }
-
- @Override
- @Nonnull
- public Iterator<Replica> iterator() {
- return replicas.values().iterator();
- }
-
- @Override
- public Iterable<Replica> replicas() {
- return ShardImpl.this::iterator;
- }
-
- @Override
- public Replica getLeader() {
- return leader;
- }
-
- @Override
- public ShardState getState() {
- return shardState;
- }
-
- public boolean equals(Object obj) {
- if (obj == null) { return false; }
- if (obj == this) { return true; }
- if (obj.getClass() != getClass()) { return false; }
- ShardImpl other = (ShardImpl) obj;
- return Objects.equals(this.shardName, other.shardName)
- && Objects.equals(this.collection, other.collection)
- && Objects.equals(this.shardState, other.shardState)
- && Objects.equals(this.replicas, other.replicas)
- && Objects.equals(this.leader, other.leader);
- }
-
- public int hashCode() {
- return Objects.hash(shardName, collection, shardState);
- }
- }
-
-
- static class ReplicaImpl implements Replica {
- private final String replicaName;
- private final String coreName;
- private final Shard shard;
- private final ReplicaType replicaType;
- private final ReplicaState replicaState;
- private final Node node;
-
- ReplicaImpl(String replicaName, String coreName, Shard shard, ReplicaType replicaType, ReplicaState replicaState, Node node) {
- this.replicaName = replicaName;
- this.coreName = coreName;
- this.shard = shard;
- this.replicaType = replicaType;
- this.replicaState = replicaState;
- this.node = node;
- }
-
- @Override
- public Shard getShard() {
- return shard;
- }
-
- @Override
- public ReplicaType getType() {
- return replicaType;
- }
-
- @Override
- public ReplicaState getState() {
- return replicaState;
- }
-
- @Override
- public String getReplicaName() {
- return replicaName;
- }
-
- @Override
- public String getCoreName() {
- return coreName;
- }
-
- @Override
- public Node getNode() {
- return node;
- }
-
- public boolean equals(Object obj) {
- if (obj == null) { return false; }
- if (obj == this) { return true; }
- if (obj.getClass() != getClass()) { return false; }
- ReplicaImpl other = (ReplicaImpl) obj;
- return Objects.equals(this.replicaName, other.replicaName)
- && Objects.equals(this.coreName, other.coreName)
- && Objects.equals(this.shard, other.shard)
- && Objects.equals(this.replicaType, other.replicaType)
- && Objects.equals(this.replicaState, other.replicaState)
- && Objects.equals(this.node, other.node);
- }
-
- public int hashCode() {
- return Objects.hash(replicaName, coreName, shard, replicaType, replicaState, node);
- }
+ static class ClusterImpl implements Cluster {
+ private final Set<Node> liveNodes = new HashSet<>();
+ private final Map<String, SolrCollection> collections = new HashMap<>();
+
+ ClusterImpl(Set<Node> liveNodes, Map<String, SolrCollection> collections) {
+ this.liveNodes.addAll(liveNodes);
+ this.collections.putAll(collections);
+ }
+
+ @Override
+ public Set<Node> getLiveNodes() {
+ return liveNodes;
+ }
+
+ @Override
+ public SolrCollection getCollection(String collectionName) {
+ return collections.get(collectionName);
+ }
+
+ @Override
+ @Nonnull
+ public Iterator<SolrCollection> iterator() {
+ return collections.values().iterator();
+ }
+
+ @Override
+ public Iterable<SolrCollection> collections() {
+ return ClusterImpl.this::iterator;
+ }
+
+ // for unit tests
+
+ ClusterImpl addNode(Node node) {
+ liveNodes.add(node);
+ return this;
+ }
+
+ ClusterImpl removeNode(Node node) {
+ liveNodes.remove(node);
+ return this;
+ }
+
+ ClusterImpl putCollection(SolrCollection collection) {
+ collections.put(collection.getName(), collection);
+ return this;
+ }
+
+ ClusterImpl removeCollection(String name) {
+ collections.remove(name);
+ return this;
+ }
+
+ ClusterImpl removeAllCollections() {
+ collections.clear();
+ return this;
+ }
+ }
+
+
+ static class NodeImpl implements Node {
+ public final String nodeName;
+
+ /**
+ * Transforms a collection of node names into a set of {@link Node} instances.
+ */
+ static Set<Node> getNodes(Collection<String> nodeNames) {
+ return nodeNames.stream().map(NodeImpl::new).collect(Collectors.toSet());
+ }
+
+ NodeImpl(String nodeName) {
+ this.nodeName = nodeName;
+ }
+
+ @Override
+ public String getName() {
+ return nodeName;
+ }
+
+ @Override
+ public String toString() {
+ return getClass().getSimpleName() + "(" + getName() + ")";
+ }
+
+ /**
+ * This class ends up as a key in Maps in {@link org.apache.solr.cluster.placement.AttributeValues}.
+ * It is important to implement this method comparing node names given that new instances of {@link Node} are created
+ * with names equal to existing instances (See {@link Builders.NodeBuilder#build()}).
+ */
+ public boolean equals(Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (obj == this) {
+ return true;
+ }
+ if (obj.getClass() != getClass()) {
+ return false;
+ }
+ NodeImpl other = (NodeImpl) obj;
+ return Objects.equals(this.nodeName, other.nodeName);
+ }
+
+ public int hashCode() {
+ return Objects.hashCode(nodeName);
+ }
+ }
+
+
+ static class SolrCollectionImpl implements SolrCollection {
+ private final String collectionName;
+ /**
+ * Map from {@link Shard#getShardName()} to {@link Shard}
+ */
+ private Map<String, Shard> shards;
+ private final Map<String, String> customProperties;
+
+ SolrCollectionImpl(String collectionName, Map<String, String> customProperties) {
+ this.collectionName = collectionName;
+ this.customProperties = customProperties;
+ }
+
+ /**
+ * Setting the shards has to happen (in tests) after creating the collection because shards reference the collection
+ */
+ void setShards(Map<String, Shard> shards) {
+ this.shards = shards;
+ }
+
+ Set<String> getShardNames() {
+ return shards.keySet();
+ }
+
+ @Override
+ public String getName() {
+ return collectionName;
+ }
+
+ @Override
+ public Shard getShard(String name) {
+ return shards.get(name);
+ }
+
+ @Override
+ @Nonnull
+ public Iterator<Shard> iterator() {
+ return shards.values().iterator();
+ }
+
+ @Override
+ public Iterable<Shard> shards() {
+ return SolrCollectionImpl.this::iterator;
+ }
+
+ @Override
+ public String getCustomProperty(String customPropertyName) {
+ return customProperties.get(customPropertyName);
+ }
+ }
+
+
+ static class ShardImpl implements Shard {
+ private final String shardName;
+ private final SolrCollection collection;
+ private final ShardState shardState;
+ private Map<String, Replica> replicas;
+ private Replica leader;
+
+ ShardImpl(String shardName, SolrCollection collection, ShardState shardState) {
+ this.shardName = shardName;
+ this.collection = collection;
+ this.shardState = shardState;
+ }
+
+ /**
+ * Setting the replicas has to happen (in tests) after creating the shard because replicas reference the shard
+ */
+ void setReplicas(Map<String, Replica> replicas, Replica leader) {
+ this.replicas = replicas;
+ this.leader = leader;
+ }
+
+ @Override
+ public String getShardName() {
+ return shardName;
+ }
+
+ @Override
+ public SolrCollection getCollection() {
+ return collection;
+ }
+
+ @Override
+ public Replica getReplica(String name) {
+ return replicas.get(name);
+ }
+
+ @Override
+ @Nonnull
+ public Iterator<Replica> iterator() {
+ return replicas.values().iterator();
+ }
+
+ @Override
+ public Iterable<Replica> replicas() {
+ return ShardImpl.this::iterator;
+ }
+
+ @Override
+ public Replica getLeader() {
+ return leader;
+ }
+
+ @Override
+ public ShardState getState() {
+ return shardState;
+ }
+
+ public boolean equals(Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (obj == this) {
+ return true;
+ }
+ if (obj.getClass() != getClass()) {
+ return false;
+ }
+ ShardImpl other = (ShardImpl) obj;
+ return Objects.equals(this.shardName, other.shardName)
+ && Objects.equals(this.collection, other.collection)
+ && Objects.equals(this.shardState, other.shardState)
+ && Objects.equals(this.replicas, other.replicas)
+ && Objects.equals(this.leader, other.leader);
+ }
+
+ public int hashCode() {
+ return Objects.hash(shardName, collection, shardState);
+ }
+ }
+
+
+ static class ReplicaImpl implements Replica {
+ private final String replicaName;
+ private final String coreName;
+ private final Shard shard;
+ private final ReplicaType replicaType;
+ private final ReplicaState replicaState;
+ private final Node node;
+
+ ReplicaImpl(String replicaName, String coreName, Shard shard, ReplicaType replicaType, ReplicaState replicaState, Node node) {
+ this.replicaName = replicaName;
+ this.coreName = coreName;
+ this.shard = shard;
+ this.replicaType = replicaType;
+ this.replicaState = replicaState;
+ this.node = node;
+ }
+
+ @Override
+ public Shard getShard() {
+ return shard;
+ }
+
+ @Override
+ public ReplicaType getType() {
+ return replicaType;
+ }
+
+ @Override
+ public ReplicaState getState() {
+ return replicaState;
+ }
+
+ @Override
+ public String getReplicaName() {
+ return replicaName;
+ }
+
+ @Override
+ public String getCoreName() {
+ return coreName;
+ }
+
+ @Override
+ public Node getNode() {
+ return node;
+ }
+
+ public boolean equals(Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (obj == this) {
+ return true;
+ }
+ if (obj.getClass() != getClass()) {
+ return false;
+ }
+ ReplicaImpl other = (ReplicaImpl) obj;
+ return Objects.equals(this.replicaName, other.replicaName)
+ && Objects.equals(this.coreName, other.coreName)
+ && Objects.equals(this.shard, other.shard)
+ && Objects.equals(this.replicaType, other.replicaType)
+ && Objects.equals(this.replicaState, other.replicaState)
+ && Objects.equals(this.node, other.node);
+ }
+
+ public int hashCode() {
+ return Objects.hash(replicaName, coreName, shard, replicaType, replicaState, node);
}
+ }
}
diff --git a/solr/core/src/test/org/apache/solr/cluster/placement/impl/PluginTestHelper.java b/solr/core/src/test/org/apache/solr/cluster/placement/impl/PluginTestHelper.java
index 5b88b9d..61670da 100644
--- a/solr/core/src/test/org/apache/solr/cluster/placement/impl/PluginTestHelper.java
+++ b/solr/core/src/test/org/apache/solr/cluster/placement/impl/PluginTestHelper.java
@@ -29,66 +29,66 @@ import java.util.Set;
public class PluginTestHelper {
- static ClusterAbstractionsForTest.SolrCollectionImpl createCollection(String name, Map<String, String> properties,
- int numShards, int nrtReplicas, int tlogReplicas, int pullReplicas, Set<Node> nodes) {
- ClusterAbstractionsForTest.SolrCollectionImpl solrCollection = new ClusterAbstractionsForTest.SolrCollectionImpl(name, properties);
- Map<String, Shard> shards = createShardsAndReplicas(solrCollection, numShards, nrtReplicas, tlogReplicas, pullReplicas, nodes);
- solrCollection.setShards(shards);
- return solrCollection;
- }
+ static ClusterAbstractionsForTest.SolrCollectionImpl createCollection(String name, Map<String, String> properties,
+ int numShards, int nrtReplicas, int tlogReplicas, int pullReplicas, Set<Node> nodes) {
+ ClusterAbstractionsForTest.SolrCollectionImpl solrCollection = new ClusterAbstractionsForTest.SolrCollectionImpl(name, properties);
+ Map<String, Shard> shards = createShardsAndReplicas(solrCollection, numShards, nrtReplicas, tlogReplicas, pullReplicas, nodes);
+ solrCollection.setShards(shards);
+ return solrCollection;
+ }
+
+ /**
+ * Builds the representation of shards for a collection, based on the number of shards and replicas for each to create.
+ * The replicas are allocated to the provided nodes in a round robin way. The leader is set to the last replica of each shard.
+ */
+ static Map<String, Shard> createShardsAndReplicas(SolrCollection collection, int numShards,
+ int nrtReplicas, int tlogReplicas, int pullReplicas,
+ Set<Node> nodes) {
+ Iterator<Node> nodeIterator = nodes.iterator();
+
+ Map<String, Shard> shards = new HashMap<>();
+
+ for (int s = 0; s < numShards; s++) {
+ // "traditional" shard name
+ String shardName = "shard" + (s + 1);
+
+ ClusterAbstractionsForTest.ShardImpl shard = new ClusterAbstractionsForTest.ShardImpl(shardName, collection, Shard.ShardState.ACTIVE);
+
+ Map<String, Replica> replicas = new HashMap<>();
+
+ Replica leader = null;
+ int totalReplicas = nrtReplicas + tlogReplicas + pullReplicas;
+ for (int r = 0; r < totalReplicas; r++) {
+ Replica.ReplicaType type;
+ if (r < nrtReplicas) {
+ type = Replica.ReplicaType.NRT;
+ } else if (r < nrtReplicas + tlogReplicas) {
+ type = Replica.ReplicaType.TLOG;
+ } else {
+ type = Replica.ReplicaType.PULL;
+ }
+ String replicaName = shardName + "_replica_" + type.getSuffixChar() + r;
+ String coreName = replicaName + "_c";
+ final Node node;
+ if (!nodeIterator.hasNext()) {
+ nodeIterator = nodes.iterator();
+ }
+ // If the nodes set is empty, this call will fail
+ node = nodeIterator.next();
- /**
- * Builds the representation of shards for a collection, based on the number of shards and replicas for each to create.
- * The replicas are allocated to the provided nodes in a round robin way. The leader is set to the last replica of each shard.
- */
- static Map<String, Shard> createShardsAndReplicas(SolrCollection collection, int numShards,
- int nrtReplicas, int tlogReplicas, int pullReplicas,
- Set<Node> nodes) {
- Iterator<Node> nodeIterator = nodes.iterator();
-
- Map<String, Shard> shards = new HashMap<>();
-
- for (int s = 0; s < numShards; s++) {
- // "traditional" shard name
- String shardName = "shard" + (s + 1);
-
- ClusterAbstractionsForTest.ShardImpl shard = new ClusterAbstractionsForTest.ShardImpl(shardName, collection, Shard.ShardState.ACTIVE);
-
- Map<String, Replica> replicas = new HashMap<>();
-
- Replica leader = null;
- int totalReplicas = nrtReplicas + tlogReplicas + pullReplicas;
- for (int r = 0; r < totalReplicas; r++) {
- Replica.ReplicaType type;
- if (r < nrtReplicas) {
- type = Replica.ReplicaType.NRT;
- } else if (r < nrtReplicas + tlogReplicas) {
- type = Replica.ReplicaType.TLOG;
- } else {
- type = Replica.ReplicaType.PULL;
- }
- String replicaName = shardName + "_replica_" + type.getSuffixChar() + r;
- String coreName = replicaName + "_c";
- final Node node;
- if (!nodeIterator.hasNext()) {
- nodeIterator = nodes.iterator();
- }
- // If the nodes set is empty, this call will fail
- node = nodeIterator.next();
-
- Replica replica = new ClusterAbstractionsForTest.ReplicaImpl(replicaName, coreName, shard, type, Replica.ReplicaState.ACTIVE, node);
-
- replicas.put(replica.getReplicaName(), replica);
- if (replica.getType() == Replica.ReplicaType.NRT) {
- leader = replica;
- }
- }
-
- shard.setReplicas(replicas, leader);
-
- shards.put(shard.getShardName(), shard);
+ Replica replica = new ClusterAbstractionsForTest.ReplicaImpl(replicaName, coreName, shard, type, Replica.ReplicaState.ACTIVE, node);
+
+ replicas.put(replica.getReplicaName(), replica);
+ if (replica.getType() == Replica.ReplicaType.NRT) {
+ leader = replica;
}
+ }
+
+ shard.setReplicas(replicas, leader);
- return shards;
+ shards.put(shard.getShardName(), shard);
}
+
+ return shards;
+ }
}