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.CellUtil; 037import org.apache.hadoop.hbase.DoNotRetryIOException; 038import org.apache.hadoop.hbase.HBaseClassTestRule; 039import org.apache.hadoop.hbase.HBaseTestingUtility; 040import org.apache.hadoop.hbase.HConstants; 041import org.apache.hadoop.hbase.HTableDescriptor; 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 HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility(); 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 HTableDescriptor hdt = TEST_UTIL.createTableDescriptor(TableName.valueOf(name.getMethodName())); 110 Map<String, String> kvs = new HashMap<>(); 111 kvs.put(HConnectionTestingUtility.SleepAtFirstRpcCall.SLEEP_TIME_CONF_KEY, "2000"); 112 hdt.addCoprocessor(HConnectionTestingUtility.SleepAtFirstRpcCall.class.getName(), null, 1, kvs); 113 TEST_UTIL.createTable(hdt, new byte[][] { ROW }).close(); 114 115 Configuration c = new Configuration(TEST_UTIL.getConfiguration()); 116 c.setInt(HConstants.HBASE_CLIENT_PAUSE, 50); 117 // Client will retry beacuse rpc timeout is small than the sleep time of first rpc call 118 c.setInt(HConstants.HBASE_RPC_TIMEOUT_KEY, 1500); 119 120 Connection connection = ConnectionFactory.createConnection(c); 121 Table t = connection.getTable(TableName.valueOf(name.getMethodName())); 122 if (t instanceof HTable) { 123 HTable table = (HTable) t; 124 table.setOperationTimeout(3 * 1000); 125 126 try { 127 Increment inc = new Increment(ROW); 128 inc.addColumn(TEST_UTIL.fam1, QUALIFIER, 1); 129 Result result = table.increment(inc); 130 131 Cell[] cells = result.rawCells(); 132 assertEquals(1, cells.length); 133 assertIncrementKey(cells[0], ROW, TEST_UTIL.fam1, QUALIFIER, 1); 134 135 // Verify expected result 136 Result readResult = table.get(new Get(ROW)); 137 cells = readResult.rawCells(); 138 assertEquals(1, cells.length); 139 assertIncrementKey(cells[0], ROW, TEST_UTIL.fam1, QUALIFIER, 1); 140 } finally { 141 table.close(); 142 connection.close(); 143 } 144 } 145 } 146 147 /** 148 * Test batch increment result when there are duplicate rpc request. 149 */ 150 @Test 151 public void testDuplicateBatchIncrement() throws Exception { 152 HTableDescriptor hdt = TEST_UTIL.createTableDescriptor(TableName.valueOf(name.getMethodName())); 153 Map<String, String> kvs = new HashMap<>(); 154 kvs.put(HConnectionTestingUtility.SleepAtFirstRpcCall.SLEEP_TIME_CONF_KEY, "2000"); 155 hdt.addCoprocessor(HConnectionTestingUtility.SleepAtFirstRpcCall.class.getName(), null, 1, kvs); 156 TEST_UTIL.createTable(hdt, new byte[][] { ROW }).close(); 157 158 Configuration c = new Configuration(TEST_UTIL.getConfiguration()); 159 c.setInt(HConstants.HBASE_CLIENT_PAUSE, 50); 160 // Client will retry beacuse rpc timeout is small than the sleep time of first rpc call 161 c.setInt(HConstants.HBASE_RPC_TIMEOUT_KEY, 1500); 162 163 try (Connection connection = ConnectionFactory.createConnection(c); 164 Table table = connection.getTableBuilder(TableName.valueOf(name.getMethodName()), null) 165 .setOperationTimeout(3 * 1000).build()) { 166 Increment inc = new Increment(ROW); 167 inc.addColumn(HBaseTestingUtility.fam1, QUALIFIER, 1); 168 169 // Batch increment 170 Object[] results = new Object[1]; 171 table.batch(Collections.singletonList(inc), results); 172 173 Cell[] cells = ((Result) results[0]).rawCells(); 174 assertEquals(1, cells.length); 175 assertIncrementKey(cells[0], ROW, HBaseTestingUtility.fam1, QUALIFIER, 1); 176 177 // Verify expected result 178 Result readResult = table.get(new Get(ROW)); 179 cells = readResult.rawCells(); 180 assertEquals(1, cells.length); 181 assertIncrementKey(cells[0], ROW, HBaseTestingUtility.fam1, QUALIFIER, 1); 182 } 183 } 184 185 @Test 186 public void testIncrementWithDeletes() throws Exception { 187 LOG.info("Starting " + this.name.getMethodName()); 188 final TableName TABLENAME = 189 TableName.valueOf(filterStringSoTableNameSafe(this.name.getMethodName())); 190 Table ht = TEST_UTIL.createTable(TABLENAME, FAMILY); 191 final byte[] COLUMN = Bytes.toBytes("column"); 192 193 ht.incrementColumnValue(ROW, FAMILY, COLUMN, 5); 194 TEST_UTIL.flush(TABLENAME); 195 196 Delete del = new Delete(ROW); 197 ht.delete(del); 198 199 ht.incrementColumnValue(ROW, FAMILY, COLUMN, 5); 200 201 Get get = new Get(ROW); 202 Result r = ht.get(get); 203 assertEquals(1, r.size()); 204 assertEquals(5, Bytes.toLong(r.getValue(FAMILY, COLUMN))); 205 } 206 207 @Test 208 public void testIncrementingInvalidValue() throws Exception { 209 LOG.info("Starting " + this.name.getMethodName()); 210 final TableName TABLENAME = 211 TableName.valueOf(filterStringSoTableNameSafe(this.name.getMethodName())); 212 Table ht = TEST_UTIL.createTable(TABLENAME, FAMILY); 213 final byte[] COLUMN = Bytes.toBytes("column"); 214 Put p = new Put(ROW); 215 // write an integer here (not a Long) 216 p.addColumn(FAMILY, COLUMN, Bytes.toBytes(5)); 217 ht.put(p); 218 try { 219 ht.incrementColumnValue(ROW, FAMILY, COLUMN, 5); 220 fail("Should have thrown DoNotRetryIOException"); 221 } catch (DoNotRetryIOException iox) { 222 // success 223 } 224 Increment inc = new Increment(ROW); 225 inc.addColumn(FAMILY, COLUMN, 5); 226 try { 227 ht.increment(inc); 228 fail("Should have thrown DoNotRetryIOException"); 229 } catch (DoNotRetryIOException iox) { 230 // success 231 } 232 } 233 234 @Test 235 public void testBatchIncrementsWithReturnResultFalse() throws Exception { 236 LOG.info("Starting testBatchIncrementsWithReturnResultFalse"); 237 final TableName tableName = TableName.valueOf(name.getMethodName()); 238 Table table = TEST_UTIL.createTable(tableName, FAMILY); 239 Increment inc1 = new Increment(Bytes.toBytes("row2")); 240 inc1.setReturnResults(false); 241 inc1.addColumn(FAMILY, Bytes.toBytes("f1"), 1); 242 Increment inc2 = new Increment(Bytes.toBytes("row2")); 243 inc2.setReturnResults(false); 244 inc2.addColumn(FAMILY, Bytes.toBytes("f1"), 1); 245 List<Increment> incs = new ArrayList<>(); 246 incs.add(inc1); 247 incs.add(inc2); 248 Object[] results = new Object[2]; 249 table.batch(incs, results); 250 assertTrue(results.length == 2); 251 for (Object r : results) { 252 Result result = (Result) r; 253 assertTrue(result.isEmpty()); 254 } 255 table.close(); 256 } 257 258 @Test 259 public void testIncrementInvalidArguments() throws Exception { 260 LOG.info("Starting " + this.name.getMethodName()); 261 final TableName TABLENAME = 262 TableName.valueOf(filterStringSoTableNameSafe(this.name.getMethodName())); 263 Table ht = TEST_UTIL.createTable(TABLENAME, FAMILY); 264 final byte[] COLUMN = Bytes.toBytes("column"); 265 try { 266 // try null row 267 ht.incrementColumnValue(null, FAMILY, COLUMN, 5); 268 fail("Should have thrown IOException"); 269 } catch (IOException iox) { 270 // success 271 } 272 try { 273 // try null family 274 ht.incrementColumnValue(ROW, null, COLUMN, 5); 275 fail("Should have thrown IOException"); 276 } catch (IOException iox) { 277 // success 278 } 279 // try null row 280 try { 281 Increment incNoRow = new Increment((byte[]) null); 282 incNoRow.addColumn(FAMILY, COLUMN, 5); 283 fail("Should have thrown IllegalArgumentException"); 284 } catch (IllegalArgumentException iax) { 285 // success 286 } catch (NullPointerException npe) { 287 // success 288 } 289 // try null family 290 try { 291 Increment incNoFamily = new Increment(ROW); 292 incNoFamily.addColumn(null, COLUMN, 5); 293 fail("Should have thrown IllegalArgumentException"); 294 } catch (IllegalArgumentException iax) { 295 // success 296 } 297 } 298 299 @Test 300 public void testIncrementOutOfOrder() throws Exception { 301 LOG.info("Starting " + this.name.getMethodName()); 302 final TableName TABLENAME = 303 TableName.valueOf(filterStringSoTableNameSafe(this.name.getMethodName())); 304 Table ht = TEST_UTIL.createTable(TABLENAME, FAMILY); 305 306 byte[][] QUALIFIERS = 307 new byte[][] { Bytes.toBytes("B"), Bytes.toBytes("A"), Bytes.toBytes("C") }; 308 309 Increment inc = new Increment(ROW); 310 for (int i = 0; i < QUALIFIERS.length; i++) { 311 inc.addColumn(FAMILY, QUALIFIERS[i], 1); 312 } 313 ht.increment(inc); 314 315 // Verify expected results 316 Get get = new Get(ROW); 317 Result r = ht.get(get); 318 Cell[] kvs = r.rawCells(); 319 assertEquals(3, kvs.length); 320 assertIncrementKey(kvs[0], ROW, FAMILY, QUALIFIERS[1], 1); 321 assertIncrementKey(kvs[1], ROW, FAMILY, QUALIFIERS[0], 1); 322 assertIncrementKey(kvs[2], ROW, FAMILY, QUALIFIERS[2], 1); 323 324 // Now try multiple columns again 325 inc = new Increment(ROW); 326 for (int i = 0; i < QUALIFIERS.length; i++) { 327 inc.addColumn(FAMILY, QUALIFIERS[i], 1); 328 } 329 ht.increment(inc); 330 331 // Verify 332 r = ht.get(get); 333 kvs = r.rawCells(); 334 assertEquals(3, kvs.length); 335 assertIncrementKey(kvs[0], ROW, FAMILY, QUALIFIERS[1], 2); 336 assertIncrementKey(kvs[1], ROW, FAMILY, QUALIFIERS[0], 2); 337 assertIncrementKey(kvs[2], ROW, FAMILY, QUALIFIERS[2], 2); 338 } 339 340 @Test 341 public void testIncrementOnSameColumn() throws Exception { 342 LOG.info("Starting " + this.name.getMethodName()); 343 final byte[] TABLENAME = Bytes.toBytes(filterStringSoTableNameSafe(this.name.getMethodName())); 344 Table ht = TEST_UTIL.createTable(TableName.valueOf(TABLENAME), FAMILY); 345 346 byte[][] QUALIFIERS = 347 new byte[][] { Bytes.toBytes("A"), Bytes.toBytes("B"), Bytes.toBytes("C") }; 348 349 Increment inc = new Increment(ROW); 350 for (int i = 0; i < QUALIFIERS.length; i++) { 351 inc.addColumn(FAMILY, QUALIFIERS[i], 1); 352 inc.addColumn(FAMILY, QUALIFIERS[i], 1); 353 } 354 ht.increment(inc); 355 356 // Verify expected results 357 Get get = new Get(ROW); 358 Result r = ht.get(get); 359 Cell[] kvs = r.rawCells(); 360 assertEquals(3, kvs.length); 361 assertIncrementKey(kvs[0], ROW, FAMILY, QUALIFIERS[0], 1); 362 assertIncrementKey(kvs[1], ROW, FAMILY, QUALIFIERS[1], 1); 363 assertIncrementKey(kvs[2], ROW, FAMILY, QUALIFIERS[2], 1); 364 365 // Now try multiple columns again 366 inc = new Increment(ROW); 367 for (int i = 0; i < QUALIFIERS.length; i++) { 368 inc.addColumn(FAMILY, QUALIFIERS[i], 1); 369 inc.addColumn(FAMILY, QUALIFIERS[i], 1); 370 } 371 ht.increment(inc); 372 373 // Verify 374 r = ht.get(get); 375 kvs = r.rawCells(); 376 assertEquals(3, kvs.length); 377 assertIncrementKey(kvs[0], ROW, FAMILY, QUALIFIERS[0], 2); 378 assertIncrementKey(kvs[1], ROW, FAMILY, QUALIFIERS[1], 2); 379 assertIncrementKey(kvs[2], ROW, FAMILY, QUALIFIERS[2], 2); 380 381 ht.close(); 382 } 383 384 @Test 385 public void testIncrementIncrZeroAtFirst() throws Exception { 386 LOG.info("Starting " + this.name.getMethodName()); 387 final TableName TABLENAME = 388 TableName.valueOf(filterStringSoTableNameSafe(this.name.getMethodName())); 389 Table ht = TEST_UTIL.createTable(TABLENAME, FAMILY); 390 391 byte[] col1 = Bytes.toBytes("col1"); 392 byte[] col2 = Bytes.toBytes("col2"); 393 byte[] col3 = Bytes.toBytes("col3"); 394 395 // Now increment zero at first time incr 396 Increment inc = new Increment(ROW); 397 inc.addColumn(FAMILY, col1, 0); 398 ht.increment(inc); 399 400 // Verify expected results 401 Get get = new Get(ROW); 402 Result r = ht.get(get); 403 Cell[] kvs = r.rawCells(); 404 assertEquals(1, kvs.length); 405 assertNotNull(kvs[0]); 406 assertIncrementKey(kvs[0], ROW, FAMILY, col1, 0); 407 408 // Now try multiple columns by different amounts 409 inc = new Increment(ROW); 410 inc.addColumn(FAMILY, col1, 1); 411 inc.addColumn(FAMILY, col2, 0); 412 inc.addColumn(FAMILY, col3, 2); 413 ht.increment(inc); 414 // Verify 415 get = new Get(ROW); 416 r = ht.get(get); 417 kvs = r.rawCells(); 418 assertEquals(3, kvs.length); 419 assertNotNull(kvs[0]); 420 assertNotNull(kvs[1]); 421 assertNotNull(kvs[2]); 422 assertIncrementKey(kvs[0], ROW, FAMILY, col1, 1); 423 assertIncrementKey(kvs[1], ROW, FAMILY, col2, 0); 424 assertIncrementKey(kvs[2], ROW, FAMILY, col3, 2); 425 } 426 427 @Test 428 public void testIncrement() throws Exception { 429 LOG.info("Starting " + this.name.getMethodName()); 430 final TableName TABLENAME = 431 TableName.valueOf(filterStringSoTableNameSafe(this.name.getMethodName())); 432 Table ht = TEST_UTIL.createTable(TABLENAME, FAMILY); 433 434 byte[][] ROWS = new byte[][] { Bytes.toBytes("a"), Bytes.toBytes("b"), Bytes.toBytes("c"), 435 Bytes.toBytes("d"), Bytes.toBytes("e"), Bytes.toBytes("f"), Bytes.toBytes("g"), 436 Bytes.toBytes("h"), Bytes.toBytes("i") }; 437 byte[][] QUALIFIERS = new byte[][] { Bytes.toBytes("a"), Bytes.toBytes("b"), Bytes.toBytes("c"), 438 Bytes.toBytes("d"), Bytes.toBytes("e"), Bytes.toBytes("f"), Bytes.toBytes("g"), 439 Bytes.toBytes("h"), Bytes.toBytes("i") }; 440 441 // Do some simple single-column increments 442 443 // First with old API 444 ht.incrementColumnValue(ROW, FAMILY, QUALIFIERS[0], 1); 445 ht.incrementColumnValue(ROW, FAMILY, QUALIFIERS[1], 2); 446 ht.incrementColumnValue(ROW, FAMILY, QUALIFIERS[2], 3); 447 ht.incrementColumnValue(ROW, FAMILY, QUALIFIERS[3], 4); 448 449 // Now increment things incremented with old and do some new 450 Increment inc = new Increment(ROW); 451 inc.addColumn(FAMILY, QUALIFIERS[1], 1); 452 inc.addColumn(FAMILY, QUALIFIERS[3], 1); 453 inc.addColumn(FAMILY, QUALIFIERS[4], 1); 454 ht.increment(inc); 455 456 // Verify expected results 457 Get get = new Get(ROW); 458 Result r = ht.get(get); 459 Cell[] kvs = r.rawCells(); 460 assertEquals(5, kvs.length); 461 assertIncrementKey(kvs[0], ROW, FAMILY, QUALIFIERS[0], 1); 462 assertIncrementKey(kvs[1], ROW, FAMILY, QUALIFIERS[1], 3); 463 assertIncrementKey(kvs[2], ROW, FAMILY, QUALIFIERS[2], 3); 464 assertIncrementKey(kvs[3], ROW, FAMILY, QUALIFIERS[3], 5); 465 assertIncrementKey(kvs[4], ROW, FAMILY, QUALIFIERS[4], 1); 466 467 // Now try multiple columns by different amounts 468 inc = new Increment(ROWS[0]); 469 for (int i = 0; i < QUALIFIERS.length; i++) { 470 inc.addColumn(FAMILY, QUALIFIERS[i], i + 1); 471 } 472 ht.increment(inc); 473 // Verify 474 get = new Get(ROWS[0]); 475 r = ht.get(get); 476 kvs = r.rawCells(); 477 assertEquals(QUALIFIERS.length, kvs.length); 478 for (int i = 0; i < QUALIFIERS.length; i++) { 479 assertIncrementKey(kvs[i], ROWS[0], FAMILY, QUALIFIERS[i], i + 1); 480 } 481 482 // Re-increment them 483 inc = new Increment(ROWS[0]); 484 for (int i = 0; i < QUALIFIERS.length; i++) { 485 inc.addColumn(FAMILY, QUALIFIERS[i], i + 1); 486 } 487 ht.increment(inc); 488 // Verify 489 r = ht.get(get); 490 kvs = r.rawCells(); 491 assertEquals(QUALIFIERS.length, kvs.length); 492 for (int i = 0; i < QUALIFIERS.length; i++) { 493 assertIncrementKey(kvs[i], ROWS[0], FAMILY, QUALIFIERS[i], 2 * (i + 1)); 494 } 495 496 // Verify that an Increment of an amount of zero, returns current count; i.e. same as for above 497 // test, that is: 2 * (i + 1). 498 inc = new Increment(ROWS[0]); 499 for (int i = 0; i < QUALIFIERS.length; i++) { 500 inc.addColumn(FAMILY, QUALIFIERS[i], 0); 501 } 502 ht.increment(inc); 503 r = ht.get(get); 504 kvs = r.rawCells(); 505 assertEquals(QUALIFIERS.length, kvs.length); 506 for (int i = 0; i < QUALIFIERS.length; i++) { 507 assertIncrementKey(kvs[i], ROWS[0], FAMILY, QUALIFIERS[i], 2 * (i + 1)); 508 } 509 } 510 511 @Test 512 public void testIncrementWithCustomTimestamp() throws IOException { 513 TableName TABLENAME = TableName.valueOf(name.getMethodName()); 514 Table table = TEST_UTIL.createTable(TABLENAME, FAMILY); 515 long timestamp = 999; 516 Increment increment = new Increment(ROW); 517 increment.add(CellUtil.createCell(ROW, FAMILY, QUALIFIER, timestamp, 518 KeyValue.Type.Put.getCode(), Bytes.toBytes(100L))); 519 Result r = table.increment(increment); 520 assertEquals(1, r.size()); 521 assertEquals(timestamp, r.rawCells()[0].getTimestamp()); 522 r = table.get(new Get(ROW)); 523 assertEquals(1, r.size()); 524 assertEquals(timestamp, r.rawCells()[0].getTimestamp()); 525 r = table.increment(increment); 526 assertEquals(1, r.size()); 527 assertNotEquals(timestamp, r.rawCells()[0].getTimestamp()); 528 r = table.get(new Get(ROW)); 529 assertEquals(1, r.size()); 530 assertNotEquals(timestamp, r.rawCells()[0].getTimestamp()); 531 } 532 533 /** 534 * Call over to the adjacent class's method of same name. 535 */ 536 static void assertIncrementKey(Cell key, byte[] row, byte[] family, byte[] qualifier, long value) 537 throws Exception { 538 TestFromClientSide.assertIncrementKey(key, row, family, qualifier, value); 539 } 540 541 public static String filterStringSoTableNameSafe(final String str) { 542 return str.replaceAll("\\[fast\\=(.*)\\]", ".FAST.is.$1"); 543 } 544 545 /* 546 * Test that we have only 1 ttl tag with increment mutation. 547 */ 548 @Test 549 public void testIncrementWithTtlTags() throws Exception { 550 LOG.info("Starting " + this.name.getMethodName()); 551 final TableName tableName = 552 TableName.valueOf(filterStringSoTableNameSafe(this.name.getMethodName())); 553 Table ht = TEST_UTIL.createTable(tableName, FAMILY); 554 final byte[] COLUMN = Bytes.toBytes("column"); 555 556 Configuration conf = new Configuration(TEST_UTIL.getConfiguration()); 557 // Set RPC_CODEC_CONF_KEY to KeyValueCodecWithTags so that scan will return tags. 558 conf.set(RPC_CODEC_CONF_KEY, KeyValueCodecWithTags.class.getName()); 559 conf.set(DEFAULT_CODEC_CLASS, ""); 560 try (Connection connection = ConnectionFactory.createConnection(conf); 561 Table table = connection.getTable(tableName)) { 562 for (int i = 0; i < 10; i++) { 563 Increment inc = new Increment(ROW); 564 inc.addColumn(FAMILY, COLUMN, 1); 565 long ttl = i + 3600000; 566 inc.setTTL(ttl); 567 ht.increment(inc); 568 569 Scan scan = new Scan().withStartRow(ROW); 570 ResultScanner scanner = table.getScanner(scan); 571 int count = 0; 572 Result result; 573 while ((result = scanner.next()) != null) { 574 Cell[] cells = result.rawCells(); 575 for (Cell cell : cells) { 576 List<Tag> tags = PrivateCellUtil.getTags(cell); 577 // Make sure there is only 1 tag. 578 assertEquals(1, tags.size()); 579 Tag tag = tags.get(0); 580 assertEquals(TagType.TTL_TAG_TYPE, tag.getType()); 581 long ttlTagValue = Bytes.toLong(tag.getValueArray(), tag.getValueOffset()); 582 assertEquals(ttl, ttlTagValue); 583 } 584 count++; 585 } 586 // Make sure there is only 1 result. 587 assertEquals(1, count); 588 } 589 } 590 } 591}