001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.apache.hadoop.hbase.client; 019 020import static org.apache.hadoop.hbase.HConstants.RPC_CODEC_CONF_KEY; 021import static org.apache.hadoop.hbase.ipc.RpcClient.DEFAULT_CODEC_CLASS; 022import static org.junit.Assert.assertEquals; 023import static org.junit.Assert.assertNotEquals; 024import static org.junit.Assert.assertNotNull; 025import static org.junit.Assert.assertTrue; 026import static org.junit.Assert.fail; 027 028import java.io.IOException; 029import java.util.ArrayList; 030import java.util.Collections; 031import java.util.HashMap; 032import java.util.List; 033import java.util.Map; 034import org.apache.hadoop.conf.Configuration; 035import org.apache.hadoop.hbase.Cell; 036import org.apache.hadoop.hbase.CellBuilderType; 037import org.apache.hadoop.hbase.DoNotRetryIOException; 038import org.apache.hadoop.hbase.ExtendedCellBuilderFactory; 039import org.apache.hadoop.hbase.HBaseClassTestRule; 040import org.apache.hadoop.hbase.HBaseTestingUtil; 041import org.apache.hadoop.hbase.HConstants; 042import org.apache.hadoop.hbase.KeyValue; 043import org.apache.hadoop.hbase.PrivateCellUtil; 044import org.apache.hadoop.hbase.TableName; 045import org.apache.hadoop.hbase.Tag; 046import org.apache.hadoop.hbase.TagType; 047import org.apache.hadoop.hbase.codec.KeyValueCodecWithTags; 048import org.apache.hadoop.hbase.coprocessor.CoprocessorHost; 049import org.apache.hadoop.hbase.coprocessor.MultiRowMutationEndpoint; 050import org.apache.hadoop.hbase.testclassification.LargeTests; 051import org.apache.hadoop.hbase.util.Bytes; 052import org.junit.AfterClass; 053import org.junit.BeforeClass; 054import org.junit.ClassRule; 055import org.junit.Rule; 056import org.junit.Test; 057import org.junit.experimental.categories.Category; 058import org.junit.rules.TestName; 059import org.slf4j.Logger; 060import org.slf4j.LoggerFactory; 061 062/** 063 * Run Increment tests that use the HBase clients; {@link TableBuilder}. Test is parameterized to 064 * run the slow and fast increment code paths. If fast, in the @before, we do a rolling restart of 065 * the single regionserver so that it can pick up the go fast configuration. Doing it this way 066 * should be faster than starting/stopping a cluster per test. Test takes a long time because spin 067 * up a cluster between each run -- ugh. 068 */ 069@Category(LargeTests.class) 070public class TestIncrementsFromClientSide { 071 072 @ClassRule 073 public static final HBaseClassTestRule CLASS_RULE = 074 HBaseClassTestRule.forClass(TestIncrementsFromClientSide.class); 075 076 final Logger LOG = LoggerFactory.getLogger(getClass()); 077 protected final static HBaseTestingUtil TEST_UTIL = new HBaseTestingUtil(); 078 private static byte[] ROW = Bytes.toBytes("testRow"); 079 private static byte[] FAMILY = Bytes.toBytes("testFamily"); 080 private static byte[] QUALIFIER = Bytes.toBytes("testQualifier"); 081 // This test depends on there being only one slave running at at a time. See the @Before 082 // method where we do rolling restart. 083 protected static int SLAVES = 1; 084 @Rule 085 public TestName name = new TestName(); 086 087 @BeforeClass 088 public static void beforeClass() throws Exception { 089 Configuration conf = TEST_UTIL.getConfiguration(); 090 conf.setStrings(CoprocessorHost.REGION_COPROCESSOR_CONF_KEY, 091 MultiRowMutationEndpoint.class.getName()); 092 // We need more than one region server in this test 093 TEST_UTIL.startMiniCluster(SLAVES); 094 } 095 096 /** 097 * @throws java.lang.Exception 098 */ 099 @AfterClass 100 public static void afterClass() throws Exception { 101 TEST_UTIL.shutdownMiniCluster(); 102 } 103 104 /** 105 * Test increment result when there are duplicate rpc request. 106 */ 107 @Test 108 public void testDuplicateIncrement() throws Exception { 109 TableDescriptorBuilder builder = 110 TEST_UTIL.createModifyableTableDescriptor(name.getMethodName()); 111 Map<String, String> kvs = new HashMap<>(); 112 kvs.put(SleepAtFirstRpcCall.SLEEP_TIME_CONF_KEY, "2000"); 113 builder.setCoprocessor(CoprocessorDescriptorBuilder 114 .newBuilder(SleepAtFirstRpcCall.class.getName()).setPriority(1).setProperties(kvs).build()); 115 TEST_UTIL.createTable(builder.build(), new byte[][] { ROW }).close(); 116 117 Configuration c = new Configuration(TEST_UTIL.getConfiguration()); 118 c.setInt(HConstants.HBASE_CLIENT_PAUSE, 50); 119 // Client will retry beacuse rpc timeout is small than the sleep time of first rpc call 120 c.setInt(HConstants.HBASE_RPC_TIMEOUT_KEY, 1500); 121 122 try (Connection connection = ConnectionFactory.createConnection(c); 123 Table table = connection.getTableBuilder(TableName.valueOf(name.getMethodName()), null) 124 .setOperationTimeout(3 * 1000).build()) { 125 Increment inc = new Increment(ROW); 126 inc.addColumn(HBaseTestingUtil.fam1, QUALIFIER, 1); 127 Result result = table.increment(inc); 128 129 Cell[] cells = result.rawCells(); 130 assertEquals(1, cells.length); 131 assertIncrementKey(cells[0], ROW, HBaseTestingUtil.fam1, QUALIFIER, 1); 132 133 // Verify expected result 134 Result readResult = table.get(new Get(ROW)); 135 cells = readResult.rawCells(); 136 assertEquals(1, cells.length); 137 assertIncrementKey(cells[0], ROW, HBaseTestingUtil.fam1, QUALIFIER, 1); 138 } 139 } 140 141 /** 142 * Test batch increment result when there are duplicate rpc request. 143 */ 144 @Test 145 public void testDuplicateBatchIncrement() throws Exception { 146 TableDescriptorBuilder builder = 147 TEST_UTIL.createModifyableTableDescriptor(name.getMethodName()); 148 Map<String, String> kvs = new HashMap<>(); 149 kvs.put(SleepAtFirstRpcCall.SLEEP_TIME_CONF_KEY, "2000"); 150 builder.setCoprocessor(CoprocessorDescriptorBuilder 151 .newBuilder(SleepAtFirstRpcCall.class.getName()).setPriority(1).setProperties(kvs).build()); 152 TEST_UTIL.createTable(builder.build(), new byte[][] { ROW }).close(); 153 154 Configuration c = new Configuration(TEST_UTIL.getConfiguration()); 155 c.setInt(HConstants.HBASE_CLIENT_PAUSE, 50); 156 // Client will retry beacuse rpc timeout is small than the sleep time of first rpc call 157 c.setInt(HConstants.HBASE_RPC_TIMEOUT_KEY, 1500); 158 159 try (Connection connection = ConnectionFactory.createConnection(c); 160 Table table = connection.getTableBuilder(TableName.valueOf(name.getMethodName()), null) 161 .setOperationTimeout(3 * 1000).build()) { 162 Increment inc = new Increment(ROW); 163 inc.addColumn(HBaseTestingUtil.fam1, QUALIFIER, 1); 164 165 // Batch increment 166 Object[] results = new Object[1]; 167 table.batch(Collections.singletonList(inc), results); 168 169 Cell[] cells = ((Result) results[0]).rawCells(); 170 assertEquals(1, cells.length); 171 assertIncrementKey(cells[0], ROW, HBaseTestingUtil.fam1, QUALIFIER, 1); 172 173 // Verify expected result 174 Result readResult = table.get(new Get(ROW)); 175 cells = readResult.rawCells(); 176 assertEquals(1, cells.length); 177 assertIncrementKey(cells[0], ROW, HBaseTestingUtil.fam1, QUALIFIER, 1); 178 } 179 } 180 181 @Test 182 public void testIncrementWithDeletes() throws Exception { 183 LOG.info("Starting " + this.name.getMethodName()); 184 final TableName TABLENAME = 185 TableName.valueOf(filterStringSoTableNameSafe(this.name.getMethodName())); 186 Table ht = TEST_UTIL.createTable(TABLENAME, FAMILY); 187 final byte[] COLUMN = Bytes.toBytes("column"); 188 189 ht.incrementColumnValue(ROW, FAMILY, COLUMN, 5); 190 TEST_UTIL.flush(TABLENAME); 191 192 Delete del = new Delete(ROW); 193 ht.delete(del); 194 195 ht.incrementColumnValue(ROW, FAMILY, COLUMN, 5); 196 197 Get get = new Get(ROW); 198 Result r = ht.get(get); 199 assertEquals(1, r.size()); 200 assertEquals(5, Bytes.toLong(r.getValue(FAMILY, COLUMN))); 201 } 202 203 @Test 204 public void testIncrementingInvalidValue() throws Exception { 205 LOG.info("Starting " + this.name.getMethodName()); 206 final TableName TABLENAME = 207 TableName.valueOf(filterStringSoTableNameSafe(this.name.getMethodName())); 208 Table ht = TEST_UTIL.createTable(TABLENAME, FAMILY); 209 final byte[] COLUMN = Bytes.toBytes("column"); 210 Put p = new Put(ROW); 211 // write an integer here (not a Long) 212 p.addColumn(FAMILY, COLUMN, Bytes.toBytes(5)); 213 ht.put(p); 214 try { 215 ht.incrementColumnValue(ROW, FAMILY, COLUMN, 5); 216 fail("Should have thrown DoNotRetryIOException"); 217 } catch (DoNotRetryIOException iox) { 218 // success 219 } 220 Increment inc = new Increment(ROW); 221 inc.addColumn(FAMILY, COLUMN, 5); 222 try { 223 ht.increment(inc); 224 fail("Should have thrown DoNotRetryIOException"); 225 } catch (DoNotRetryIOException iox) { 226 // success 227 } 228 } 229 230 @Test 231 public void testBatchIncrementsWithReturnResultFalse() throws Exception { 232 LOG.info("Starting testBatchIncrementsWithReturnResultFalse"); 233 final TableName tableName = TableName.valueOf(name.getMethodName()); 234 Table table = TEST_UTIL.createTable(tableName, FAMILY); 235 Increment inc1 = new Increment(Bytes.toBytes("row2")); 236 inc1.setReturnResults(false); 237 inc1.addColumn(FAMILY, Bytes.toBytes("f1"), 1); 238 Increment inc2 = new Increment(Bytes.toBytes("row2")); 239 inc2.setReturnResults(false); 240 inc2.addColumn(FAMILY, Bytes.toBytes("f1"), 1); 241 List<Increment> incs = new ArrayList<>(); 242 incs.add(inc1); 243 incs.add(inc2); 244 Object[] results = new Object[2]; 245 table.batch(incs, results); 246 assertTrue(results.length == 2); 247 for (Object r : results) { 248 Result result = (Result) r; 249 assertTrue(result.isEmpty()); 250 } 251 table.close(); 252 } 253 254 @Test 255 public void testIncrementInvalidArguments() throws Exception { 256 LOG.info("Starting " + this.name.getMethodName()); 257 final TableName TABLENAME = 258 TableName.valueOf(filterStringSoTableNameSafe(this.name.getMethodName())); 259 Table ht = TEST_UTIL.createTable(TABLENAME, FAMILY); 260 final byte[] COLUMN = Bytes.toBytes("column"); 261 try { 262 // try null row 263 ht.incrementColumnValue(null, FAMILY, COLUMN, 5); 264 fail("Should have thrown NPE/IOE"); 265 } catch (NullPointerException | IOException error) { 266 // success 267 } 268 try { 269 // try null family 270 ht.incrementColumnValue(ROW, null, COLUMN, 5); 271 fail("Should have thrown NPE/IOE"); 272 } catch (NullPointerException | IOException error) { 273 // success 274 } 275 // try null row 276 try { 277 Increment incNoRow = new Increment((byte[]) null); 278 incNoRow.addColumn(FAMILY, COLUMN, 5); 279 fail("Should have thrown IAE/NPE"); 280 } catch (IllegalArgumentException | NullPointerException error) { 281 // success 282 } 283 // try null family 284 try { 285 Increment incNoFamily = new Increment(ROW); 286 incNoFamily.addColumn(null, COLUMN, 5); 287 fail("Should have thrown IAE"); 288 } catch (IllegalArgumentException iax) { 289 // success 290 } 291 } 292 293 @Test 294 public void testIncrementOutOfOrder() throws Exception { 295 LOG.info("Starting " + this.name.getMethodName()); 296 final TableName TABLENAME = 297 TableName.valueOf(filterStringSoTableNameSafe(this.name.getMethodName())); 298 Table ht = TEST_UTIL.createTable(TABLENAME, FAMILY); 299 300 byte[][] QUALIFIERS = 301 new byte[][] { Bytes.toBytes("B"), Bytes.toBytes("A"), Bytes.toBytes("C") }; 302 303 Increment inc = new Increment(ROW); 304 for (int i = 0; i < QUALIFIERS.length; i++) { 305 inc.addColumn(FAMILY, QUALIFIERS[i], 1); 306 } 307 ht.increment(inc); 308 309 // Verify expected results 310 Get get = new Get(ROW); 311 Result r = ht.get(get); 312 Cell[] kvs = r.rawCells(); 313 assertEquals(3, kvs.length); 314 assertIncrementKey(kvs[0], ROW, FAMILY, QUALIFIERS[1], 1); 315 assertIncrementKey(kvs[1], ROW, FAMILY, QUALIFIERS[0], 1); 316 assertIncrementKey(kvs[2], ROW, FAMILY, QUALIFIERS[2], 1); 317 318 // Now try multiple columns again 319 inc = new Increment(ROW); 320 for (int i = 0; i < QUALIFIERS.length; i++) { 321 inc.addColumn(FAMILY, QUALIFIERS[i], 1); 322 } 323 ht.increment(inc); 324 325 // Verify 326 r = ht.get(get); 327 kvs = r.rawCells(); 328 assertEquals(3, kvs.length); 329 assertIncrementKey(kvs[0], ROW, FAMILY, QUALIFIERS[1], 2); 330 assertIncrementKey(kvs[1], ROW, FAMILY, QUALIFIERS[0], 2); 331 assertIncrementKey(kvs[2], ROW, FAMILY, QUALIFIERS[2], 2); 332 } 333 334 @Test 335 public void testIncrementOnSameColumn() throws Exception { 336 LOG.info("Starting " + this.name.getMethodName()); 337 final byte[] TABLENAME = Bytes.toBytes(filterStringSoTableNameSafe(this.name.getMethodName())); 338 Table ht = TEST_UTIL.createTable(TableName.valueOf(TABLENAME), FAMILY); 339 340 byte[][] QUALIFIERS = 341 new byte[][] { Bytes.toBytes("A"), Bytes.toBytes("B"), Bytes.toBytes("C") }; 342 343 Increment inc = new Increment(ROW); 344 for (int i = 0; i < QUALIFIERS.length; i++) { 345 inc.addColumn(FAMILY, QUALIFIERS[i], 1); 346 inc.addColumn(FAMILY, QUALIFIERS[i], 1); 347 } 348 ht.increment(inc); 349 350 // Verify expected results 351 Get get = new Get(ROW); 352 Result r = ht.get(get); 353 Cell[] kvs = r.rawCells(); 354 assertEquals(3, kvs.length); 355 assertIncrementKey(kvs[0], ROW, FAMILY, QUALIFIERS[0], 1); 356 assertIncrementKey(kvs[1], ROW, FAMILY, QUALIFIERS[1], 1); 357 assertIncrementKey(kvs[2], ROW, FAMILY, QUALIFIERS[2], 1); 358 359 // Now try multiple columns again 360 inc = new Increment(ROW); 361 for (int i = 0; i < QUALIFIERS.length; i++) { 362 inc.addColumn(FAMILY, QUALIFIERS[i], 1); 363 inc.addColumn(FAMILY, QUALIFIERS[i], 1); 364 } 365 ht.increment(inc); 366 367 // Verify 368 r = ht.get(get); 369 kvs = r.rawCells(); 370 assertEquals(3, kvs.length); 371 assertIncrementKey(kvs[0], ROW, FAMILY, QUALIFIERS[0], 2); 372 assertIncrementKey(kvs[1], ROW, FAMILY, QUALIFIERS[1], 2); 373 assertIncrementKey(kvs[2], ROW, FAMILY, QUALIFIERS[2], 2); 374 375 ht.close(); 376 } 377 378 @Test 379 public void testIncrementIncrZeroAtFirst() throws Exception { 380 LOG.info("Starting " + this.name.getMethodName()); 381 final TableName TABLENAME = 382 TableName.valueOf(filterStringSoTableNameSafe(this.name.getMethodName())); 383 Table ht = TEST_UTIL.createTable(TABLENAME, FAMILY); 384 385 byte[] col1 = Bytes.toBytes("col1"); 386 byte[] col2 = Bytes.toBytes("col2"); 387 byte[] col3 = Bytes.toBytes("col3"); 388 389 // Now increment zero at first time incr 390 Increment inc = new Increment(ROW); 391 inc.addColumn(FAMILY, col1, 0); 392 ht.increment(inc); 393 394 // Verify expected results 395 Get get = new Get(ROW); 396 Result r = ht.get(get); 397 Cell[] kvs = r.rawCells(); 398 assertEquals(1, kvs.length); 399 assertNotNull(kvs[0]); 400 assertIncrementKey(kvs[0], ROW, FAMILY, col1, 0); 401 402 // Now try multiple columns by different amounts 403 inc = new Increment(ROW); 404 inc.addColumn(FAMILY, col1, 1); 405 inc.addColumn(FAMILY, col2, 0); 406 inc.addColumn(FAMILY, col3, 2); 407 ht.increment(inc); 408 // Verify 409 get = new Get(ROW); 410 r = ht.get(get); 411 kvs = r.rawCells(); 412 assertEquals(3, kvs.length); 413 assertNotNull(kvs[0]); 414 assertNotNull(kvs[1]); 415 assertNotNull(kvs[2]); 416 assertIncrementKey(kvs[0], ROW, FAMILY, col1, 1); 417 assertIncrementKey(kvs[1], ROW, FAMILY, col2, 0); 418 assertIncrementKey(kvs[2], ROW, FAMILY, col3, 2); 419 } 420 421 @Test 422 public void testIncrement() throws Exception { 423 LOG.info("Starting " + this.name.getMethodName()); 424 final TableName TABLENAME = 425 TableName.valueOf(filterStringSoTableNameSafe(this.name.getMethodName())); 426 Table ht = TEST_UTIL.createTable(TABLENAME, FAMILY); 427 428 byte[][] ROWS = new byte[][] { Bytes.toBytes("a"), Bytes.toBytes("b"), Bytes.toBytes("c"), 429 Bytes.toBytes("d"), Bytes.toBytes("e"), Bytes.toBytes("f"), Bytes.toBytes("g"), 430 Bytes.toBytes("h"), Bytes.toBytes("i") }; 431 byte[][] QUALIFIERS = new byte[][] { Bytes.toBytes("a"), Bytes.toBytes("b"), Bytes.toBytes("c"), 432 Bytes.toBytes("d"), Bytes.toBytes("e"), Bytes.toBytes("f"), Bytes.toBytes("g"), 433 Bytes.toBytes("h"), Bytes.toBytes("i") }; 434 435 // Do some simple single-column increments 436 437 // First with old API 438 ht.incrementColumnValue(ROW, FAMILY, QUALIFIERS[0], 1); 439 ht.incrementColumnValue(ROW, FAMILY, QUALIFIERS[1], 2); 440 ht.incrementColumnValue(ROW, FAMILY, QUALIFIERS[2], 3); 441 ht.incrementColumnValue(ROW, FAMILY, QUALIFIERS[3], 4); 442 443 // Now increment things incremented with old and do some new 444 Increment inc = new Increment(ROW); 445 inc.addColumn(FAMILY, QUALIFIERS[1], 1); 446 inc.addColumn(FAMILY, QUALIFIERS[3], 1); 447 inc.addColumn(FAMILY, QUALIFIERS[4], 1); 448 ht.increment(inc); 449 450 // Verify expected results 451 Get get = new Get(ROW); 452 Result r = ht.get(get); 453 Cell[] kvs = r.rawCells(); 454 assertEquals(5, kvs.length); 455 assertIncrementKey(kvs[0], ROW, FAMILY, QUALIFIERS[0], 1); 456 assertIncrementKey(kvs[1], ROW, FAMILY, QUALIFIERS[1], 3); 457 assertIncrementKey(kvs[2], ROW, FAMILY, QUALIFIERS[2], 3); 458 assertIncrementKey(kvs[3], ROW, FAMILY, QUALIFIERS[3], 5); 459 assertIncrementKey(kvs[4], ROW, FAMILY, QUALIFIERS[4], 1); 460 461 // Now try multiple columns by different amounts 462 inc = new Increment(ROWS[0]); 463 for (int i = 0; i < QUALIFIERS.length; i++) { 464 inc.addColumn(FAMILY, QUALIFIERS[i], i + 1); 465 } 466 ht.increment(inc); 467 // Verify 468 get = new Get(ROWS[0]); 469 r = ht.get(get); 470 kvs = r.rawCells(); 471 assertEquals(QUALIFIERS.length, kvs.length); 472 for (int i = 0; i < QUALIFIERS.length; i++) { 473 assertIncrementKey(kvs[i], ROWS[0], FAMILY, QUALIFIERS[i], i + 1); 474 } 475 476 // Re-increment them 477 inc = new Increment(ROWS[0]); 478 for (int i = 0; i < QUALIFIERS.length; i++) { 479 inc.addColumn(FAMILY, QUALIFIERS[i], i + 1); 480 } 481 ht.increment(inc); 482 // Verify 483 r = ht.get(get); 484 kvs = r.rawCells(); 485 assertEquals(QUALIFIERS.length, kvs.length); 486 for (int i = 0; i < QUALIFIERS.length; i++) { 487 assertIncrementKey(kvs[i], ROWS[0], FAMILY, QUALIFIERS[i], 2 * (i + 1)); 488 } 489 490 // Verify that an Increment of an amount of zero, returns current count; i.e. same as for above 491 // test, that is: 2 * (i + 1). 492 inc = new Increment(ROWS[0]); 493 for (int i = 0; i < QUALIFIERS.length; i++) { 494 inc.addColumn(FAMILY, QUALIFIERS[i], 0); 495 } 496 ht.increment(inc); 497 r = ht.get(get); 498 kvs = r.rawCells(); 499 assertEquals(QUALIFIERS.length, kvs.length); 500 for (int i = 0; i < QUALIFIERS.length; i++) { 501 assertIncrementKey(kvs[i], ROWS[0], FAMILY, QUALIFIERS[i], 2 * (i + 1)); 502 } 503 } 504 505 @Test 506 public void testIncrementWithCustomTimestamp() throws IOException { 507 TableName TABLENAME = TableName.valueOf(name.getMethodName()); 508 Table table = TEST_UTIL.createTable(TABLENAME, FAMILY); 509 long timestamp = 999; 510 Increment increment = new Increment(ROW); 511 increment.add(ExtendedCellBuilderFactory.create(CellBuilderType.DEEP_COPY).setRow(ROW) 512 .setFamily(FAMILY).setQualifier(QUALIFIER).setTimestamp(timestamp) 513 .setType(KeyValue.Type.Put.getCode()).setValue(Bytes.toBytes(100L)).build()); 514 Result r = table.increment(increment); 515 assertEquals(1, r.size()); 516 assertEquals(timestamp, r.rawCells()[0].getTimestamp()); 517 r = table.get(new Get(ROW)); 518 assertEquals(1, r.size()); 519 assertEquals(timestamp, r.rawCells()[0].getTimestamp()); 520 r = table.increment(increment); 521 assertEquals(1, r.size()); 522 assertNotEquals(timestamp, r.rawCells()[0].getTimestamp()); 523 r = table.get(new Get(ROW)); 524 assertEquals(1, r.size()); 525 assertNotEquals(timestamp, r.rawCells()[0].getTimestamp()); 526 } 527 528 /** 529 * Call over to the adjacent class's method of same name. 530 */ 531 static void assertIncrementKey(Cell key, byte[] row, byte[] family, byte[] qualifier, long value) 532 throws Exception { 533 TestFromClientSide.assertIncrementKey(key, row, family, qualifier, value); 534 } 535 536 public static String filterStringSoTableNameSafe(final String str) { 537 return str.replaceAll("\\[fast\\=(.*)\\]", ".FAST.is.$1"); 538 } 539 540 /* 541 * Test that we have only 1 ttl tag with increment mutation. 542 */ 543 @Test 544 public void testIncrementWithTtlTags() throws Exception { 545 LOG.info("Starting " + this.name.getMethodName()); 546 final TableName tableName = 547 TableName.valueOf(filterStringSoTableNameSafe(this.name.getMethodName())); 548 Table ht = TEST_UTIL.createTable(tableName, FAMILY); 549 final byte[] COLUMN = Bytes.toBytes("column"); 550 551 Configuration conf = new Configuration(TEST_UTIL.getConfiguration()); 552 // Set RPC_CODEC_CONF_KEY to KeyValueCodecWithTags so that scan will return tags. 553 conf.set(RPC_CODEC_CONF_KEY, KeyValueCodecWithTags.class.getName()); 554 conf.set(DEFAULT_CODEC_CLASS, ""); 555 try (Connection connection = ConnectionFactory.createConnection(conf); 556 Table table = connection.getTable(tableName)) { 557 for (int i = 0; i < 10; i++) { 558 Increment inc = new Increment(ROW); 559 inc.addColumn(FAMILY, COLUMN, 1); 560 long ttl = i + 3600000; 561 inc.setTTL(ttl); 562 ht.increment(inc); 563 564 Scan scan = new Scan().withStartRow(ROW); 565 ResultScanner scanner = table.getScanner(scan); 566 int count = 0; 567 Result result; 568 while ((result = scanner.next()) != null) { 569 Cell[] cells = result.rawCells(); 570 for (Cell cell : cells) { 571 List<Tag> tags = PrivateCellUtil.getTags(cell); 572 // Make sure there is only 1 tag. 573 assertEquals(1, tags.size()); 574 Tag tag = tags.get(0); 575 assertEquals(TagType.TTL_TAG_TYPE, tag.getType()); 576 long ttlTagValue = Bytes.toLong(tag.getValueArray(), tag.getValueOffset()); 577 assertEquals(ttl, ttlTagValue); 578 } 579 count++; 580 } 581 // Make sure there is only 1 result. 582 assertEquals(1, count); 583 } 584 } 585 } 586}