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

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


The following commit(s) were added to refs/heads/2.1 by this push:
     new f3ea5a8d57 Created new static methods that easily create TabletId 
objects (#5678)
f3ea5a8d57 is described below

commit f3ea5a8d5736efca3beba06b9b6b736f0ca21973
Author: Imirie Billey <148128385+ibill...@users.noreply.github.com>
AuthorDate: Tue Jul 1 11:26:56 2025 -0400

    Created new static methods that easily create TabletId objects (#5678)
    
    * Created new static methods that easily create TabletId objects
    
    Created the static overloaded of() methods in TabletId.java that creates 
TabletId objects using TabletIdImpl. Implemented testing in TabletIdTest.java 
that ensure TabletId is created correctly and it's fields can be properly 
accessed and used. This is being submitted as an update to include new methods 
in 2.1. Changes will be made later in a separate PR to target version 4.0.0 in 
order to replace existing Mock tests of TabletId with these methods.
    
    Closes #5666
    
    ---------
    
    Co-authored-by: Kevin Rathbun <kevinrr...@gmail.com>
---
 .../org/apache/accumulo/core/data/TabletId.java    |  59 +++++-
 .../apache/accumulo/core/data/TabletIdTest.java    | 218 +++++++++++++++++++++
 2 files changed, 276 insertions(+), 1 deletion(-)

diff --git a/core/src/main/java/org/apache/accumulo/core/data/TabletId.java 
b/core/src/main/java/org/apache/accumulo/core/data/TabletId.java
index 51bfa1aaae..bfddb36a43 100644
--- a/core/src/main/java/org/apache/accumulo/core/data/TabletId.java
+++ b/core/src/main/java/org/apache/accumulo/core/data/TabletId.java
@@ -18,6 +18,8 @@
  */
 package org.apache.accumulo.core.data;
 
+import org.apache.accumulo.core.dataImpl.KeyExtent;
+import org.apache.accumulo.core.dataImpl.TabletIdImpl;
 import org.apache.hadoop.io.Text;
 
 /**
@@ -26,6 +28,62 @@ import org.apache.hadoop.io.Text;
  * @since 1.7.0
  */
 public interface TabletId extends Comparable<TabletId> {
+
+  /**
+   * Return a TabletId object for the provided TableId in range of 
(prevEndRow, endRow]. If the
+   * parameters prevEndRow and/or endRow are null, they represent a tablet 
over the range of -inf
+   * and/or inf respectively.
+   *
+   * @param tableId the ID for a table
+   * @param endRow the last row in this tablet, or null if this is the last 
tablet in this table
+   * @param prevEndRow the last row in the immediately preceding tablet for 
the table, or null if
+   *        this represents the first tablet in this table
+   * @return Return the new {@link TabletId} object
+   * @since 2.1.4
+   */
+  static TabletId of(TableId tableId, Text endRow, Text prevEndRow) {
+    KeyExtent ke = new KeyExtent(tableId, endRow, prevEndRow);
+    return new TabletIdImpl(ke);
+  }
+
+  /**
+   * @see #of(TableId, Text, Text)
+   * @since 2.1.4
+   */
+  static TabletId of(TableId tableId, String endRow, String prevEndRow) {
+    KeyExtent ke;
+    if (endRow == null && prevEndRow == null) {
+      ke = new KeyExtent(tableId, null, null);
+    } else if (endRow == null) {
+      ke = new KeyExtent(tableId, null, new Text(prevEndRow));
+    } else if (prevEndRow == null) {
+      ke = new KeyExtent(tableId, new Text(endRow), null);
+    } else {
+      ke = new KeyExtent(tableId, new Text(endRow), new Text(prevEndRow));
+    }
+
+    return new TabletIdImpl(ke);
+  }
+
+  /**
+   * @see #of(TableId, Text, Text)
+   * @since 2.1.4
+   */
+  static TabletId of(TableId tableId, byte[] endRow, byte[] prevEndRow) {
+    KeyExtent ke;
+    if (endRow == null && prevEndRow == null) {
+      ke = new KeyExtent(tableId, null, null);
+    } else if (endRow == null) {
+      ke = new KeyExtent(tableId, null, new Text(prevEndRow));
+    } else if (prevEndRow == null) {
+      ke = new KeyExtent(tableId, new Text(endRow), null);
+    } else {
+      ke = new KeyExtent(tableId, new Text(endRow), new Text(prevEndRow));
+    }
+
+    return new TabletIdImpl(ke);
+  }
+
   /**
    * @since 2.1.0
    */
@@ -47,5 +105,4 @@ public interface TabletId extends Comparable<TabletId> {
    * @since 1.8.0
    */
   Range toRange();
-
 }
diff --git a/core/src/test/java/org/apache/accumulo/core/data/TabletIdTest.java 
b/core/src/test/java/org/apache/accumulo/core/data/TabletIdTest.java
new file mode 100644
index 0000000000..711fb835f0
--- /dev/null
+++ b/core/src/test/java/org/apache/accumulo/core/data/TabletIdTest.java
@@ -0,0 +1,218 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.accumulo.core.data;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.accumulo.core.dataImpl.TabletIdImpl;
+import org.apache.hadoop.io.Text;
+import org.junit.jupiter.api.Test;
+
+class TabletIdTest {
+  /**
+   * Tests the {@link TabletId#of(TableId, String, String)} method to verify 
that a {@link TabletId}
+   * object is created
+   */
+  @Test
+  void testOfGivenStringArgs() {
+    TabletId tabletId = TabletId.of(TableId.of("2"), "b", "a");
+    assertEquals("2", tabletId.getTable().canonical(), "Expected the Table ID 
to be 2");
+    assertEquals(new Text("b"), tabletId.getEndRow(), "Expected endRow to be 
b");
+    assertEquals(new Text("a"), tabletId.getPrevEndRow(), "Expected prevEndRow 
to be a");
+  }
+
+  /**
+   * Tests the {@link TabletId#of(TableId, Text, Text)} method to verify that 
a {@link TabletId}
+   * object is created.
+   */
+  @Test
+  void testOfGivenTextArgs() {
+    TabletId tabletId = TabletId.of(TableId.of("2"), new Text("b"), new 
Text("a"));
+    assertEquals("2", tabletId.getTable().canonical(), "Expected the Table ID 
to be 2");
+    assertEquals(new Text("b"), tabletId.getEndRow(), "Expected endRow to be 
b");
+    assertEquals(new Text("a"), tabletId.getPrevEndRow(), "Expected prevEndRow 
to be a");
+  }
+
+  /**
+   * Tests the {@link TabletId#of(TableId, byte[], byte[])} method to verify 
that a {@link TabletId}
+   * object is created.
+   */
+  @Test
+  void testOfGivenByteArrayArgs() {
+    TabletId tabletId = TabletId.of(TableId.of("2"), ("b").getBytes(UTF_8), 
("a").getBytes(UTF_8));
+    assertEquals("2", tabletId.getTable().canonical(), "Expected the Table ID 
to be 2");
+    assertEquals(new Text("b"), tabletId.getEndRow(), "Expected endRow to be 
b");
+    assertEquals(new Text("a"), tabletId.getPrevEndRow(), "Expected prevEndRow 
to be a");
+  }
+
+  /**
+   * Test when null is given for the endRow/prevEndRow, that it is treated as 
an infinite range, and
+   * any other TabletId objects with the same TableId are within range, no 
matter the values for
+   * endRow and prevEndRow. The values of endRow and prevEndRow must be null 
or cast to a type to
+   * avoid ambiguous references.
+   */
+  @Test
+  void testInfiniteRanges() {
+    Text endRow = null;
+    Text prevEndRow = null;
+    TabletId tabletId = TabletId.of(TableId.of("2"), endRow, prevEndRow);
+    TabletId tabletId1 = TabletId.of(TableId.of("2"), "b", "a");
+    TabletId tabletId2 = TabletId.of(TableId.of("2"), "z", "a");
+    TabletId tabletId3 = TabletId.of(TableId.of("2"), new Text("z"), null);
+
+    assertTrue((((TabletIdImpl) tabletId).toKeyExtent())
+        .overlaps(((TabletIdImpl) tabletId1).toKeyExtent()));
+    assertTrue((((TabletIdImpl) tabletId).toKeyExtent())
+        .overlaps(((TabletIdImpl) tabletId2).toKeyExtent()));
+    assertTrue((((TabletIdImpl) tabletId).toKeyExtent())
+        .overlaps(((TabletIdImpl) tabletId3).toKeyExtent()));
+  }
+
+  /**
+   * Tests that given a endRow equal to null, that {@link 
TabletId#getEndRow()} is equal to null.
+   */
+  @Test
+  void testEndRowIsNull() {
+    Text endRow = null;
+    TabletId tabletId = TabletId.of(TableId.of("2"), endRow, new Text("a"));
+
+    assertNull(tabletId.getEndRow(), "Expected endRow to be null");
+    // Checking other fields just in case a bug with null sets other fields to 
null
+    assertEquals("2", tabletId.getTable().canonical(), "Expected the Table ID 
to be 2");
+    assertEquals(new Text("a"), tabletId.getPrevEndRow(), "Expected prevEndRow 
to be a");
+  }
+
+  /**
+   * Tests that given a prevEndRow equal to null, that {@link 
TabletId#getPrevEndRow()} is equal to
+   * null.
+   */
+  @Test
+  void testPrevEndRowIsNull() {
+    Text prevEndRow = null;
+    TabletId tabletId = TabletId.of(TableId.of("2"), new Text("b"), 
prevEndRow);
+
+    assertNull(tabletId.getPrevEndRow(), "Expected prevEndRow to be null");
+    // Checking other fields just in case
+    assertEquals("2", tabletId.getTable().canonical(), "Expected the Table ID 
to be 2");
+    assertEquals(new Text("b"), tabletId.getEndRow(), "Expected endRow to be 
b");
+  }
+
+  /**
+   * Tests that the inputted TableId of the TabletId is equal to its {@link 
TabletId#getTable()},
+   * verifying the {@link TabletId} is correctly created.
+   */
+  @Test
+  void testTableIdEqualsTableId() {
+    TabletId tabletOne = TabletId.of(TableId.of("2"), "b", "a");
+    TabletId tabletTwo = TabletId.of(TableId.of("Hello"), "b", "a");
+    TabletId tabletThree = TabletId.of(TableId.of("---String---"), "b", "a");
+
+    assertEquals("2", tabletOne.getTable().canonical(), "Expected the Table ID 
to be 2");
+    assertEquals("Hello", tabletTwo.getTable().canonical(), "Expected the 
Table ID to be Hello");
+    assertEquals("---String---", tabletThree.getTable().canonical(),
+        "Expected the Table ID to be ---String---");
+  }
+
+  @Test
+  void testCompareToOfTabletId() {
+    ArrayList<TabletId> tablets = new ArrayList<>();
+    tablets.add(TabletId.of(TableId.of("d"), "w", "a"));
+    tablets.add(TabletId.of(TableId.of("e"), "z", "g"));
+    tablets.add(TabletId.of(TableId.of("g"), "b", "a"));
+    tablets.add(TabletId.of(TableId.of("c"), (String) null, null));
+    tablets.add(TabletId.of(TableId.of("a"), "m", "l"));
+    tablets.add(TabletId.of(TableId.of("a"), null, "b"));
+    tablets.add(TabletId.of(TableId.of("a"), null, (String) null));
+    tablets.add(TabletId.of(TableId.of("a"), null, "c"));
+    tablets.add(TabletId.of(TableId.of("a"), "b", "a"));
+    tablets.add(TabletId.of(TableId.of("a"), "z", null));
+    tablets.add(TabletId.of(TableId.of("f"), null, "a"));
+    tablets.add(TabletId.of(TableId.of("b"), "d", null));
+    Collections.sort(tablets);
+
+    for (int curr = 1; curr < tablets.size() - 1; curr++) {
+      int prev = curr - 1;
+      int comparison = tablets.get(prev).compareTo(tablets.get(curr));
+
+      if (comparison == 0) {
+        assertTrue(tablets.get(prev).equals(tablets.get(curr)));
+      } else {
+        assertTrue(comparison < 0);
+      }
+    }
+  }
+
+  @Test
+  void testEqualsOfTabletId() {
+    TabletId t = TabletId.of(TableId.of("2"), "b", "a");
+    TabletId equalsT = TabletId.of(TableId.of("2"), "b".getBytes(UTF_8), 
"a".getBytes(UTF_8));
+    ArrayList<TabletId> tablets = new ArrayList<>();
+
+    tablets.add(TabletId.of(TableId.of("5"), "b", "a"));
+    tablets.add(TabletId.of(TableId.of("5"), "b", "a"));
+    tablets.add(TabletId.of(TableId.of("6"), "d", "a"));
+    tablets.add(TabletId.of(TableId.of("1"), "g", "e"));
+    tablets.add(TabletId.of(TableId.of("2"), null, "a"));
+    tablets.add(TabletId.of(TableId.of("2"), "b", null));
+    tablets.add(TabletId.of(TableId.of("2"), (String) null, null));
+
+    for (TabletId tablet : tablets) {
+      assertNotEquals(tablet, t);
+      assertNotEquals(tablet.hashCode(), t.hashCode());
+    }
+    assertEquals(t, equalsT);
+    assertEquals(t.hashCode(), equalsT.hashCode());
+  }
+
+  @Test
+  void testHashCodeOfTabletId() {
+    // Testing consistency
+    TabletId tabletId = TabletId.of(TableId.of("2"), "b", "a");
+    int hashCode1 = tabletId.hashCode();
+    int hashCode2 = tabletId.hashCode();
+    assertEquals(hashCode1, hashCode2);
+
+    // Testing equality
+    TabletId tabletOne = TabletId.of(TableId.of("2"), "b", "a");
+    TabletId tabletTwo = TabletId.of(TableId.of("2"), "b", "a");
+    assertEquals(tabletOne.hashCode(), tabletTwo.hashCode());
+
+    // Testing even distribution
+    List<TabletId> tablets = new ArrayList<>();
+    for (int i = 0; i < 1000; i++) {
+      tablets.add(TabletId.of(TableId.of("value" + i), "b", "a"));
+    }
+    Set<Integer> hashCodes = new HashSet<>();
+    for (TabletId tabs : tablets) {
+      hashCodes.add(tabs.hashCode());
+    }
+    assertEquals(tablets.size(), hashCodes.size(), 10);
+  }
+
+}

Reply via email to