This is an automated email from the ASF dual-hosted git repository. kturner pushed a commit to branch 3.1 in repository https://gitbox.apache.org/repos/asf/accumulo.git
The following commit(s) were added to refs/heads/3.1 by this push: new cdf30d0667 Adds ByteSequence constructors to Key (#5327) cdf30d0667 is described below commit cdf30d0667cf67bd3bdf04f7b3b24cd1037b63f9 Author: Keith Turner <ktur...@apache.org> AuthorDate: Fri Feb 14 17:17:54 2025 -0500 Adds ByteSequence constructors to Key (#5327) Key has methods to get data as ByteSequences but no methods to create keys using ByteSequence. This leads to either using Text or ByteSequence plus byte[]. Text always does an intermediate copy and ByteSequence plus byte[] is cumbersome. These new method make it easier to efficiently create a new Key from an existing Key w/ less code and less copying of data. Co-authored-by: Christopher Tubbs <ctubb...@apache.org> --- .../java/org/apache/accumulo/core/data/Key.java | 57 ++++++++++++++ .../org/apache/accumulo/core/data/KeyBuilder.java | 88 ++++++++++++++++++++++ .../org/apache/accumulo/core/data/KeyTest.java | 50 ++++++++++++ 3 files changed, 195 insertions(+) diff --git a/core/src/main/java/org/apache/accumulo/core/data/Key.java b/core/src/main/java/org/apache/accumulo/core/data/Key.java index d6f0ebccf7..6344d4bb70 100644 --- a/core/src/main/java/org/apache/accumulo/core/data/Key.java +++ b/core/src/main/java/org/apache/accumulo/core/data/Key.java @@ -552,6 +552,63 @@ public class Key implements WritableComparable<Key>, Cloneable { new Text(cv.getExpression()), ts); } + /** + * Creates a key with the specified row, the specified column family, the specified column + * qualifier, the specified column visibility, the specified timestamp, and delete marker false. + * This constructor creates a copy of the fields. + * <p> + * To avoid copying, use + * {@link Key#Key(byte[] row, byte[] cf, byte[] cq, byte[] cv, long ts, boolean deleted, boolean copy)} + * instead. + * + * @see #builder() + * @since 3.1.0 + */ + public Key(ByteSequence row, ByteSequence cf, ByteSequence cq, ByteSequence cv, long ts) { + byte[] rowBytes, cfBytes, cqBytes, cvBytes; + int rowOffset, cfOffset, cqOffset, cvOffset; + int rowLen, cfLen, cqLen, cvLen; + + if (row.isBackedByArray()) { + rowBytes = row.getBackingArray(); + rowOffset = row.offset(); + } else { + rowBytes = row.toArray(); + rowOffset = 0; + } + rowLen = row.length(); + + if (cf.isBackedByArray()) { + cfBytes = cf.getBackingArray(); + cfOffset = cf.offset(); + } else { + cfBytes = cf.toArray(); + cfOffset = 0; + } + cfLen = cf.length(); + + if (cq.isBackedByArray()) { + cqBytes = cq.getBackingArray(); + cqOffset = cq.offset(); + } else { + cqBytes = cq.toArray(); + cqOffset = 0; + } + cqLen = cq.length(); + + if (cv.isBackedByArray()) { + cvBytes = cv.getBackingArray(); + cvOffset = cv.offset(); + } else { + cvBytes = cv.toArray(); + cvOffset = 0; + } + cvLen = cv.length(); + + init(rowBytes, rowOffset, rowLen, cfBytes, cfOffset, cfLen, cqBytes, cqOffset, cqLen, cvBytes, + cvOffset, cvLen, ts, false, true); + } + private byte[] followingArray(byte[] ba) { byte[] fba = new byte[ba.length + 1]; System.arraycopy(ba, 0, fba, 0, ba.length); diff --git a/core/src/main/java/org/apache/accumulo/core/data/KeyBuilder.java b/core/src/main/java/org/apache/accumulo/core/data/KeyBuilder.java index b9798ab64f..b49d9f76c9 100644 --- a/core/src/main/java/org/apache/accumulo/core/data/KeyBuilder.java +++ b/core/src/main/java/org/apache/accumulo/core/data/KeyBuilder.java @@ -100,6 +100,15 @@ public class KeyBuilder { */ ColumnFamilyStep row(final byte[] row); + /** + * Set the row of the {@link Key} that this builder will build to the parameter. + * + * @param row the row to use for the key + * @return this builder + * @since 3.1.0 + */ + ColumnFamilyStep row(final ByteSequence row); + /** * Set the row of the {@link Key} that this builder will build to the parameter. * @@ -136,6 +145,15 @@ public class KeyBuilder { */ ColumnQualifierStep family(final byte[] columnFamily); + /** + * Set the column family of the {@link Key} that this builder will build to the parameter. + * + * @param columnFamily the column family to use for the {@link Key} + * @return this builder + * @since 3.1.0 + */ + ColumnQualifierStep family(final ByteSequence columnFamily); + /** * Set the column family of the {@link Key} that this builder will build to the parameter. * @@ -180,6 +198,15 @@ public class KeyBuilder { */ ColumnVisibilityStep qualifier(final byte[] columnQualifier); + /** + * Set the column qualifier of the {@link Key} that this builder will build to the parameter. + * + * @param columnQualifier the column qualifier to use for the {@link Key} + * @return this builder + * @since 3.1.0 + */ + ColumnVisibilityStep qualifier(final ByteSequence columnQualifier); + /** * Set the column qualifier of the {@link Key} that this builder will build to the parameter. * @@ -225,6 +252,15 @@ public class KeyBuilder { */ Build visibility(final byte[] columnVisibility); + /** + * Set the column qualifier of the {@link Key} that this builder will build to the parameter. + * + * @param columnVisibility the column visibility to use for the {@link Key} + * @return this builder + * @since 3.1.0 + */ + Build visibility(ByteSequence columnVisibility); + /** * Set the column qualifier of the {@link Key} that this builder will build to the parameter. * @@ -312,6 +348,19 @@ public class KeyBuilder { return row(row, 0, row.length); } + @Override + public ColumnFamilyStep row(ByteSequence row) { + if (row.isBackedByArray()) { + this.row = row.getBackingArray(); + this.rowOffset = row.offset(); + } else { + this.row = row.toArray(); + this.rowOffset = 0; + } + this.rowLength = row.length(); + return this; + } + @Override public ColumnFamilyStep row(final Text row) { return row(row.getBytes(), 0, row.getLength()); @@ -335,6 +384,19 @@ public class KeyBuilder { return family(family, 0, family.length); } + @Override + public ColumnQualifierStep family(ByteSequence columnFamily) { + if (columnFamily.isBackedByArray()) { + this.family = columnFamily.getBackingArray(); + this.familyOffset = columnFamily.offset(); + } else { + this.family = columnFamily.toArray(); + this.familyOffset = 0; + } + this.familyLength = columnFamily.length(); + return this; + } + @Override public ColumnQualifierStep family(Text family) { return family(family.getBytes(), 0, family.getLength()); @@ -358,6 +420,19 @@ public class KeyBuilder { return qualifier(qualifier, 0, qualifier.length); } + @Override + public ColumnVisibilityStep qualifier(ByteSequence columnQualifier) { + if (columnQualifier.isBackedByArray()) { + this.qualifier = columnQualifier.getBackingArray(); + this.qualifierOffset = columnQualifier.offset(); + } else { + this.qualifier = columnQualifier.toArray(); + this.qualifierOffset = 0; + } + this.qualifierLength = columnQualifier.length(); + return this; + } + @Override public ColumnVisibilityStep qualifier(Text qualifier) { return qualifier(qualifier.getBytes(), 0, qualifier.getLength()); @@ -381,6 +456,19 @@ public class KeyBuilder { return visibility(visibility, 0, visibility.length); } + @Override + public Build visibility(ByteSequence columnVisibility) { + if (columnVisibility.isBackedByArray()) { + this.visibility = columnVisibility.getBackingArray(); + this.visibilityOffset = columnVisibility.offset(); + } else { + this.visibility = columnVisibility.toArray(); + this.visibilityOffset = 0; + } + this.visibilityLength = columnVisibility.length(); + return this; + } + @Override public Build visibility(Text visibility) { return visibility(visibility.getBytes(), 0, visibility.getLength()); diff --git a/core/src/test/java/org/apache/accumulo/core/data/KeyTest.java b/core/src/test/java/org/apache/accumulo/core/data/KeyTest.java index 4751f45ef6..7b36606b55 100644 --- a/core/src/test/java/org/apache/accumulo/core/data/KeyTest.java +++ b/core/src/test/java/org/apache/accumulo/core/data/KeyTest.java @@ -328,4 +328,54 @@ public class KeyTest { new Key(new Text(row), new Text(colFamily), new Text(colQualifier), colVisibility2, ts); assertEquals(bytesColVisibilityKey2, textColVisibilityKey2); } + + private static class TestByteSequence extends ArrayByteSequence { + + private static final long serialVersionUID = 1234L; + + public TestByteSequence(String s) { + super(s); + } + + @Override + public boolean isBackedByArray() { + return false; + } + } + + @Test + public void testByteSequenceConstructor() { + var row1 = new ArrayByteSequence("Row"); + var row2 = new ArrayByteSequence("TheRowData").subSequence(3, 6); + var row3 = new TestByteSequence("Row"); + + var fam1 = new ArrayByteSequence("Family"); + var fam2 = new ArrayByteSequence("SomeFamilyData").subSequence(4, 10); + var fam3 = new TestByteSequence("Family"); + + var qual1 = new ArrayByteSequence("Qual"); + var qual2 = new ArrayByteSequence("TheQualData").subSequence(3, 7); + var qual3 = new TestByteSequence("Qual"); + + var vis1 = new ArrayByteSequence("Vis"); + var vis2 = new ArrayByteSequence("AVisData").subSequence(1, 4); + var vis3 = new TestByteSequence("Vis"); + + var expectedKey = new Key("Row", "Family", "Qual", "Vis", 4); + + for (var r : List.of(row1, row2, row3)) { + for (var f : List.of(fam1, fam2, fam3)) { + for (var q : List.of(qual1, qual2, qual3)) { + for (var v : List.of(vis1, vis2, vis3)) { + var actualKey = new Key(r, f, q, v, 4); + assertEquals(expectedKey, actualKey); + var actualKey2 = + Key.builder().row(r).family(f).qualifier(q).visibility(v).timestamp(4).build(); + assertEquals(expectedKey, actualKey2); + } + } + } + } + + } }