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