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;
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?
return null;
}
// non-root-node. Make sure parent exists.
String[] elements = relPath.split("/");
StringBuilder parentStringBuilder = new StringBuilder();
for (int i = 0; i < elements.length - 1; i++) {
parentStringBuilder.append('/');
parentStringBuilder.append(elements[i]);
}
if (!hasData(parentStringBuilder.toString())) {
throw new NoSuchElementException(parentStringBuilder.toString());
Node parentNode = null;
if (elements.length == 1) { // Direct descendant of '/'.
parentNode = getRoot();
} else { // Indirect descendant of '/', lookup parent node
for (int i = 0; i < elements.length - 1; i++) {
parentStringBuilder.append('/');
parentStringBuilder.append(elements[i]);
}
if (!hasData(parentStringBuilder.toString())) {
throw new NoSuchElementException(parentStringBuilder.toString());
}
parentNode = traverse(parentStringBuilder.toString(), false, mode);
}
multiLock.lock();
try {
String nodeName = elements[elements.length-1];
Node parentNode = traverse(parentStringBuilder.toString(), false, mode);
Node childNode = createNode(parentNode, mode, parentStringBuilder.append("/"), nodeName, false);
childNode.setData(data, -1);
parentNode.setChild(childNode.name, childNode);

View File

@ -18,6 +18,7 @@
package org.apache.solr.cloud.autoscaling.sim;
import java.lang.invoke.MethodHandles;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
@ -262,6 +263,12 @@ public class TestSimDistribStateManager extends SolrTestCaseJ4 {
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 {
CountDownLatch triggered = new CountDownLatch(1);
WatchedEvent event;