This is an automated email from the ASF dual-hosted git repository.

jmark99 pushed a commit to branch 1.10
in repository https://gitbox.apache.org/repos/asf/accumulo.git


The following commit(s) were added to refs/heads/1.10 by this push:
     new b94ce9a  Fix incorrect scan range output in getsplits command (#2370)
b94ce9a is described below

commit b94ce9ac73328488f8f8dd55dfa77e3795353515
Author: Mark Owens <jmar...@apache.org>
AuthorDate: Mon Nov 29 13:16:54 2021 -0500

    Fix incorrect scan range output in getsplits command (#2370)
    
    In the Accumulo shell, calling getsplits with the verbose option can result 
in incorret output. It occurs when the tableId of the table happens to be a 
single character and there are other tables where the tableId starts with the 
same character. This results in the output of getsplits displaying splits for 
the other tables as well.
    
    Added a couple of grammatical fixes based upon @millerruntime suggestions.
    
    Closes #2356
---
 .../accumulo/shell/commands/GetSplitsCommand.java  |  2 +
 .../org/apache/accumulo/test/ShellServerIT.java    | 75 +++++++++++++++++++++-
 2 files changed, 76 insertions(+), 1 deletion(-)

diff --git 
a/shell/src/main/java/org/apache/accumulo/shell/commands/GetSplitsCommand.java 
b/shell/src/main/java/org/apache/accumulo/shell/commands/GetSplitsCommand.java
index 0eae20b..a89d797 100644
--- 
a/shell/src/main/java/org/apache/accumulo/shell/commands/GetSplitsCommand.java
+++ 
b/shell/src/main/java/org/apache/accumulo/shell/commands/GetSplitsCommand.java
@@ -81,6 +81,8 @@ public class GetSplitsCommand extends Command {
         final Text start =
             new 
Text(shellState.getConnector().tableOperations().tableIdMap().get(tableName));
         final Text end = new Text(start);
+        // do not append the ';' until the end value above is assigned.
+        start.append(new byte[] {';'}, 0, 1);
         end.append(new byte[] {'<'}, 0, 1);
         scanner.setRange(new Range(start, end));
         for (Iterator<Entry<Key,Value>> iterator = scanner.iterator(); 
iterator.hasNext();) {
diff --git a/test/src/main/java/org/apache/accumulo/test/ShellServerIT.java 
b/test/src/main/java/org/apache/accumulo/test/ShellServerIT.java
index 8f009f3..5c874ab 100644
--- a/test/src/main/java/org/apache/accumulo/test/ShellServerIT.java
+++ b/test/src/main/java/org/apache/accumulo/test/ShellServerIT.java
@@ -327,7 +327,7 @@ public class ShellServerIT extends SharedMiniClusterBase {
 
   @Override
   public int defaultTimeoutSeconds() {
-    return 60;
+    return 180;
   }
 
   @Test
@@ -2063,4 +2063,77 @@ public class ShellServerIT extends SharedMiniClusterBase 
{
     return null;
   }
 
+  // This test addresses a bug (#2356) where if a table with a tableId of 
character length 1
+  // exists and another table(s) exist starting with the same character but 
with a tableId of
+  // length > 1, the verbose version of the getsplits command will return 
information from multiple
+  // tables when a lexicographical ordered table with an earlier ID is queried.
+  //
+  // In order to test, enough tables need to be created until the required 
condition exists.
+  // Since table ID counts increment using 1..9a..z, this test creates tables 
in groups of 36
+  // until a second table meeting the criteria is created.
+  // It then adds splits to the single digit ID table and one of the others. 
It performs a
+  // "getsplits -v" command on the single digit ID table and verifies that 
data from the other
+  // table is not present.
+  //
+  // Due to the number for createtable calls, this test will time out if a 
match is not found
+  // within some number of operations. Therefore, if a match is not found 
within the creation
+  // of the first 360 or so tables, the test exits with no results. In initial 
runs of the ITs
+  // this never occurred.
+  @Test
+  public void testGetSplitsScanRange() throws Exception {
+    Shell.log.debug("Starting testGetSplitsScanRange test ------------------");
+    int idCycleLen = 36;
+    int maxLoopcnt = 10;
+    int postModifier = 0;
+    int loopCnt = 0;
+
+    String[] tables = new String[2];
+    Connector conn = getCluster().getConnector(getPrincipal(), getToken());
+    while (loopCnt++ < maxLoopcnt) {
+      Map<String,String> idMap = conn.tableOperations().tableIdMap();
+      if (findIds(tables, idMap)) {
+        break;
+      }
+      createTables(idCycleLen, postModifier++);
+    }
+    if (loopCnt >= maxLoopcnt) {
+      Shell.log.warn("Warning: Unable to find needed tables...exiting test 
without verifying.");
+      return;
+    }
+    // add splits to the two tables
+    ts.exec("addsplits -t " + tables[0] + " a c e", true);
+    ts.exec("addsplits -t " + tables[1] + " g i t", true);
+    // first table should contain supplied string
+    ts.exec("getsplits -v -t " + tables[0], true, "(e, +inf) Default Tablet", 
true);
+    // first table should not contain the supplied string
+    ts.exec("getsplits -v -t " + tables[0], true, "(t, +inf) Default Tablet", 
false);
+  }
+
+  private boolean findIds(String[] tables, Map<String,String> idMap) {
+    String ids = "0123456789abcdefghijklmnopqrstuvwxyz";
+    for (int i = 0; i < ids.length(); i++) {
+      String id = ids.substring(i, i + 1);
+      if (idMap.containsValue(id) && idMap.containsValue(id + "0")) {
+        tables[0] = getTableNameFromId(idMap, id);
+        tables[1] = getTableNameFromId(idMap, id + "0");
+        Shell.log
+            .debug("Found tables: " + tables[0] + ":" + id + ", " + tables[1] 
+ ":" + id + "0");
+        return true;
+      }
+    }
+    return false;
+  }
+
+  private String getTableNameFromId(Map<String,String> map, String value) {
+    return map.entrySet().stream().filter(entry -> 
value.equals(entry.getValue()))
+        .map(Map.Entry::getKey).findFirst().get();
+  }
+
+  private void createTables(final int limit, final int modifier) throws 
IOException {
+    String postfix = Integer.toString(modifier);
+    for (int i = 0; i < limit; i++) {
+      ts.exec("createtable tabx" + Integer.toString(i) + postfix);
+    }
+  }
+
 }

Reply via email to