SOLR-13045: Allow SimDistribStateManager to create top-level data nodes

While working on a related issue in SimDistribStateManager, I noticed
that `createData()` only worked successfully on nodes nested more than
one level under root.  (i.e. `createData("/foo", someData, mode)` would
fail, while the same with "/foo/bar" wouldn't).  This was due to an edge
case in SimDistribStateManager's path building logic.  This commit fixes
this issue.
This commit is contained in:
Jason Gerlowski 2018-12-20 11:06:02 -05:00
parent 846dfbef39
commit 272178eff5
2 changed files with 20 additions and 9 deletions

View File

@ -456,26 +456,30 @@ public class SimDistribStateManager implements DistribStateManager {
} }
String relPath = path.charAt(0) == '/' ? path.substring(1) : path; String relPath = path.charAt(0) == '/' ? path.substring(1) : path;
if (relPath.length() == 0) { if (relPath.length() == 0) { //Trying to create root-node, return null.
// TODO should trying to create a root node throw an exception since its always init'd in the ctor? // TODO should trying to create a root node throw an exception since its always init'd in the ctor?
return null; return null;
} }
// non-root-node. Make sure parent exists.
String[] elements = relPath.split("/"); String[] elements = relPath.split("/");
StringBuilder parentStringBuilder = new StringBuilder(); StringBuilder parentStringBuilder = new StringBuilder();
for (int i = 0; i < elements.length - 1; i++) { Node parentNode = null;
parentStringBuilder.append('/'); if (elements.length == 1) { // Direct descendant of '/'.
parentStringBuilder.append(elements[i]); parentNode = getRoot();
} } else { // Indirect descendant of '/', lookup parent node
if (!hasData(parentStringBuilder.toString())) { for (int i = 0; i < elements.length - 1; i++) {
throw new NoSuchElementException(parentStringBuilder.toString()); parentStringBuilder.append('/');
parentStringBuilder.append(elements[i]);
}
if (!hasData(parentStringBuilder.toString())) {
throw new NoSuchElementException(parentStringBuilder.toString());
}
parentNode = traverse(parentStringBuilder.toString(), false, mode);
} }
multiLock.lock(); multiLock.lock();
try { try {
String nodeName = elements[elements.length-1]; String nodeName = elements[elements.length-1];
Node parentNode = traverse(parentStringBuilder.toString(), false, mode);
Node childNode = createNode(parentNode, mode, parentStringBuilder.append("/"), nodeName, false); Node childNode = createNode(parentNode, mode, parentStringBuilder.append("/"), nodeName, false);
childNode.setData(data, -1); childNode.setData(data, -1);
parentNode.setChild(childNode.name, childNode); parentNode.setChild(childNode.name, childNode);

View File

@ -18,6 +18,7 @@
package org.apache.solr.cloud.autoscaling.sim; package org.apache.solr.cloud.autoscaling.sim;
import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodHandles;
import java.nio.charset.StandardCharsets;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
@ -262,6 +263,12 @@ public class TestSimDistribStateManager extends SolrTestCaseJ4 {
assertEquals(0, kids.size()); assertEquals(0, kids.size());
} }
@Test
public void testCanCreateNodesWithDataAtTopLevel() throws Exception {
final String path = stateManager.createData("/topLevelNodeWithData", new String("helloworld").getBytes(StandardCharsets.UTF_8), CreateMode.PERSISTENT);
assertEquals("/topLevelNodeWithData", path);
}
static class OnceWatcher implements Watcher { static class OnceWatcher implements Watcher {
CountDownLatch triggered = new CountDownLatch(1); CountDownLatch triggered = new CountDownLatch(1);
WatchedEvent event; WatchedEvent event;