Skip to content

Commit cdf30d0

Browse files
Adds ByteSequence constructors to Key (apache#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 <ctubbsii@apache.org>
1 parent da5fcb9 commit cdf30d0

File tree

3 files changed

+195
-0
lines changed

3 files changed

+195
-0
lines changed

core/src/main/java/org/apache/accumulo/core/data/Key.java

+57
Original file line numberDiff line numberDiff line change
@@ -552,6 +552,63 @@ public Key(CharSequence row, CharSequence cf, CharSequence cq, ColumnVisibility
552552
new Text(cv.getExpression()), ts);
553553
}
554554

555+
/**
556+
* Creates a key with the specified row, the specified column family, the specified column
557+
* qualifier, the specified column visibility, the specified timestamp, and delete marker false.
558+
* This constructor creates a copy of the fields.
559+
* <p>
560+
* To avoid copying, use
561+
* {@link Key#Key(byte[] row, byte[] cf, byte[] cq, byte[] cv, long ts, boolean deleted, boolean copy)}
562+
* instead.
563+
*
564+
* @see #builder()
565+
* @since 3.1.0
566+
*/
567+
public Key(ByteSequence row, ByteSequence cf, ByteSequence cq, ByteSequence cv, long ts) {
568+
byte[] rowBytes, cfBytes, cqBytes, cvBytes;
569+
int rowOffset, cfOffset, cqOffset, cvOffset;
570+
int rowLen, cfLen, cqLen, cvLen;
571+
572+
if (row.isBackedByArray()) {
573+
rowBytes = row.getBackingArray();
574+
rowOffset = row.offset();
575+
} else {
576+
rowBytes = row.toArray();
577+
rowOffset = 0;
578+
}
579+
rowLen = row.length();
580+
581+
if (cf.isBackedByArray()) {
582+
cfBytes = cf.getBackingArray();
583+
cfOffset = cf.offset();
584+
} else {
585+
cfBytes = cf.toArray();
586+
cfOffset = 0;
587+
}
588+
cfLen = cf.length();
589+
590+
if (cq.isBackedByArray()) {
591+
cqBytes = cq.getBackingArray();
592+
cqOffset = cq.offset();
593+
} else {
594+
cqBytes = cq.toArray();
595+
cqOffset = 0;
596+
}
597+
cqLen = cq.length();
598+
599+
if (cv.isBackedByArray()) {
600+
cvBytes = cv.getBackingArray();
601+
cvOffset = cv.offset();
602+
} else {
603+
cvBytes = cv.toArray();
604+
cvOffset = 0;
605+
}
606+
cvLen = cv.length();
607+
608+
init(rowBytes, rowOffset, rowLen, cfBytes, cfOffset, cfLen, cqBytes, cqOffset, cqLen, cvBytes,
609+
cvOffset, cvLen, ts, false, true);
610+
}
611+
555612
private byte[] followingArray(byte[] ba) {
556613
byte[] fba = new byte[ba.length + 1];
557614
System.arraycopy(ba, 0, fba, 0, ba.length);

core/src/main/java/org/apache/accumulo/core/data/KeyBuilder.java

+88
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,15 @@ public interface RowStep extends Build {
100100
*/
101101
ColumnFamilyStep row(final byte[] row);
102102

103+
/**
104+
* Set the row of the {@link Key} that this builder will build to the parameter.
105+
*
106+
* @param row the row to use for the key
107+
* @return this builder
108+
* @since 3.1.0
109+
*/
110+
ColumnFamilyStep row(final ByteSequence row);
111+
103112
/**
104113
* Set the row of the {@link Key} that this builder will build to the parameter.
105114
*
@@ -136,6 +145,15 @@ public interface ColumnFamilyStep extends ColumnVisibilityStep {
136145
*/
137146
ColumnQualifierStep family(final byte[] columnFamily);
138147

148+
/**
149+
* Set the column family of the {@link Key} that this builder will build to the parameter.
150+
*
151+
* @param columnFamily the column family to use for the {@link Key}
152+
* @return this builder
153+
* @since 3.1.0
154+
*/
155+
ColumnQualifierStep family(final ByteSequence columnFamily);
156+
139157
/**
140158
* Set the column family of the {@link Key} that this builder will build to the parameter.
141159
*
@@ -180,6 +198,15 @@ public interface ColumnQualifierStep extends ColumnVisibilityStep {
180198
*/
181199
ColumnVisibilityStep qualifier(final byte[] columnQualifier);
182200

201+
/**
202+
* Set the column qualifier of the {@link Key} that this builder will build to the parameter.
203+
*
204+
* @param columnQualifier the column qualifier to use for the {@link Key}
205+
* @return this builder
206+
* @since 3.1.0
207+
*/
208+
ColumnVisibilityStep qualifier(final ByteSequence columnQualifier);
209+
183210
/**
184211
* Set the column qualifier of the {@link Key} that this builder will build to the parameter.
185212
*
@@ -225,6 +252,15 @@ public interface ColumnVisibilityStep extends Build {
225252
*/
226253
Build visibility(final byte[] columnVisibility);
227254

255+
/**
256+
* Set the column qualifier of the {@link Key} that this builder will build to the parameter.
257+
*
258+
* @param columnVisibility the column visibility to use for the {@link Key}
259+
* @return this builder
260+
* @since 3.1.0
261+
*/
262+
Build visibility(ByteSequence columnVisibility);
263+
228264
/**
229265
* Set the column qualifier of the {@link Key} that this builder will build to the parameter.
230266
*
@@ -312,6 +348,19 @@ public ColumnFamilyStep row(final byte[] row) {
312348
return row(row, 0, row.length);
313349
}
314350

351+
@Override
352+
public ColumnFamilyStep row(ByteSequence row) {
353+
if (row.isBackedByArray()) {
354+
this.row = row.getBackingArray();
355+
this.rowOffset = row.offset();
356+
} else {
357+
this.row = row.toArray();
358+
this.rowOffset = 0;
359+
}
360+
this.rowLength = row.length();
361+
return this;
362+
}
363+
315364
@Override
316365
public ColumnFamilyStep row(final Text row) {
317366
return row(row.getBytes(), 0, row.getLength());
@@ -335,6 +384,19 @@ public ColumnQualifierStep family(final byte[] family) {
335384
return family(family, 0, family.length);
336385
}
337386

387+
@Override
388+
public ColumnQualifierStep family(ByteSequence columnFamily) {
389+
if (columnFamily.isBackedByArray()) {
390+
this.family = columnFamily.getBackingArray();
391+
this.familyOffset = columnFamily.offset();
392+
} else {
393+
this.family = columnFamily.toArray();
394+
this.familyOffset = 0;
395+
}
396+
this.familyLength = columnFamily.length();
397+
return this;
398+
}
399+
338400
@Override
339401
public ColumnQualifierStep family(Text family) {
340402
return family(family.getBytes(), 0, family.getLength());
@@ -358,6 +420,19 @@ public ColumnVisibilityStep qualifier(final byte[] qualifier) {
358420
return qualifier(qualifier, 0, qualifier.length);
359421
}
360422

423+
@Override
424+
public ColumnVisibilityStep qualifier(ByteSequence columnQualifier) {
425+
if (columnQualifier.isBackedByArray()) {
426+
this.qualifier = columnQualifier.getBackingArray();
427+
this.qualifierOffset = columnQualifier.offset();
428+
} else {
429+
this.qualifier = columnQualifier.toArray();
430+
this.qualifierOffset = 0;
431+
}
432+
this.qualifierLength = columnQualifier.length();
433+
return this;
434+
}
435+
361436
@Override
362437
public ColumnVisibilityStep qualifier(Text qualifier) {
363438
return qualifier(qualifier.getBytes(), 0, qualifier.getLength());
@@ -381,6 +456,19 @@ public Build visibility(final byte[] visibility) {
381456
return visibility(visibility, 0, visibility.length);
382457
}
383458

459+
@Override
460+
public Build visibility(ByteSequence columnVisibility) {
461+
if (columnVisibility.isBackedByArray()) {
462+
this.visibility = columnVisibility.getBackingArray();
463+
this.visibilityOffset = columnVisibility.offset();
464+
} else {
465+
this.visibility = columnVisibility.toArray();
466+
this.visibilityOffset = 0;
467+
}
468+
this.visibilityLength = columnVisibility.length();
469+
return this;
470+
}
471+
384472
@Override
385473
public Build visibility(Text visibility) {
386474
return visibility(visibility.getBytes(), 0, visibility.getLength());

core/src/test/java/org/apache/accumulo/core/data/KeyTest.java

+50
Original file line numberDiff line numberDiff line change
@@ -328,4 +328,54 @@ public void testBytesText() {
328328
new Key(new Text(row), new Text(colFamily), new Text(colQualifier), colVisibility2, ts);
329329
assertEquals(bytesColVisibilityKey2, textColVisibilityKey2);
330330
}
331+
332+
private static class TestByteSequence extends ArrayByteSequence {
333+
334+
private static final long serialVersionUID = 1234L;
335+
336+
public TestByteSequence(String s) {
337+
super(s);
338+
}
339+
340+
@Override
341+
public boolean isBackedByArray() {
342+
return false;
343+
}
344+
}
345+
346+
@Test
347+
public void testByteSequenceConstructor() {
348+
var row1 = new ArrayByteSequence("Row");
349+
var row2 = new ArrayByteSequence("TheRowData").subSequence(3, 6);
350+
var row3 = new TestByteSequence("Row");
351+
352+
var fam1 = new ArrayByteSequence("Family");
353+
var fam2 = new ArrayByteSequence("SomeFamilyData").subSequence(4, 10);
354+
var fam3 = new TestByteSequence("Family");
355+
356+
var qual1 = new ArrayByteSequence("Qual");
357+
var qual2 = new ArrayByteSequence("TheQualData").subSequence(3, 7);
358+
var qual3 = new TestByteSequence("Qual");
359+
360+
var vis1 = new ArrayByteSequence("Vis");
361+
var vis2 = new ArrayByteSequence("AVisData").subSequence(1, 4);
362+
var vis3 = new TestByteSequence("Vis");
363+
364+
var expectedKey = new Key("Row", "Family", "Qual", "Vis", 4);
365+
366+
for (var r : List.of(row1, row2, row3)) {
367+
for (var f : List.of(fam1, fam2, fam3)) {
368+
for (var q : List.of(qual1, qual2, qual3)) {
369+
for (var v : List.of(vis1, vis2, vis3)) {
370+
var actualKey = new Key(r, f, q, v, 4);
371+
assertEquals(expectedKey, actualKey);
372+
var actualKey2 =
373+
Key.builder().row(r).family(f).qualifier(q).visibility(v).timestamp(4).build();
374+
assertEquals(expectedKey, actualKey2);
375+
}
376+
}
377+
}
378+
}
379+
380+
}
331381
}

0 commit comments

Comments
 (0)