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

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


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

commit 7e97566a8b1f0b464753d9e7099afb1bdfa5b043
Author: Mark Owens <jmar...@apache.org>
AuthorDate: Mon Nov 29 12:44:45 2021 -0500

    Fix incorrect scan range output in getsplits command (#2369)
    
    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.
    
    Closes #2356
    
    Co-authored-by: Mike Miller <mmil...@apache.org>
---
 .../accumulo/shell/commands/GetSplitsCommand.java  |  2 +
 .../java/org/apache/accumulo/test/ShellIT.java     | 76 +++++++++++++++++++++-
 2 files changed, 77 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 64ab003..79e9746 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
@@ -72,6 +72,8 @@ public class GetSplitsCommand extends Command {
         final Text start =
             new 
Text(shellState.getAccumuloClient().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 (final Entry<Key,Value> next : scanner) {
diff --git a/test/src/main/java/org/apache/accumulo/test/ShellIT.java 
b/test/src/main/java/org/apache/accumulo/test/ShellIT.java
index 139247a..0136f6c 100644
--- a/test/src/main/java/org/apache/accumulo/test/ShellIT.java
+++ b/test/src/main/java/org/apache/accumulo/test/ShellIT.java
@@ -31,6 +31,7 @@ import java.text.SimpleDateFormat;
 import java.util.Arrays;
 import java.util.Date;
 import java.util.List;
+import java.util.Map;
 import java.util.TimeZone;
 
 import org.apache.accumulo.harness.SharedMiniClusterBase;
@@ -56,7 +57,7 @@ public class ShellIT extends SharedMiniClusterBase {
 
   @Override
   protected int defaultTimeoutSeconds() {
-    return 30;
+    return 180;
   }
 
   @BeforeClass
@@ -515,4 +516,77 @@ public class ShellIT extends SharedMiniClusterBase {
 
     exec("deletetable t -f", true, "Table: [t] has been deleted");
   }
+
+  // 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 postModifier = 0;
+    int maxLoopcnt = 10;
+    int loopCnt = 0;
+
+    String[] tables = new String[2];
+    while (loopCnt++ < maxLoopcnt) {
+      Map<String,String> idMap = 
shell.getAccumuloClient().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
+    exec("addsplits -t " + tables[0] + " a c e", true);
+    exec("addsplits -t " + tables[1] + " g i t", true);
+    // first table should contain supplied string
+    exec("getsplits -v -t " + tables[0], true, "(e, +inf) Default Tablet", 
true);
+    // first table should not contain the supplied string
+    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 tableModifier = "x" + Integer.toString(modifier);
+    for (int i = 0; i < limit; i++) {
+      exec("createtable tabx" + Integer.toString(i) + tableModifier);
+    }
+  }
+
 }

Reply via email to