Skip to content

Commit 99b61f3

Browse files
authored
HBASE-26713 Default to LATEST_TIMESTAMP if no timestamp sent along on Increment/Append (#4074)
Signed-off-by: Andrew Purtell <[email protected]> Signed-off-by: Viraj Jasani <[email protected]>
1 parent 8c60739 commit 99b61f3

File tree

2 files changed

+83
-35
lines changed

2 files changed

+83
-35
lines changed

hbase-client/src/main/java/org/apache/hadoop/hbase/shaded/protobuf/ProtobufUtil.java

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -836,10 +836,7 @@ public static Delete toDelete(final MutationProto proto, final CellScanner cellS
836836
if (qv.hasQualifier()) {
837837
qualifier = qv.getQualifier().toByteArray();
838838
}
839-
long ts = HConstants.LATEST_TIMESTAMP;
840-
if (qv.hasTimestamp()) {
841-
ts = qv.getTimestamp();
842-
}
839+
long ts = cellTimestampOrLatest(qv);
843840
if (deleteType == DeleteType.DELETE_ONE_VERSION) {
844841
delete.addColumn(family, qualifier, ts);
845842
} else if (deleteType == DeleteType.DELETE_MULTIPLE_VERSIONS) {
@@ -906,7 +903,7 @@ private static <T extends Mutation> T toDelta(Function<Bytes, T> supplier, Consu
906903
.setRow(mutation.getRow())
907904
.setFamily(family)
908905
.setQualifier(qualifier)
909-
.setTimestamp(qv.getTimestamp())
906+
.setTimestamp(cellTimestampOrLatest(qv))
910907
.setType(KeyValue.Type.Put.getCode())
911908
.setValue(value)
912909
.setTags(tags)
@@ -921,6 +918,14 @@ private static <T extends Mutation> T toDelta(Function<Bytes, T> supplier, Consu
921918
return mutation;
922919
}
923920

921+
private static long cellTimestampOrLatest(QualifierValue cell) {
922+
if (cell.hasTimestamp()) {
923+
return cell.getTimestamp();
924+
} else {
925+
return HConstants.LATEST_TIMESTAMP;
926+
}
927+
}
928+
924929
/**
925930
* Convert a protocol buffer Mutate to an Append
926931
* @param cellScanner

hbase-client/src/test/java/org/apache/hadoop/hbase/shaded/protobuf/TestProtobufUtil.java

Lines changed: 73 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
import org.apache.hadoop.hbase.ExtendedCellBuilder;
3434
import org.apache.hadoop.hbase.ExtendedCellBuilderFactory;
3535
import org.apache.hadoop.hbase.HBaseClassTestRule;
36+
import org.apache.hadoop.hbase.HConstants;
3637
import org.apache.hadoop.hbase.KeyValue;
3738
import org.apache.hadoop.hbase.PrivateCellUtil;
3839
import org.apache.hadoop.hbase.Tag;
@@ -294,7 +295,22 @@ public void testToCell() {
294295
*/
295296
@Test
296297
public void testIncrement() throws IOException {
297-
long timeStamp = 111111;
298+
299+
MutationProto proto = getIncrementMutation(111111L);
300+
// default fields
301+
assertEquals(MutationProto.Durability.USE_DEFAULT, proto.getDurability());
302+
303+
// set the default value for equal comparison
304+
MutationProto.Builder mutateBuilder = MutationProto.newBuilder(proto);
305+
mutateBuilder.setDurability(MutationProto.Durability.USE_DEFAULT);
306+
307+
Increment increment = ProtobufUtil.toIncrement(proto, null);
308+
mutateBuilder.setTimestamp(increment.getTimestamp());
309+
mutateBuilder.setTimeRange(ProtobufUtil.toTimeRange(increment.getTimeRange()));
310+
assertEquals(mutateBuilder.build(), ProtobufUtil.toMutation(MutationType.INCREMENT, increment));
311+
}
312+
313+
private MutationProto getIncrementMutation(Long timestamp) {
298314
MutationProto.Builder mutateBuilder = MutationProto.newBuilder();
299315
mutateBuilder.setRow(ByteString.copyFromUtf8("row"));
300316
mutateBuilder.setMutateType(MutationProto.MutationType.INCREMENT);
@@ -303,66 +319,93 @@ public void testIncrement() throws IOException {
303319
QualifierValue.Builder qualifierBuilder = QualifierValue.newBuilder();
304320
qualifierBuilder.setQualifier(ByteString.copyFromUtf8("c1"));
305321
qualifierBuilder.setValue(ByteString.copyFrom(Bytes.toBytes(11L)));
306-
qualifierBuilder.setTimestamp(timeStamp);
322+
323+
if (timestamp != null) {
324+
qualifierBuilder.setTimestamp(timestamp);
325+
}
326+
307327
valueBuilder.addQualifierValue(qualifierBuilder.build());
308328
qualifierBuilder.setQualifier(ByteString.copyFromUtf8("c2"));
309329
qualifierBuilder.setValue(ByteString.copyFrom(Bytes.toBytes(22L)));
310330
valueBuilder.addQualifierValue(qualifierBuilder.build());
311331
mutateBuilder.addColumnValue(valueBuilder.build());
312332

313-
MutationProto proto = mutateBuilder.build();
333+
return mutateBuilder.build();
334+
}
335+
336+
/**
337+
* Older clients may not send along a timestamp in the MutationProto. Check that we
338+
* default correctly.
339+
*/
340+
@Test
341+
public void testIncrementNoTimestamp() throws IOException {
342+
MutationProto mutation = getIncrementMutation(null);
343+
Increment increment = ProtobufUtil.toIncrement(mutation, null);
344+
assertEquals(HConstants.LATEST_TIMESTAMP, increment.getTimestamp());
345+
increment.getFamilyCellMap().values()
346+
.forEach(cells ->
347+
cells.forEach(cell ->
348+
assertEquals(HConstants.LATEST_TIMESTAMP, cell.getTimestamp())));
349+
}
350+
351+
/**
352+
* Test Append Mutate conversions.
353+
*
354+
* @throws IOException if converting to an {@link Append} fails
355+
*/
356+
@Test
357+
public void testAppend() throws IOException {
358+
MutationProto proto = getAppendMutation(111111L);
314359
// default fields
315360
assertEquals(MutationProto.Durability.USE_DEFAULT, proto.getDurability());
316361

317362
// set the default value for equal comparison
318-
mutateBuilder = MutationProto.newBuilder(proto);
363+
MutationProto.Builder mutateBuilder = MutationProto.newBuilder(proto);
319364
mutateBuilder.setDurability(MutationProto.Durability.USE_DEFAULT);
320365

321-
Increment increment = ProtobufUtil.toIncrement(proto, null);
322-
mutateBuilder.setTimestamp(increment.getTimestamp());
323-
mutateBuilder.setTimeRange(ProtobufUtil.toTimeRange(increment.getTimeRange()));
324-
assertEquals(mutateBuilder.build(), ProtobufUtil.toMutation(MutationType.INCREMENT, increment));
366+
Append append = ProtobufUtil.toAppend(proto, null);
367+
368+
// append always use the latest timestamp,
369+
// reset the timestamp to the original mutate
370+
mutateBuilder.setTimestamp(append.getTimestamp());
371+
mutateBuilder.setTimeRange(ProtobufUtil.toTimeRange(append.getTimeRange()));
372+
assertEquals(mutateBuilder.build(), ProtobufUtil.toMutation(MutationType.APPEND, append));
325373
}
326374

327375
/**
328-
* Test Append Mutate conversions.
329-
*
330-
* @throws IOException if converting to an {@link Append} fails
376+
* Older clients may not send along a timestamp in the MutationProto. Check that we
377+
* default correctly.
331378
*/
332379
@Test
333-
public void testAppend() throws IOException {
334-
long timeStamp = 111111;
380+
public void testAppendNoTimestamp() throws IOException {
381+
MutationProto mutation = getAppendMutation(null);
382+
Append append = ProtobufUtil.toAppend(mutation, null);
383+
assertEquals(HConstants.LATEST_TIMESTAMP, append.getTimestamp());
384+
append.getFamilyCellMap().values().forEach(cells -> cells.forEach(cell -> assertEquals(HConstants.LATEST_TIMESTAMP, cell.getTimestamp())));
385+
}
386+
387+
private MutationProto getAppendMutation(Long timestamp) {
335388
MutationProto.Builder mutateBuilder = MutationProto.newBuilder();
336389
mutateBuilder.setRow(ByteString.copyFromUtf8("row"));
337390
mutateBuilder.setMutateType(MutationType.APPEND);
338-
mutateBuilder.setTimestamp(timeStamp);
391+
if (timestamp != null) {
392+
mutateBuilder.setTimestamp(timestamp);
393+
}
339394
ColumnValue.Builder valueBuilder = ColumnValue.newBuilder();
340395
valueBuilder.setFamily(ByteString.copyFromUtf8("f1"));
341396
QualifierValue.Builder qualifierBuilder = QualifierValue.newBuilder();
342397
qualifierBuilder.setQualifier(ByteString.copyFromUtf8("c1"));
343398
qualifierBuilder.setValue(ByteString.copyFromUtf8("v1"));
344-
qualifierBuilder.setTimestamp(timeStamp);
399+
if (timestamp != null) {
400+
qualifierBuilder.setTimestamp(timestamp);
401+
}
345402
valueBuilder.addQualifierValue(qualifierBuilder.build());
346403
qualifierBuilder.setQualifier(ByteString.copyFromUtf8("c2"));
347404
qualifierBuilder.setValue(ByteString.copyFromUtf8("v2"));
348405
valueBuilder.addQualifierValue(qualifierBuilder.build());
349406
mutateBuilder.addColumnValue(valueBuilder.build());
350407

351-
MutationProto proto = mutateBuilder.build();
352-
// default fields
353-
assertEquals(MutationProto.Durability.USE_DEFAULT, proto.getDurability());
354-
355-
// set the default value for equal comparison
356-
mutateBuilder = MutationProto.newBuilder(proto);
357-
mutateBuilder.setDurability(MutationProto.Durability.USE_DEFAULT);
358-
359-
Append append = ProtobufUtil.toAppend(proto, null);
360-
361-
// append always use the latest timestamp,
362-
// reset the timestamp to the original mutate
363-
mutateBuilder.setTimestamp(append.getTimestamp());
364-
mutateBuilder.setTimeRange(ProtobufUtil.toTimeRange(append.getTimeRange()));
365-
assertEquals(mutateBuilder.build(), ProtobufUtil.toMutation(MutationType.APPEND, append));
408+
return mutateBuilder.build();
366409
}
367410

368411
private static ProcedureProtos.Procedure.Builder createProcedureBuilder(long procId) {

0 commit comments

Comments
 (0)