You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by no...@apache.org on 2016/07/01 12:09:03 UTC

lucene-solr:branch_6x: SOLR-9251: Support for a new tag 'role' in replica placement rules

Repository: lucene-solr
Updated Branches:
  refs/heads/branch_6x ed38a29a9 -> 5937247ac


SOLR-9251: Support for a new tag 'role' in replica placement rules


Project: http://git-wip-us.apache.org/repos/asf/lucene-solr/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucene-solr/commit/5937247a
Tree: http://git-wip-us.apache.org/repos/asf/lucene-solr/tree/5937247a
Diff: http://git-wip-us.apache.org/repos/asf/lucene-solr/diff/5937247a

Branch: refs/heads/branch_6x
Commit: 5937247ac38aaaeb166b92fcc6f6a08681d73a1e
Parents: ed38a29
Author: Noble Paul <no...@apache.org>
Authored: Fri Jul 1 17:37:36 2016 +0530
Committer: Noble Paul <no...@apache.org>
Committed: Fri Jul 1 17:38:40 2016 +0530

----------------------------------------------------------------------
 solr/CHANGES.txt                                |  2 +
 .../apache/solr/cloud/rule/ImplicitSnitch.java  | 25 +++++++++-
 .../apache/solr/cloud/rule/ReplicaAssigner.java | 10 +++-
 .../java/org/apache/solr/cloud/rule/Rule.java   | 10 +++-
 .../apache/solr/cloud/rule/SnitchContext.java   | 33 ++++++++++++-
 .../solr/cloud/rule/ImplicitSnitchTest.java     | 15 +++---
 .../apache/solr/cloud/rule/RuleEngineTest.java  | 51 +++++++++++++++-----
 7 files changed, 121 insertions(+), 25 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/5937247a/solr/CHANGES.txt
----------------------------------------------------------------------
diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt
index f384b2e..b0d6786 100644
--- a/solr/CHANGES.txt
+++ b/solr/CHANGES.txt
@@ -42,6 +42,8 @@ New Features
 
 * SOLR-9216: Support collection.configName in MODIFYCOLLECTION request (Keith Laban, noble)
 
+* SOLR-9251: Support for a new tag 'role' in replica placement rules (noble)
+
 
 Bug Fixes
 ----------------------

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/5937247a/solr/core/src/java/org/apache/solr/cloud/rule/ImplicitSnitch.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/cloud/rule/ImplicitSnitch.java b/solr/core/src/java/org/apache/solr/cloud/rule/ImplicitSnitch.java
index d089aa0..ac1d7ad 100644
--- a/solr/core/src/java/org/apache/solr/cloud/rule/ImplicitSnitch.java
+++ b/solr/core/src/java/org/apache/solr/cloud/rule/ImplicitSnitch.java
@@ -22,6 +22,7 @@ import java.net.InetAddress;
 import java.nio.file.Files;
 import java.nio.file.Paths;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -31,6 +32,7 @@ import java.util.regex.Pattern;
 
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableSet;
+import org.apache.solr.common.cloud.ZkStateReader;
 import org.apache.solr.common.params.ModifiableSolrParams;
 import org.apache.solr.core.CoreContainer;
 import org.apache.solr.handler.admin.CoreAdminHandler;
@@ -49,10 +51,11 @@ public class ImplicitSnitch extends Snitch implements CoreAdminHandler.Invocable
   public static final String HOST = "host";
   public static final String CORES = "cores";
   public static final String DISK = "freedisk";
+  public static final String ROLE = "role";
   public static final String SYSPROP = "sysprop.";
   public static final List<String> IP_SNITCHES = ImmutableList.of("ip_1", "ip_2", "ip_3", "ip_4");
 
-  public static final Set<String> tags = ImmutableSet.<String>builder().add(NODE, PORT, HOST, CORES, DISK).addAll(IP_SNITCHES).build();
+  public static final Set<String> tags = ImmutableSet.<String>builder().add(NODE, PORT, HOST, CORES, DISK, ROLE).addAll(IP_SNITCHES).build();
 
 
 
@@ -67,7 +70,7 @@ public class ImplicitSnitch extends Snitch implements CoreAdminHandler.Invocable
       Matcher hostAndPortMatcher = hostAndPortPattern.matcher(solrNode);
       if (hostAndPortMatcher.find()) ctx.getTags().put(PORT, hostAndPortMatcher.group(2));
     }
-
+    if (requestedTags.contains(ROLE)) fillRole(solrNode, ctx);
     addIpTags(solrNode, requestedTags, ctx);
 
     ModifiableSolrParams params = new ModifiableSolrParams();
@@ -79,6 +82,24 @@ public class ImplicitSnitch extends Snitch implements CoreAdminHandler.Invocable
     if (params.size() > 0) ctx.invokeRemote(solrNode, params, ImplicitSnitch.class.getName(), null);
   }
 
+  private void fillRole(String solrNode, SnitchContext ctx) {
+    Map roles = (Map) ctx.retrieve(ZkStateReader.ROLES); // we don't want to hit the ZK for each node
+    // so cache and reuse
+    if(roles == null) roles = ctx.getZkJson(ZkStateReader.ROLES);
+    ctx.store(ZkStateReader.ROLES, roles == null ? Collections.emptyMap() : roles);
+    if (roles != null) {
+      for (Object o : roles.entrySet()) {
+        Map.Entry e = (Map.Entry) o;
+        if (e.getValue() instanceof List) {
+          if(((List) e.getValue()).contains(solrNode)) {
+            ctx.getTags().put(ROLE, e.getKey());
+            break;
+          }
+        }
+      }
+    }
+  }
+
   static long getUsableSpaceInGB() throws IOException {
     long space = Files.getFileStore(Paths.get("/")).getUsableSpace();
     long spaceInGB = space / 1024 / 1024 / 1024;

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/5937247a/solr/core/src/java/org/apache/solr/cloud/rule/ReplicaAssigner.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/cloud/rule/ReplicaAssigner.java b/solr/core/src/java/org/apache/solr/cloud/rule/ReplicaAssigner.java
index eb881be..b1a1f2c 100644
--- a/solr/core/src/java/org/apache/solr/cloud/rule/ReplicaAssigner.java
+++ b/solr/core/src/java/org/apache/solr/cloud/rule/ReplicaAssigner.java
@@ -254,7 +254,8 @@ public class ReplicaAssigner {
         Integer n = nodeNames.get(liveNode);
         n = n == null ? 1 : n + 1;
         nodeNames.put(liveNode, n);
-        Number coreCount = (Number) nodeVsTagsCopy.get(liveNode).get(ImplicitSnitch.CORES);
+        Map<String, Object> tagsMap = nodeVsTagsCopy.get(liveNode);
+        Number coreCount = tagsMap == null ? null: (Number) tagsMap.get(ImplicitSnitch.CORES);
         if (coreCount != null) {
           nodeVsTagsCopy.get(liveNode).put(ImplicitSnitch.CORES, coreCount.intValue() + 1);
         }
@@ -398,7 +399,7 @@ public class ReplicaAssigner {
       //now use the Snitch to get the tags
       for (SnitchInfoImpl info : snitches.values()) {
         if (!info.myTags.isEmpty()) {
-          SnitchContext context = new SnitchContext(info, node);
+          SnitchContext context = getSnitchCtx(node, info);
           info.nodeVsContext.put(node, context);
           try {
             info.snitch.getTags(node, info.myTags, context);
@@ -441,6 +442,11 @@ public class ReplicaAssigner {
 
   }
 
+  private Map<String, Object> snitchSession = new HashMap<>();
+  protected SnitchContext getSnitchCtx( String node, SnitchInfoImpl info) {
+    return new SnitchContext(info, node, snitchSession);
+  }
+
   public static void verifySnitchConf(CoreContainer cc, List snitchConf) {
     getSnitchInfos(cc, snitchConf);
   }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/5937247a/solr/core/src/java/org/apache/solr/cloud/rule/Rule.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/cloud/rule/Rule.java b/solr/core/src/java/org/apache/solr/cloud/rule/Rule.java
index 209b755..8db6ac3 100644
--- a/solr/core/src/java/org/apache/solr/cloud/rule/Rule.java
+++ b/solr/core/src/java/org/apache/solr/cloud/rule/Rule.java
@@ -137,7 +137,8 @@ public class Rule {
       if (replica.isWildCard()) {
         //this means for each replica, the value must match
         //shard match is already tested
-        if (tag.canMatch(nodeVsTags.get(testNode).get(tag.name), phase)) return NODE_CAN_BE_ASSIGNED;
+        Map<String, Object> tags = nodeVsTags.get(testNode);
+        if (tag.canMatch(tags == null ? null : tags.get(tag.name), phase)) return NODE_CAN_BE_ASSIGNED;
         else return CANNOT_ASSIGN_FAIL;
       } else {
         int v = getNumberOfNodesWithSameTagVal(shard, nodeVsTags, shardVsNodeSet, shardName, tag, phase);
@@ -367,7 +368,12 @@ public class Rule {
     }
 
     public int compare(String n1, String n2, Map<String, Map<String, Object>> nodeVsTags) {
-      return isWildCard() ? 0 : operand.compare(nodeVsTags.get(n1).get(name), nodeVsTags.get(n2).get(name));
+      Map<String, Object> tags = nodeVsTags.get(n1);
+      Object n1Val = tags == null ? null : tags.get(name);
+      tags = nodeVsTags.get(n2);
+      Object n2Val = tags == null ? null : tags.get(name);
+      if (n1Val == null || n2Val == null) return -1;
+      return isWildCard() ? 0 : operand.compare(n1Val, n2Val);
     }
 
   }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/5937247a/solr/core/src/java/org/apache/solr/cloud/rule/SnitchContext.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/cloud/rule/SnitchContext.java b/solr/core/src/java/org/apache/solr/cloud/rule/SnitchContext.java
index 2808906..bfb80c0 100644
--- a/solr/core/src/java/org/apache/solr/cloud/rule/SnitchContext.java
+++ b/solr/core/src/java/org/apache/solr/cloud/rule/SnitchContext.java
@@ -32,8 +32,10 @@ import org.apache.solr.common.params.CommonParams;
 import org.apache.solr.common.params.ModifiableSolrParams;
 import org.apache.solr.common.params.SolrParams;
 import org.apache.solr.common.util.NamedList;
+import org.apache.solr.common.util.Utils;
 import org.apache.solr.core.CoreContainer;
 import org.apache.solr.update.UpdateShardHandler;
+import org.apache.zookeeper.data.Stat;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -48,13 +50,15 @@ public class SnitchContext implements RemoteCallback {
   private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
   private final Map<String, Object> tags = new HashMap<>();
   private String node;
+  private Map<String, Object> session;
   final SnitchInfo snitchInfo;
   Exception exception;
 
 
-  SnitchContext(SnitchInfo perSnitch, String node) {
+  SnitchContext(SnitchInfo perSnitch, String node, Map<String, Object> session) {
     this.snitchInfo = perSnitch;
     this.node = node;
+    this.session = session;
   }
 
   public SnitchInfo getSnitchInfo() {
@@ -65,6 +69,33 @@ public class SnitchContext implements RemoteCallback {
     return tags;
   }
 
+  public void store(String s, Object val) {
+    if (session != null) session.put(s, val);
+
+  }
+
+  public Object retrieve(String s) {
+    return session != null ? session.get(s) : null;
+
+  }
+
+  public Map getZkJson(String path) {
+    if (snitchInfo.getCoreContainer().isZooKeeperAware()) {
+      try {
+        byte[] data = snitchInfo.getCoreContainer().getZkController().getZkClient().getData(path, null, new Stat(), true);
+        if (data == null) return null;
+        return (Map) Utils.fromJSON(data);
+      } catch (Exception e) {
+        log.warn("Unable to read from ZK path : " + path, e);
+        return null;
+
+      }
+    } else {
+      return null;
+    }
+
+  }
+
   public String getNode() {
     return node;
   }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/5937247a/solr/core/src/test/org/apache/solr/cloud/rule/ImplicitSnitchTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/cloud/rule/ImplicitSnitchTest.java b/solr/core/src/test/org/apache/solr/cloud/rule/ImplicitSnitchTest.java
index a5abb16..5ae9710 100644
--- a/solr/core/src/test/org/apache/solr/cloud/rule/ImplicitSnitchTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/rule/ImplicitSnitchTest.java
@@ -1,5 +1,6 @@
 package org.apache.solr.cloud.rule;
 
+import java.util.HashMap;
 import java.util.Map;
 
 import com.google.common.collect.Sets;
@@ -44,7 +45,7 @@ public class ImplicitSnitchTest {
   @Before
   public void beforeImplicitSnitchTest() {
     snitch = new ImplicitSnitch();
-    context = new SnitchContext(null, null);
+    context = new SnitchContext(null, null, new HashMap<>());
   }
 
 
@@ -81,7 +82,7 @@ public class ImplicitSnitchTest {
   public void testGetTags_withIPv4RequestedTags_ip2_and_ip4_returns_two_tags() throws Exception {
     String node = "192.168.1.2:8983_solr";
 
-    SnitchContext context = new SnitchContext(null, node);
+    SnitchContext context = new SnitchContext(null, node, new HashMap<>());
     snitch.getTags(node, Sets.newHashSet(IP_2, IP_4), context);
 
     Map<String, Object> tags = context.getTags();
@@ -94,7 +95,7 @@ public class ImplicitSnitchTest {
   public void testGetTags_with_wrong_ipv4_format_ip_returns_nothing() throws Exception {
     String node = "192.168.1.2.1:8983_solr";
 
-    SnitchContext context = new SnitchContext(null, node);
+    SnitchContext context = new SnitchContext(null, node, new HashMap<>());
     snitch.getTags(node, Sets.newHashSet(IP_1), context);
 
     Map<String, Object> tags = context.getTags();
@@ -106,7 +107,7 @@ public class ImplicitSnitchTest {
   public void testGetTags_with_correct_ipv6_format_ip_returns_nothing() throws Exception {
     String node = "[0:0:0:0:0:0:0:1]:8983_solr";
 
-    SnitchContext context = new SnitchContext(null, node);
+    SnitchContext context = new SnitchContext(null, node, new HashMap<>());
     snitch.getTags(node, Sets.newHashSet(IP_1), context);
 
     Map<String, Object> tags = context.getTags();
@@ -129,7 +130,7 @@ public class ImplicitSnitchTest {
   public void testGetTags_withAllHostNameRequestedTags_returns_all_Tags() throws Exception {
     String node = "serv01.dc01.london.uk.apache.org:8983_solr";
 
-    SnitchContext context = new SnitchContext(null, node);
+    SnitchContext context = new SnitchContext(null, node, new HashMap<>());
     //We need mocking here otherwise, we would need proper DNS entry for this test to pass
     ImplicitSnitch mockedSnitch = Mockito.spy(snitch);
     when(mockedSnitch.getHostIp(anyString())).thenReturn("10.11.12.13");
@@ -148,7 +149,7 @@ public class ImplicitSnitchTest {
   public void testGetTags_withHostNameRequestedTag_ip3_returns_1_tag() throws Exception {
     String node = "serv01.dc01.london.uk.apache.org:8983_solr";
 
-    SnitchContext context = new SnitchContext(null, node);
+    SnitchContext context = new SnitchContext(null, node, new HashMap<>());
     //We need mocking here otherwise, we would need proper DNS entry for this test to pass
     ImplicitSnitch mockedSnitch = Mockito.spy(snitch);
     when(mockedSnitch.getHostIp(anyString())).thenReturn("10.11.12.13");
@@ -163,7 +164,7 @@ public class ImplicitSnitchTest {
   public void testGetTags_withHostNameRequestedTag_ip99999_returns_nothing() throws Exception {
     String node = "serv01.dc01.london.uk.apache.org:8983_solr";
 
-    SnitchContext context = new SnitchContext(null, node);
+    SnitchContext context = new SnitchContext(null, node, new HashMap<>());
     //We need mocking here otherwise, we would need proper DNS entry for this test to pass
     ImplicitSnitch mockedSnitch = Mockito.spy(snitch);
     when(mockedSnitch.getHostIp(anyString())).thenReturn("10.11.12.13");

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/5937247a/solr/core/src/test/org/apache/solr/cloud/rule/RuleEngineTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/cloud/rule/RuleEngineTest.java b/solr/core/src/test/org/apache/solr/cloud/rule/RuleEngineTest.java
index ad98e61..01dd868 100644
--- a/solr/core/src/test/org/apache/solr/cloud/rule/RuleEngineTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/rule/RuleEngineTest.java
@@ -26,11 +26,14 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
+import com.google.common.collect.ImmutableList;
 import org.apache.solr.SolrTestCaseJ4;
 import org.apache.solr.cloud.rule.ReplicaAssigner.Position;
+import org.apache.solr.common.cloud.ZkStateReader;
 import org.apache.solr.common.util.Utils;
 import org.junit.Test;
 
+import static java.util.Collections.singletonList;
 import static org.apache.solr.cloud.rule.Rule.parseRule;
 import static org.apache.solr.common.util.Utils.makeMap;
 
@@ -69,17 +72,43 @@ public class RuleEngineTest extends SolrTestCaseJ4{
 
     Map<Position, String> mapping = new ReplicaAssigner(
         rules,
-        shardVsReplicaCount, Collections.singletonList(MockSnitch.class.getName()),
+        shardVsReplicaCount, singletonList(MockSnitch.class.getName()),
         new HashMap(), new ArrayList<>(MockSnitch.nodeVsTags.keySet()), null, null ).getNodeMappings();
     assertNotNull(mapping);
 
     mapping = new ReplicaAssigner(
         rules,
-        shardVsReplicaCount, Collections.singletonList(MockSnitch.class.getName()),
+        shardVsReplicaCount, singletonList(MockSnitch.class.getName()),
         new HashMap(), new ArrayList<>(MockSnitch.nodeVsTags.keySet()), null, null ).getNodeMappings();
     assertNotNull(mapping);
 
+    rules = parseRules("[{role:'!overseer'}]" );
+    Map<String, Object> snitchSession = new HashMap<>();
+    List<String> preferredOverseerNodes = ImmutableList.of("127.0.0.1:49947_", "127.0.0.1:49952_");
+    ReplicaAssigner replicaAssigner = new ReplicaAssigner(
+        rules,
+        shardVsReplicaCount, singletonList(MockSnitch.class.getName()),
+        new HashMap(), new ArrayList<>(MockSnitch.nodeVsTags.keySet()), null, null) {
+
+      @Override
+      protected SnitchContext getSnitchCtx(String node, SnitchInfoImpl info) {
+        return new SnitchContext(info, node, snitchSession){
+          @Override
+          public Map getZkJson(String path) {
+            if(ZkStateReader.ROLES.equals(path)){
+              return Collections.singletonMap("overseer", preferredOverseerNodes);
+            }
+            return null;
+          }
+        };
+      }
+    };
+    mapping = replicaAssigner.getNodeMappings();
+    assertNotNull(mapping);
 
+    for (String nodeName : mapping.values()) {
+      assertFalse(preferredOverseerNodes.contains(nodeName));
+    }
 
   }
 
@@ -115,7 +144,7 @@ public class RuleEngineTest extends SolrTestCaseJ4{
     Map shardVsReplicaCount = makeMap("shard1", 2, "shard2", 2);
     Map<Position, String> mapping = new ReplicaAssigner(
         rules,
-        shardVsReplicaCount, Collections.singletonList(MockSnitch.class.getName()),
+        shardVsReplicaCount, singletonList(MockSnitch.class.getName()),
         new HashMap(), new ArrayList<>(MockSnitch.nodeVsTags.keySet()), null, null).getNodeMappings();
     assertNotNull(mapping);
     assertFalse(mapping.containsValue("127.0.0.1:49947_"));
@@ -127,7 +156,7 @@ public class RuleEngineTest extends SolrTestCaseJ4{
     shardVsReplicaCount = makeMap("shard1", 2, "shard2", 2);
     mapping = new ReplicaAssigner(
         rules,
-        shardVsReplicaCount, Collections.singletonList(MockSnitch.class.getName()),
+        shardVsReplicaCount, singletonList(MockSnitch.class.getName()),
         new HashMap(), new ArrayList<>(MockSnitch.nodeVsTags.keySet()), null, null).getNodeMappings0();
     assertNull(mapping);
 
@@ -139,7 +168,7 @@ public class RuleEngineTest extends SolrTestCaseJ4{
     shardVsReplicaCount = makeMap("shard1", 2, "shard2", 2);
     mapping = new ReplicaAssigner(
         rules,
-        shardVsReplicaCount, Collections.singletonList(MockSnitch.class.getName()),
+        shardVsReplicaCount, singletonList(MockSnitch.class.getName()),
         new HashMap(), new ArrayList<>(MockSnitch.nodeVsTags.keySet()), null, null).getNodeMappings0();
     assertNotNull(mapping);
     assertFalse(mapping.containsValue("127.0.0.2:49958_"));
@@ -151,7 +180,7 @@ public class RuleEngineTest extends SolrTestCaseJ4{
     shardVsReplicaCount = makeMap("shard1", 2, "shard2", 2);
     mapping = new ReplicaAssigner(
         rules,
-        shardVsReplicaCount, Collections.singletonList(MockSnitch.class.getName()),
+        shardVsReplicaCount, singletonList(MockSnitch.class.getName()),
         new HashMap(), new ArrayList<>(MockSnitch.nodeVsTags.keySet()), null, null).getNodeMappings();
     assertNotNull(mapping);
 
@@ -162,7 +191,7 @@ public class RuleEngineTest extends SolrTestCaseJ4{
     shardVsReplicaCount = makeMap("shard1", 2, "shard2", 2);
     mapping = new ReplicaAssigner(
         rules,
-        shardVsReplicaCount, Collections.singletonList(MockSnitch.class.getName()),
+        shardVsReplicaCount, singletonList(MockSnitch.class.getName()),
         new HashMap(), new ArrayList<>(MockSnitch.nodeVsTags.keySet()), null, null).getNodeMappings0();
     assertNull(mapping);
 
@@ -173,7 +202,7 @@ public class RuleEngineTest extends SolrTestCaseJ4{
     shardVsReplicaCount = makeMap("shard1", 2, "shard2", 2);
     mapping = new ReplicaAssigner(
         rules,
-        shardVsReplicaCount, Collections.singletonList(MockSnitch.class.getName()),
+        shardVsReplicaCount, singletonList(MockSnitch.class.getName()),
         new HashMap(), new ArrayList<>(MockSnitch.nodeVsTags.keySet()), null, null).getNodeMappings();
     assertNotNull(mapping);
 
@@ -204,14 +233,14 @@ public class RuleEngineTest extends SolrTestCaseJ4{
     MockSnitch.nodeVsTags = nodeVsTags;
     Map<Position, String> mapping = new ReplicaAssigner(
         rules,
-        shardVsReplicaCount, Collections.singletonList(MockSnitch.class.getName()),
+        shardVsReplicaCount, singletonList(MockSnitch.class.getName()),
         new HashMap(), new ArrayList<>(MockSnitch.nodeVsTags.keySet()), null, null).getNodeMappings0();
     assertNull(mapping);
     rulesStr = "rack:*,replica:<2~";
     rules = parse(Arrays.asList(rulesStr));
     mapping = new ReplicaAssigner(
         rules,
-        shardVsReplicaCount, Collections.singletonList(MockSnitch.class.getName()),
+        shardVsReplicaCount, singletonList(MockSnitch.class.getName()),
         new HashMap(), new ArrayList<>(MockSnitch.nodeVsTags.keySet()), null ,null).getNodeMappings();
     assertNotNull(mapping);
 
@@ -219,7 +248,7 @@ public class RuleEngineTest extends SolrTestCaseJ4{
     rules = parse(Arrays.asList(rulesStr));
     mapping = new ReplicaAssigner(
         rules,
-        shardVsReplicaCount, Collections.singletonList(MockSnitch.class.getName()),
+        shardVsReplicaCount, singletonList(MockSnitch.class.getName()),
         new HashMap(), new ArrayList<>(MockSnitch.nodeVsTags.keySet()), null,null ).getNodeMappings();
     assertNotNull(mapping);
   }