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.thrift2; 019 020import static java.nio.ByteBuffer.wrap; 021import static org.apache.hadoop.hbase.HConstants.DEFAULT_HBASE_CLIENT_SCANNER_TIMEOUT_PERIOD; 022import static org.apache.hadoop.hbase.HConstants.HBASE_CLIENT_SCANNER_TIMEOUT_PERIOD; 023import static org.apache.hadoop.hbase.thrift.HBaseServiceHandler.CLEANUP_INTERVAL; 024import static org.apache.hadoop.hbase.thrift.HBaseServiceHandler.MAX_IDLETIME; 025import static org.apache.hadoop.hbase.thrift2.ThriftUtilities.deleteFromThrift; 026import static org.apache.hadoop.hbase.thrift2.ThriftUtilities.getFromThrift; 027import static org.apache.hadoop.hbase.thrift2.ThriftUtilities.incrementFromThrift; 028import static org.apache.hadoop.hbase.thrift2.ThriftUtilities.putFromThrift; 029import static org.apache.hadoop.hbase.thrift2.ThriftUtilities.scanFromThrift; 030import static org.junit.Assert.assertArrayEquals; 031import static org.junit.Assert.assertEquals; 032import static org.junit.Assert.assertFalse; 033import static org.junit.Assert.assertNull; 034import static org.junit.Assert.assertTrue; 035import static org.junit.Assert.fail; 036 037import java.io.IOException; 038import java.io.InterruptedIOException; 039import java.net.InetAddress; 040import java.nio.ByteBuffer; 041import java.util.ArrayList; 042import java.util.Arrays; 043import java.util.Collection; 044import java.util.Collections; 045import java.util.Comparator; 046import java.util.HashMap; 047import java.util.HashSet; 048import java.util.List; 049import java.util.Map; 050import java.util.Optional; 051import java.util.Set; 052import java.util.concurrent.TimeUnit; 053import org.apache.hadoop.conf.Configuration; 054import org.apache.hadoop.hbase.Cell; 055import org.apache.hadoop.hbase.CompatibilityFactory; 056import org.apache.hadoop.hbase.CoprocessorEnvironment; 057import org.apache.hadoop.hbase.HBaseClassTestRule; 058import org.apache.hadoop.hbase.HBaseTestingUtility; 059import org.apache.hadoop.hbase.HColumnDescriptor; 060import org.apache.hadoop.hbase.HTableDescriptor; 061import org.apache.hadoop.hbase.ServerName; 062import org.apache.hadoop.hbase.TableName; 063import org.apache.hadoop.hbase.client.Admin; 064import org.apache.hadoop.hbase.client.Consistency; 065import org.apache.hadoop.hbase.client.Delete; 066import org.apache.hadoop.hbase.client.Durability; 067import org.apache.hadoop.hbase.client.Get; 068import org.apache.hadoop.hbase.client.Increment; 069import org.apache.hadoop.hbase.client.LogQueryFilter; 070import org.apache.hadoop.hbase.client.Put; 071import org.apache.hadoop.hbase.client.Scan; 072import org.apache.hadoop.hbase.client.Table; 073import org.apache.hadoop.hbase.client.TableDescriptor; 074import org.apache.hadoop.hbase.coprocessor.ObserverContext; 075import org.apache.hadoop.hbase.coprocessor.RegionCoprocessor; 076import org.apache.hadoop.hbase.coprocessor.RegionCoprocessorEnvironment; 077import org.apache.hadoop.hbase.coprocessor.RegionObserver; 078import org.apache.hadoop.hbase.filter.ParseFilter; 079import org.apache.hadoop.hbase.security.UserProvider; 080import org.apache.hadoop.hbase.test.MetricsAssertHelper; 081import org.apache.hadoop.hbase.testclassification.ClientTests; 082import org.apache.hadoop.hbase.testclassification.MediumTests; 083import org.apache.hadoop.hbase.thrift.ErrorThrowingGetObserver; 084import org.apache.hadoop.hbase.thrift.HBaseThriftTestingUtility; 085import org.apache.hadoop.hbase.thrift.HbaseHandlerMetricsProxy; 086import org.apache.hadoop.hbase.thrift.ThriftMetrics; 087import org.apache.hadoop.hbase.thrift.ThriftMetrics.ThriftServerType; 088import org.apache.hadoop.hbase.thrift2.generated.TAppend; 089import org.apache.hadoop.hbase.thrift2.generated.TColumn; 090import org.apache.hadoop.hbase.thrift2.generated.TColumnFamilyDescriptor; 091import org.apache.hadoop.hbase.thrift2.generated.TColumnIncrement; 092import org.apache.hadoop.hbase.thrift2.generated.TColumnValue; 093import org.apache.hadoop.hbase.thrift2.generated.TCompareOp; 094import org.apache.hadoop.hbase.thrift2.generated.TConsistency; 095import org.apache.hadoop.hbase.thrift2.generated.TDataBlockEncoding; 096import org.apache.hadoop.hbase.thrift2.generated.TDelete; 097import org.apache.hadoop.hbase.thrift2.generated.TDeleteType; 098import org.apache.hadoop.hbase.thrift2.generated.TDurability; 099import org.apache.hadoop.hbase.thrift2.generated.TFilterByOperator; 100import org.apache.hadoop.hbase.thrift2.generated.TGet; 101import org.apache.hadoop.hbase.thrift2.generated.THBaseService; 102import org.apache.hadoop.hbase.thrift2.generated.TIOError; 103import org.apache.hadoop.hbase.thrift2.generated.TIllegalArgument; 104import org.apache.hadoop.hbase.thrift2.generated.TIncrement; 105import org.apache.hadoop.hbase.thrift2.generated.TLogQueryFilter; 106import org.apache.hadoop.hbase.thrift2.generated.TMutation; 107import org.apache.hadoop.hbase.thrift2.generated.TNamespaceDescriptor; 108import org.apache.hadoop.hbase.thrift2.generated.TOnlineLogRecord; 109import org.apache.hadoop.hbase.thrift2.generated.TPut; 110import org.apache.hadoop.hbase.thrift2.generated.TReadType; 111import org.apache.hadoop.hbase.thrift2.generated.TResult; 112import org.apache.hadoop.hbase.thrift2.generated.TRowMutations; 113import org.apache.hadoop.hbase.thrift2.generated.TScan; 114import org.apache.hadoop.hbase.thrift2.generated.TServerName; 115import org.apache.hadoop.hbase.thrift2.generated.TTableDescriptor; 116import org.apache.hadoop.hbase.thrift2.generated.TTableName; 117import org.apache.hadoop.hbase.thrift2.generated.TThriftServerType; 118import org.apache.hadoop.hbase.thrift2.generated.TTimeRange; 119import org.apache.hadoop.hbase.util.Bytes; 120import org.apache.hadoop.hbase.util.EnvironmentEdgeManager; 121import org.apache.thrift.TException; 122import org.apache.thrift.protocol.TBinaryProtocol; 123import org.apache.thrift.protocol.TProtocol; 124import org.apache.thrift.transport.TSocket; 125import org.apache.thrift.transport.TTransport; 126import org.junit.AfterClass; 127import org.junit.Assert; 128import org.junit.Before; 129import org.junit.BeforeClass; 130import org.junit.ClassRule; 131import org.junit.Rule; 132import org.junit.Test; 133import org.junit.experimental.categories.Category; 134import org.junit.rules.TestName; 135import org.slf4j.Logger; 136import org.slf4j.LoggerFactory; 137 138import org.apache.hbase.thirdparty.com.google.common.collect.Lists; 139import org.apache.hbase.thirdparty.org.apache.commons.collections4.CollectionUtils; 140 141/** 142 * Unit testing for ThriftServer.HBaseServiceHandler, a part of the org.apache.hadoop.hbase.thrift2 143 * package. 144 */ 145@Category({ ClientTests.class, MediumTests.class }) 146public class TestThriftHBaseServiceHandler { 147 148 @ClassRule 149 public static final HBaseClassTestRule CLASS_RULE = 150 HBaseClassTestRule.forClass(TestThriftHBaseServiceHandler.class); 151 152 private static final Logger LOG = LoggerFactory.getLogger(TestThriftHBaseServiceHandler.class); 153 private static final HBaseTestingUtility UTIL = new HBaseTestingUtility(); 154 155 // Static names for tables, columns, rows, and values 156 private static byte[] tableAname = Bytes.toBytes("tableA"); 157 private static byte[] familyAname = Bytes.toBytes("familyA"); 158 private static byte[] familyBname = Bytes.toBytes("familyB"); 159 private static byte[] qualifierAname = Bytes.toBytes("qualifierA"); 160 private static byte[] qualifierBname = Bytes.toBytes("qualifierB"); 161 private static byte[] valueAname = Bytes.toBytes("valueA"); 162 private static byte[] valueBname = Bytes.toBytes("valueB"); 163 private static HColumnDescriptor[] families = 164 new HColumnDescriptor[] { new HColumnDescriptor(familyAname).setMaxVersions(3), 165 new HColumnDescriptor(familyBname).setMaxVersions(2) }; 166 167 private static final MetricsAssertHelper metricsHelper = 168 CompatibilityFactory.getInstance(MetricsAssertHelper.class); 169 170 @Rule 171 public TestName name = new TestName(); 172 173 public void assertTColumnValuesEqual(List<TColumnValue> columnValuesA, 174 List<TColumnValue> columnValuesB) { 175 assertEquals(columnValuesA.size(), columnValuesB.size()); 176 Comparator<TColumnValue> comparator = new Comparator<TColumnValue>() { 177 @Override 178 public int compare(TColumnValue o1, TColumnValue o2) { 179 return Bytes.compareTo(Bytes.add(o1.getFamily(), o1.getQualifier()), 180 Bytes.add(o2.getFamily(), o2.getQualifier())); 181 } 182 }; 183 Collections.sort(columnValuesA, comparator); 184 Collections.sort(columnValuesB, comparator); 185 186 for (int i = 0; i < columnValuesA.size(); i++) { 187 TColumnValue a = columnValuesA.get(i); 188 TColumnValue b = columnValuesB.get(i); 189 assertTColumnValueEqual(a, b); 190 } 191 } 192 193 public void assertTColumnValueEqual(TColumnValue a, TColumnValue b) { 194 assertArrayEquals(a.getFamily(), b.getFamily()); 195 assertArrayEquals(a.getQualifier(), b.getQualifier()); 196 assertArrayEquals(a.getValue(), b.getValue()); 197 } 198 199 @BeforeClass 200 public static void beforeClass() throws Exception { 201 UTIL.getConfiguration().set("hbase.client.retries.number", "3"); 202 UTIL.getConfiguration().setBoolean("hbase.regionserver.slowlog.buffer.enabled", true); 203 UTIL.startMiniCluster(); 204 HTableDescriptor tableDescriptor = new HTableDescriptor(TableName.valueOf(tableAname)); 205 for (HColumnDescriptor family : families) { 206 tableDescriptor.addFamily(family); 207 } 208 try (Admin admin = UTIL.getAdmin()) { 209 admin.createTable(tableDescriptor); 210 } 211 } 212 213 @AfterClass 214 public static void afterClass() throws Exception { 215 UTIL.shutdownMiniCluster(); 216 } 217 218 @Before 219 public void setup() throws Exception { 220 221 } 222 223 private ThriftHBaseServiceHandler createHandler() throws TException { 224 try { 225 Configuration conf = UTIL.getConfiguration(); 226 return new ThriftHBaseServiceHandler(conf, UserProvider.instantiate(conf)); 227 } catch (IOException ie) { 228 throw new TException(ie); 229 } 230 } 231 232 @Test 233 public void testExists() throws TIOError, TException { 234 ThriftHBaseServiceHandler handler = createHandler(); 235 byte[] rowName = Bytes.toBytes("testExists"); 236 ByteBuffer table = wrap(tableAname); 237 238 TGet get = new TGet(wrap(rowName)); 239 assertFalse(handler.exists(table, get)); 240 241 List<TColumnValue> columnValues = new ArrayList<>(2); 242 columnValues.add(new TColumnValue(wrap(familyAname), wrap(qualifierAname), wrap(valueAname))); 243 columnValues.add(new TColumnValue(wrap(familyBname), wrap(qualifierBname), wrap(valueBname))); 244 TPut put = new TPut(wrap(rowName), columnValues); 245 put.setColumnValues(columnValues); 246 247 handler.put(table, put); 248 249 assertTrue(handler.exists(table, get)); 250 } 251 252 @Test 253 public void testExistsAll() throws TIOError, TException { 254 ThriftHBaseServiceHandler handler = createHandler(); 255 byte[] rowName1 = Bytes.toBytes("testExistsAll1"); 256 byte[] rowName2 = Bytes.toBytes("testExistsAll2"); 257 ByteBuffer table = wrap(tableAname); 258 259 List<TGet> gets = new ArrayList<>(); 260 gets.add(new TGet(wrap(rowName2))); 261 gets.add(new TGet(wrap(rowName2))); 262 List<Boolean> existsResult1 = handler.existsAll(table, gets); 263 assertFalse(existsResult1.get(0)); 264 assertFalse(existsResult1.get(1)); 265 266 List<TColumnValue> columnValues = new ArrayList<TColumnValue>(); 267 columnValues.add(new TColumnValue(wrap(familyAname), wrap(qualifierAname), wrap(valueAname))); 268 columnValues.add(new TColumnValue(wrap(familyBname), wrap(qualifierBname), wrap(valueBname))); 269 List<TPut> puts = new ArrayList<TPut>(); 270 puts.add(new TPut(wrap(rowName1), columnValues)); 271 puts.add(new TPut(wrap(rowName2), columnValues)); 272 273 handler.putMultiple(table, puts); 274 List<Boolean> existsResult2 = handler.existsAll(table, gets); 275 276 assertTrue(existsResult2.get(0)); 277 assertTrue(existsResult2.get(1)); 278 } 279 280 @Test 281 public void testPutGet() throws Exception { 282 ThriftHBaseServiceHandler handler = createHandler(); 283 byte[] rowName = Bytes.toBytes("testPutGet"); 284 ByteBuffer table = wrap(tableAname); 285 286 List<TColumnValue> columnValues = new ArrayList<>(2); 287 columnValues.add(new TColumnValue(wrap(familyAname), wrap(qualifierAname), wrap(valueAname))); 288 columnValues.add(new TColumnValue(wrap(familyBname), wrap(qualifierBname), wrap(valueBname))); 289 TPut put = new TPut(wrap(rowName), columnValues); 290 291 put.setColumnValues(columnValues); 292 293 handler.put(table, put); 294 295 TGet get = new TGet(wrap(rowName)); 296 297 TResult result = handler.get(table, get); 298 assertArrayEquals(rowName, result.getRow()); 299 List<TColumnValue> returnedColumnValues = result.getColumnValues(); 300 assertTColumnValuesEqual(columnValues, returnedColumnValues); 301 } 302 303 @Test 304 public void testPutGetMultiple() throws Exception { 305 ThriftHBaseServiceHandler handler = createHandler(); 306 ByteBuffer table = wrap(tableAname); 307 byte[] rowName1 = Bytes.toBytes("testPutGetMultiple1"); 308 byte[] rowName2 = Bytes.toBytes("testPutGetMultiple2"); 309 310 List<TColumnValue> columnValues = new ArrayList<>(2); 311 columnValues.add(new TColumnValue(wrap(familyAname), wrap(qualifierAname), wrap(valueAname))); 312 columnValues.add(new TColumnValue(wrap(familyBname), wrap(qualifierBname), wrap(valueBname))); 313 List<TPut> puts = new ArrayList<>(2); 314 puts.add(new TPut(wrap(rowName1), columnValues)); 315 puts.add(new TPut(wrap(rowName2), columnValues)); 316 317 handler.putMultiple(table, puts); 318 319 List<TGet> gets = new ArrayList<>(2); 320 gets.add(new TGet(wrap(rowName1))); 321 gets.add(new TGet(wrap(rowName2))); 322 323 List<TResult> results = handler.getMultiple(table, gets); 324 assertEquals(2, results.size()); 325 326 assertArrayEquals(rowName1, results.get(0).getRow()); 327 assertTColumnValuesEqual(columnValues, results.get(0).getColumnValues()); 328 329 assertArrayEquals(rowName2, results.get(1).getRow()); 330 assertTColumnValuesEqual(columnValues, results.get(1).getColumnValues()); 331 } 332 333 @Test 334 public void testDeleteMultiple() throws Exception { 335 ThriftHBaseServiceHandler handler = createHandler(); 336 ByteBuffer table = wrap(tableAname); 337 byte[] rowName1 = Bytes.toBytes("testDeleteMultiple1"); 338 byte[] rowName2 = Bytes.toBytes("testDeleteMultiple2"); 339 340 List<TColumnValue> columnValues = new ArrayList<>(2); 341 columnValues.add(new TColumnValue(wrap(familyAname), wrap(qualifierAname), wrap(valueAname))); 342 columnValues.add(new TColumnValue(wrap(familyBname), wrap(qualifierBname), wrap(valueBname))); 343 List<TPut> puts = new ArrayList<>(2); 344 puts.add(new TPut(wrap(rowName1), columnValues)); 345 puts.add(new TPut(wrap(rowName2), columnValues)); 346 347 handler.putMultiple(table, puts); 348 349 List<TDelete> deletes = new ArrayList<>(2); 350 deletes.add(new TDelete(wrap(rowName1))); 351 deletes.add(new TDelete(wrap(rowName2))); 352 353 List<TDelete> deleteResults = handler.deleteMultiple(table, deletes); 354 // 0 means they were all successfully applies 355 assertEquals(0, deleteResults.size()); 356 357 assertFalse(handler.exists(table, new TGet(wrap(rowName1)))); 358 assertFalse(handler.exists(table, new TGet(wrap(rowName2)))); 359 } 360 361 @Test 362 public void testDelete() throws Exception { 363 ThriftHBaseServiceHandler handler = createHandler(); 364 byte[] rowName = Bytes.toBytes("testDelete"); 365 ByteBuffer table = wrap(tableAname); 366 367 List<TColumnValue> columnValues = new ArrayList<>(2); 368 TColumnValue columnValueA = 369 new TColumnValue(wrap(familyAname), wrap(qualifierAname), wrap(valueAname)); 370 TColumnValue columnValueB = 371 new TColumnValue(wrap(familyBname), wrap(qualifierBname), wrap(valueBname)); 372 columnValues.add(columnValueA); 373 columnValues.add(columnValueB); 374 TPut put = new TPut(wrap(rowName), columnValues); 375 376 put.setColumnValues(columnValues); 377 378 handler.put(table, put); 379 380 TDelete delete = new TDelete(wrap(rowName)); 381 List<TColumn> deleteColumns = new ArrayList<>(1); 382 TColumn deleteColumn = new TColumn(wrap(familyAname)); 383 deleteColumn.setQualifier(qualifierAname); 384 deleteColumns.add(deleteColumn); 385 delete.setColumns(deleteColumns); 386 387 handler.deleteSingle(table, delete); 388 389 TGet get = new TGet(wrap(rowName)); 390 TResult result = handler.get(table, get); 391 assertArrayEquals(rowName, result.getRow()); 392 List<TColumnValue> returnedColumnValues = result.getColumnValues(); 393 List<TColumnValue> expectedColumnValues = new ArrayList<>(1); 394 expectedColumnValues.add(columnValueB); 395 assertTColumnValuesEqual(expectedColumnValues, returnedColumnValues); 396 } 397 398 @Test 399 public void testDeleteAllTimestamps() throws Exception { 400 ThriftHBaseServiceHandler handler = createHandler(); 401 byte[] rowName = Bytes.toBytes("testDeleteAllTimestamps"); 402 ByteBuffer table = wrap(tableAname); 403 404 List<TColumnValue> columnValues = new ArrayList<>(1); 405 TColumnValue columnValueA = 406 new TColumnValue(wrap(familyAname), wrap(qualifierAname), wrap(valueAname)); 407 columnValueA.setTimestamp(EnvironmentEdgeManager.currentTime() - 10); 408 columnValues.add(columnValueA); 409 TPut put = new TPut(wrap(rowName), columnValues); 410 411 put.setColumnValues(columnValues); 412 413 handler.put(table, put); 414 columnValueA.setTimestamp(EnvironmentEdgeManager.currentTime()); 415 handler.put(table, put); 416 417 TGet get = new TGet(wrap(rowName)); 418 get.setMaxVersions(2); 419 TResult result = handler.get(table, get); 420 assertEquals(2, result.getColumnValuesSize()); 421 422 TDelete delete = new TDelete(wrap(rowName)); 423 List<TColumn> deleteColumns = new ArrayList<>(1); 424 TColumn deleteColumn = new TColumn(wrap(familyAname)); 425 deleteColumn.setQualifier(qualifierAname); 426 deleteColumns.add(deleteColumn); 427 delete.setColumns(deleteColumns); 428 delete.setDeleteType(TDeleteType.DELETE_COLUMNS); // This is the default anyway. 429 430 handler.deleteSingle(table, delete); 431 432 get = new TGet(wrap(rowName)); 433 result = handler.get(table, get); 434 assertNull(result.getRow()); 435 assertEquals(0, result.getColumnValuesSize()); 436 } 437 438 @Test 439 public void testDeleteSingleTimestamp() throws Exception { 440 ThriftHBaseServiceHandler handler = createHandler(); 441 byte[] rowName = Bytes.toBytes("testDeleteSingleTimestamp"); 442 ByteBuffer table = wrap(tableAname); 443 444 long timestamp1 = EnvironmentEdgeManager.currentTime() - 10; 445 long timestamp2 = EnvironmentEdgeManager.currentTime(); 446 447 List<TColumnValue> columnValues = new ArrayList<>(1); 448 TColumnValue columnValueA = 449 new TColumnValue(wrap(familyAname), wrap(qualifierAname), wrap(valueAname)); 450 columnValueA.setTimestamp(timestamp1); 451 columnValues.add(columnValueA); 452 TPut put = new TPut(wrap(rowName), columnValues); 453 454 put.setColumnValues(columnValues); 455 456 handler.put(table, put); 457 columnValueA.setTimestamp(timestamp2); 458 handler.put(table, put); 459 460 TGet get = new TGet(wrap(rowName)); 461 get.setMaxVersions(2); 462 TResult result = handler.get(table, get); 463 assertEquals(2, result.getColumnValuesSize()); 464 465 TDelete delete = new TDelete(wrap(rowName)); 466 List<TColumn> deleteColumns = new ArrayList<>(1); 467 TColumn deleteColumn = new TColumn(wrap(familyAname)); 468 deleteColumn.setQualifier(qualifierAname); 469 deleteColumns.add(deleteColumn); 470 delete.setColumns(deleteColumns); 471 delete.setDeleteType(TDeleteType.DELETE_COLUMN); 472 473 handler.deleteSingle(table, delete); 474 475 get = new TGet(wrap(rowName)); 476 result = handler.get(table, get); 477 assertArrayEquals(rowName, result.getRow()); 478 assertEquals(1, result.getColumnValuesSize()); 479 // the older timestamp should remain. 480 assertEquals(timestamp1, result.getColumnValues().get(0).getTimestamp()); 481 } 482 483 @Test 484 public void testDeleteFamily() throws Exception { 485 ThriftHBaseServiceHandler handler = createHandler(); 486 byte[] rowName = Bytes.toBytes("testDeleteFamily"); 487 ByteBuffer table = wrap(tableAname); 488 489 long timestamp1 = EnvironmentEdgeManager.currentTime() - 10; 490 long timestamp2 = EnvironmentEdgeManager.currentTime(); 491 492 List<TColumnValue> columnValues = new ArrayList<>(); 493 TColumnValue columnValueA = 494 new TColumnValue(wrap(familyAname), wrap(qualifierAname), wrap(valueAname)); 495 columnValueA.setTimestamp(timestamp1); 496 columnValues.add(columnValueA); 497 TPut put = new TPut(wrap(rowName), columnValues); 498 499 put.setColumnValues(columnValues); 500 501 handler.put(table, put); 502 columnValueA.setTimestamp(timestamp2); 503 handler.put(table, put); 504 505 TGet get = new TGet(wrap(rowName)); 506 get.setMaxVersions(2); 507 TResult result = handler.get(table, get); 508 assertEquals(2, result.getColumnValuesSize()); 509 510 TDelete delete = new TDelete(wrap(rowName)); 511 List<TColumn> deleteColumns = new ArrayList<>(); 512 TColumn deleteColumn = new TColumn(wrap(familyAname)); 513 deleteColumns.add(deleteColumn); 514 delete.setColumns(deleteColumns); 515 delete.setDeleteType(TDeleteType.DELETE_FAMILY); 516 517 handler.deleteSingle(table, delete); 518 519 get = new TGet(wrap(rowName)); 520 result = handler.get(table, get); 521 assertArrayEquals(null, result.getRow()); 522 assertEquals(0, result.getColumnValuesSize()); 523 } 524 525 @Test 526 public void testDeleteFamilyVersion() throws Exception { 527 ThriftHBaseServiceHandler handler = createHandler(); 528 byte[] rowName = Bytes.toBytes("testDeleteFamilyVersion"); 529 ByteBuffer table = wrap(tableAname); 530 531 long timestamp1 = EnvironmentEdgeManager.currentTime() - 10; 532 long timestamp2 = EnvironmentEdgeManager.currentTime(); 533 534 List<TColumnValue> columnValues = new ArrayList<>(); 535 TColumnValue columnValueA = 536 new TColumnValue(wrap(familyAname), wrap(qualifierAname), wrap(valueAname)); 537 columnValueA.setTimestamp(timestamp1); 538 columnValues.add(columnValueA); 539 TPut put = new TPut(wrap(rowName), columnValues); 540 541 put.setColumnValues(columnValues); 542 543 handler.put(table, put); 544 columnValueA.setTimestamp(timestamp2); 545 handler.put(table, put); 546 547 TGet get = new TGet(wrap(rowName)); 548 get.setMaxVersions(2); 549 TResult result = handler.get(table, get); 550 assertEquals(2, result.getColumnValuesSize()); 551 552 TDelete delete = new TDelete(wrap(rowName)); 553 List<TColumn> deleteColumns = new ArrayList<>(); 554 TColumn deleteColumn = new TColumn(wrap(familyAname)); 555 deleteColumn.setTimestamp(timestamp1); 556 deleteColumns.add(deleteColumn); 557 delete.setColumns(deleteColumns); 558 delete.setDeleteType(TDeleteType.DELETE_FAMILY_VERSION); 559 560 handler.deleteSingle(table, delete); 561 562 get = new TGet(wrap(rowName)); 563 result = handler.get(table, get); 564 assertArrayEquals(rowName, result.getRow()); 565 assertEquals(1, result.getColumnValuesSize()); 566 assertEquals(timestamp2, result.getColumnValues().get(0).getTimestamp()); 567 } 568 569 @Test 570 public void testIncrement() throws Exception { 571 ThriftHBaseServiceHandler handler = createHandler(); 572 byte[] rowName = Bytes.toBytes("testIncrement"); 573 ByteBuffer table = wrap(tableAname); 574 575 List<TColumnValue> columnValues = new ArrayList<>(1); 576 columnValues 577 .add(new TColumnValue(wrap(familyAname), wrap(qualifierAname), wrap(Bytes.toBytes(1L)))); 578 TPut put = new TPut(wrap(rowName), columnValues); 579 put.setColumnValues(columnValues); 580 handler.put(table, put); 581 582 List<TColumnIncrement> incrementColumns = new ArrayList<>(1); 583 incrementColumns.add(new TColumnIncrement(wrap(familyAname), wrap(qualifierAname))); 584 TIncrement increment = new TIncrement(wrap(rowName), incrementColumns); 585 handler.increment(table, increment); 586 587 TGet get = new TGet(wrap(rowName)); 588 TResult result = handler.get(table, get); 589 590 assertArrayEquals(rowName, result.getRow()); 591 assertEquals(1, result.getColumnValuesSize()); 592 TColumnValue columnValue = result.getColumnValues().get(0); 593 assertArrayEquals(Bytes.toBytes(2L), columnValue.getValue()); 594 } 595 596 @Test 597 public void testAppend() throws Exception { 598 ThriftHBaseServiceHandler handler = createHandler(); 599 byte[] rowName = Bytes.toBytes("testAppend"); 600 ByteBuffer table = wrap(tableAname); 601 byte[] v1 = Bytes.toBytes("42"); 602 byte[] v2 = Bytes.toBytes("23"); 603 List<TColumnValue> columnValues = new ArrayList<>(1); 604 columnValues.add(new TColumnValue(wrap(familyAname), wrap(qualifierAname), wrap(v1))); 605 TPut put = new TPut(wrap(rowName), columnValues); 606 put.setColumnValues(columnValues); 607 handler.put(table, put); 608 609 List<TColumnValue> appendColumns = new ArrayList<>(1); 610 appendColumns.add(new TColumnValue(wrap(familyAname), wrap(qualifierAname), wrap(v2))); 611 TAppend append = new TAppend(wrap(rowName), appendColumns); 612 handler.append(table, append); 613 614 TGet get = new TGet(wrap(rowName)); 615 TResult result = handler.get(table, get); 616 617 assertArrayEquals(rowName, result.getRow()); 618 assertEquals(1, result.getColumnValuesSize()); 619 TColumnValue columnValue = result.getColumnValues().get(0); 620 assertArrayEquals(Bytes.add(v1, v2), columnValue.getValue()); 621 } 622 623 /** 624 * check that checkAndPut fails if the cell does not exist, then put in the cell, then check that 625 * the checkAndPut succeeds. 626 */ 627 @Test 628 public void testCheckAndPut() throws Exception { 629 ThriftHBaseServiceHandler handler = createHandler(); 630 byte[] rowName = Bytes.toBytes("testCheckAndPut"); 631 ByteBuffer table = wrap(tableAname); 632 633 List<TColumnValue> columnValuesA = new ArrayList<>(1); 634 TColumnValue columnValueA = 635 new TColumnValue(wrap(familyAname), wrap(qualifierAname), wrap(valueAname)); 636 columnValuesA.add(columnValueA); 637 TPut putA = new TPut(wrap(rowName), columnValuesA); 638 putA.setColumnValues(columnValuesA); 639 640 List<TColumnValue> columnValuesB = new ArrayList<>(1); 641 TColumnValue columnValueB = 642 new TColumnValue(wrap(familyBname), wrap(qualifierBname), wrap(valueBname)); 643 columnValuesB.add(columnValueB); 644 TPut putB = new TPut(wrap(rowName), columnValuesB); 645 putB.setColumnValues(columnValuesB); 646 647 assertFalse(handler.checkAndPut(table, wrap(rowName), wrap(familyAname), wrap(qualifierAname), 648 wrap(valueAname), putB)); 649 650 TGet get = new TGet(wrap(rowName)); 651 TResult result = handler.get(table, get); 652 assertEquals(0, result.getColumnValuesSize()); 653 654 handler.put(table, putA); 655 656 assertTrue(handler.checkAndPut(table, wrap(rowName), wrap(familyAname), wrap(qualifierAname), 657 wrap(valueAname), putB)); 658 659 result = handler.get(table, get); 660 assertArrayEquals(rowName, result.getRow()); 661 List<TColumnValue> returnedColumnValues = result.getColumnValues(); 662 List<TColumnValue> expectedColumnValues = new ArrayList<>(2); 663 expectedColumnValues.add(columnValueA); 664 expectedColumnValues.add(columnValueB); 665 assertTColumnValuesEqual(expectedColumnValues, returnedColumnValues); 666 } 667 668 /** 669 * check that checkAndDelete fails if the cell does not exist, then put in the cell, then check 670 * that the checkAndDelete succeeds. 671 */ 672 @Test 673 public void testCheckAndDelete() throws Exception { 674 ThriftHBaseServiceHandler handler = createHandler(); 675 byte[] rowName = Bytes.toBytes("testCheckAndDelete"); 676 ByteBuffer table = wrap(tableAname); 677 678 List<TColumnValue> columnValuesA = new ArrayList<>(1); 679 TColumnValue columnValueA = 680 new TColumnValue(wrap(familyAname), wrap(qualifierAname), wrap(valueAname)); 681 columnValuesA.add(columnValueA); 682 TPut putA = new TPut(wrap(rowName), columnValuesA); 683 putA.setColumnValues(columnValuesA); 684 685 List<TColumnValue> columnValuesB = new ArrayList<>(1); 686 TColumnValue columnValueB = 687 new TColumnValue(wrap(familyBname), wrap(qualifierBname), wrap(valueBname)); 688 columnValuesB.add(columnValueB); 689 TPut putB = new TPut(wrap(rowName), columnValuesB); 690 putB.setColumnValues(columnValuesB); 691 692 // put putB so that we know whether the row has been deleted or not 693 handler.put(table, putB); 694 695 TDelete delete = new TDelete(wrap(rowName)); 696 697 assertFalse(handler.checkAndDelete(table, wrap(rowName), wrap(familyAname), 698 wrap(qualifierAname), wrap(valueAname), delete)); 699 700 TGet get = new TGet(wrap(rowName)); 701 TResult result = handler.get(table, get); 702 assertArrayEquals(rowName, result.getRow()); 703 assertTColumnValuesEqual(columnValuesB, result.getColumnValues()); 704 705 handler.put(table, putA); 706 707 assertTrue(handler.checkAndDelete(table, wrap(rowName), wrap(familyAname), wrap(qualifierAname), 708 wrap(valueAname), delete)); 709 710 result = handler.get(table, get); 711 assertFalse(result.isSetRow()); 712 assertEquals(0, result.getColumnValuesSize()); 713 } 714 715 @Test 716 public void testScan() throws Exception { 717 ThriftHBaseServiceHandler handler = createHandler(); 718 ByteBuffer table = wrap(tableAname); 719 720 // insert data 721 TColumnValue columnValue = 722 new TColumnValue(wrap(familyAname), wrap(qualifierAname), wrap(valueAname)); 723 List<TColumnValue> columnValues = new ArrayList<>(1); 724 columnValues.add(columnValue); 725 for (int i = 0; i < 10; i++) { 726 TPut put = new TPut(wrap(Bytes.toBytes("testScan" + i)), columnValues); 727 handler.put(table, put); 728 } 729 730 // create scan instance 731 TScan scan = new TScan(); 732 List<TColumn> columns = new ArrayList<>(1); 733 TColumn column = new TColumn(); 734 column.setFamily(familyAname); 735 column.setQualifier(qualifierAname); 736 columns.add(column); 737 scan.setColumns(columns); 738 scan.setStartRow(Bytes.toBytes("testScan")); 739 scan.setStopRow(Bytes.toBytes("testScan\uffff")); 740 741 // get scanner and rows 742 int scanId = handler.openScanner(table, scan); 743 List<TResult> results = handler.getScannerRows(scanId, 10); 744 assertEquals(10, results.size()); 745 for (int i = 0; i < 10; i++) { 746 // check if the rows are returned and in order 747 assertArrayEquals(Bytes.toBytes("testScan" + i), results.get(i).getRow()); 748 } 749 750 // check that we are at the end of the scan 751 results = handler.getScannerRows(scanId, 10); 752 assertEquals(0, results.size()); 753 754 // close scanner and check that it was indeed closed 755 handler.closeScanner(scanId); 756 try { 757 handler.getScannerRows(scanId, 10); 758 fail("Scanner id should be invalid"); 759 } catch (TIllegalArgument e) { 760 } 761 } 762 763 /** 764 * Tests keeping a HBase scanner alive for long periods of time. Each call to getScannerRow() 765 * should reset the ConnectionCache timeout for the scanner's connection 766 */ 767 @org.junit.Ignore 768 @Test // Flakey. Diasabled by HBASE-24079. Renable with Fails with HBASE-24083. 769 // Caused by: java.util.concurrent.RejectedExecutionException: 770 // Task org.apache.hadoop.hbase.client.ResultBoundedCompletionService$QueueingFuture@e385431 771 // rejected from java.util.concurrent.ThreadPoolExecutor@ 52b027d[Terminated, pool size = 0, 772 // active threads = 0, queued tasks = 0, completed tasks = 1] 773 // at org.apache.hadoop.hbase.thrift2.TestThriftHBaseServiceHandler. 774 // testLongLivedScan(TestThriftHBaseServiceHandler.java:804) 775 public void testLongLivedScan() throws Exception { 776 int numTrials = 6; 777 int trialPause = 1000; 778 int cleanUpInterval = 100; 779 Configuration conf = new Configuration(UTIL.getConfiguration()); 780 // Set the ConnectionCache timeout to trigger halfway through the trials 781 conf.setInt(MAX_IDLETIME, (numTrials / 2) * trialPause); 782 conf.setInt(CLEANUP_INTERVAL, cleanUpInterval); 783 ThriftHBaseServiceHandler handler = 784 new ThriftHBaseServiceHandler(conf, UserProvider.instantiate(conf)); 785 786 ByteBuffer table = wrap(tableAname); 787 // insert data 788 TColumnValue columnValue = 789 new TColumnValue(wrap(familyAname), wrap(qualifierAname), wrap(valueAname)); 790 List<TColumnValue> columnValues = new ArrayList<>(1); 791 columnValues.add(columnValue); 792 for (int i = 0; i < numTrials; i++) { 793 TPut put = new TPut(wrap(Bytes.toBytes("testScan" + i)), columnValues); 794 handler.put(table, put); 795 } 796 797 // create scan instance 798 TScan scan = new TScan(); 799 List<TColumn> columns = new ArrayList<>(1); 800 TColumn column = new TColumn(); 801 column.setFamily(familyAname); 802 column.setQualifier(qualifierAname); 803 columns.add(column); 804 scan.setColumns(columns); 805 scan.setStartRow(Bytes.toBytes("testScan")); 806 scan.setStopRow(Bytes.toBytes("testScan\uffff")); 807 // Prevent the scanner from caching results 808 scan.setCaching(1); 809 810 // get scanner and rows 811 int scanId = handler.openScanner(table, scan); 812 for (int i = 0; i < numTrials; i++) { 813 // Make sure that the Scanner doesn't throw an exception after the ConnectionCache timeout 814 List<TResult> results = handler.getScannerRows(scanId, 1); 815 assertArrayEquals(Bytes.toBytes("testScan" + i), results.get(0).getRow()); 816 Thread.sleep(trialPause); 817 } 818 } 819 820 @Test 821 public void testReverseScan() throws Exception { 822 ThriftHBaseServiceHandler handler = createHandler(); 823 ByteBuffer table = wrap(tableAname); 824 825 // insert data 826 TColumnValue columnValue = 827 new TColumnValue(wrap(familyAname), wrap(qualifierAname), wrap(valueAname)); 828 List<TColumnValue> columnValues = new ArrayList<>(1); 829 columnValues.add(columnValue); 830 for (int i = 0; i < 10; i++) { 831 TPut put = new TPut(wrap(Bytes.toBytes("testReverseScan" + i)), columnValues); 832 handler.put(table, put); 833 } 834 835 // create reverse scan instance 836 TScan scan = new TScan(); 837 scan.setReversed(true); 838 List<TColumn> columns = new ArrayList<>(1); 839 TColumn column = new TColumn(); 840 column.setFamily(familyAname); 841 column.setQualifier(qualifierAname); 842 columns.add(column); 843 scan.setColumns(columns); 844 scan.setStartRow(Bytes.toBytes("testReverseScan\uffff")); 845 scan.setStopRow(Bytes.toBytes("testReverseScan")); 846 847 // get scanner and rows 848 int scanId = handler.openScanner(table, scan); 849 List<TResult> results = handler.getScannerRows(scanId, 10); 850 assertEquals(10, results.size()); 851 for (int i = 0; i < 10; i++) { 852 // check if the rows are returned and in order 853 assertArrayEquals(Bytes.toBytes("testReverseScan" + (9 - i)), results.get(i).getRow()); 854 } 855 856 // check that we are at the end of the scan 857 results = handler.getScannerRows(scanId, 10); 858 assertEquals(0, results.size()); 859 860 // close scanner and check that it was indeed closed 861 handler.closeScanner(scanId); 862 try { 863 handler.getScannerRows(scanId, 10); 864 fail("Scanner id should be invalid"); 865 } catch (TIllegalArgument e) { 866 } 867 } 868 869 @Test 870 public void testScanWithFilter() throws Exception { 871 ThriftHBaseServiceHandler handler = createHandler(); 872 ByteBuffer table = wrap(tableAname); 873 874 // insert data 875 TColumnValue columnValue = 876 new TColumnValue(wrap(familyAname), wrap(qualifierAname), wrap(valueAname)); 877 List<TColumnValue> columnValues = new ArrayList<>(1); 878 columnValues.add(columnValue); 879 for (int i = 0; i < 10; i++) { 880 TPut put = new TPut(wrap(Bytes.toBytes("testScanWithFilter" + i)), columnValues); 881 handler.put(table, put); 882 } 883 884 // create scan instance with filter 885 TScan scan = new TScan(); 886 List<TColumn> columns = new ArrayList<>(1); 887 TColumn column = new TColumn(); 888 column.setFamily(familyAname); 889 column.setQualifier(qualifierAname); 890 columns.add(column); 891 scan.setColumns(columns); 892 scan.setStartRow(Bytes.toBytes("testScanWithFilter")); 893 scan.setStopRow(Bytes.toBytes("testScanWithFilter\uffff")); 894 // only get the key part 895 scan.setFilterString(wrap(Bytes.toBytes("KeyOnlyFilter()"))); 896 897 // get scanner and rows 898 int scanId = handler.openScanner(table, scan); 899 List<TResult> results = handler.getScannerRows(scanId, 10); 900 assertEquals(10, results.size()); 901 for (int i = 0; i < 10; i++) { 902 // check if the rows are returned and in order 903 assertArrayEquals(Bytes.toBytes("testScanWithFilter" + i), results.get(i).getRow()); 904 // check that the value is indeed stripped by the filter 905 assertEquals(0, results.get(i).getColumnValues().get(0).getValue().length); 906 } 907 908 // check that we are at the end of the scan 909 results = handler.getScannerRows(scanId, 10); 910 assertEquals(0, results.size()); 911 912 // close scanner and check that it was indeed closed 913 handler.closeScanner(scanId); 914 try { 915 handler.getScannerRows(scanId, 10); 916 fail("Scanner id should be invalid"); 917 } catch (TIllegalArgument e) { 918 } 919 } 920 921 @Test 922 public void testScanWithColumnFamilyTimeRange() throws Exception { 923 ThriftHBaseServiceHandler handler = createHandler(); 924 ByteBuffer table = wrap(tableAname); 925 926 // insert data 927 TColumnValue familyAColumnValue = 928 new TColumnValue(wrap(familyAname), wrap(qualifierAname), wrap(valueAname)); 929 TColumnValue familyBColumnValue = 930 new TColumnValue(wrap(familyBname), wrap(qualifierBname), wrap(valueBname)); 931 long minTimestamp = EnvironmentEdgeManager.currentTime(); 932 for (int i = 0; i < 10; i++) { 933 familyAColumnValue.setTimestamp(minTimestamp + i); 934 familyBColumnValue.setTimestamp(minTimestamp + i); 935 List<TColumnValue> columnValues = new ArrayList<>(2); 936 columnValues.add(familyAColumnValue); 937 columnValues.add(familyBColumnValue); 938 TPut put = 939 new TPut(wrap(Bytes.toBytes("testScanWithColumnFamilyTimeRange" + i)), columnValues); 940 handler.put(table, put); 941 } 942 943 // create scan instance with column family time range 944 TScan scan = new TScan(); 945 Map<ByteBuffer, TTimeRange> colFamTimeRangeMap = new HashMap<>(2); 946 colFamTimeRangeMap.put(wrap(familyAname), new TTimeRange(minTimestamp + 3, minTimestamp + 5)); 947 colFamTimeRangeMap.put(wrap(familyBname), new TTimeRange(minTimestamp + 6, minTimestamp + 9)); 948 scan.setColFamTimeRangeMap(colFamTimeRangeMap); 949 950 // get scanner and rows 951 int scanId = handler.openScanner(table, scan); 952 List<TResult> results = handler.getScannerRows(scanId, 5); 953 assertEquals(5, results.size()); 954 int familyACount = 0; 955 int familyBCount = 0; 956 for (TResult result : results) { 957 List<TColumnValue> columnValues = result.getColumnValues(); 958 if (CollectionUtils.isNotEmpty(columnValues)) { 959 if (Bytes.equals(familyAname, columnValues.get(0).getFamily())) { 960 familyACount++; 961 } else if (Bytes.equals(familyBname, columnValues.get(0).getFamily())) { 962 familyBCount++; 963 } 964 } 965 } 966 assertEquals(2, familyACount); 967 assertEquals(3, familyBCount); 968 969 // check that we are at the end of the scan 970 results = handler.getScannerRows(scanId, 1); 971 assertEquals(0, results.size()); 972 973 // close scanner and check that it was indeed closed 974 handler.closeScanner(scanId); 975 try { 976 handler.getScannerRows(scanId, 1); 977 fail("Scanner id should be invalid"); 978 } catch (TIllegalArgument e) { 979 } 980 } 981 982 @Test 983 public void testSmallScan() throws Exception { 984 ThriftHBaseServiceHandler handler = createHandler(); 985 ByteBuffer table = wrap(tableAname); 986 987 // insert data 988 TColumnValue columnValue = 989 new TColumnValue(wrap(familyAname), wrap(qualifierAname), wrap(valueAname)); 990 List<TColumnValue> columnValues = new ArrayList<>(); 991 columnValues.add(columnValue); 992 for (int i = 0; i < 10; i++) { 993 TPut put = new TPut(wrap(Bytes.toBytes("testSmallScan" + i)), columnValues); 994 handler.put(table, put); 995 } 996 997 // small scan instance 998 TScan scan = new TScan(); 999 scan.setStartRow(Bytes.toBytes("testSmallScan")); 1000 scan.setStopRow(Bytes.toBytes("testSmallScan\uffff")); 1001 scan.setReadType(TReadType.PREAD); 1002 scan.setCaching(2); 1003 1004 // get scanner and rows 1005 int scanId = handler.openScanner(table, scan); 1006 List<TResult> results = handler.getScannerRows(scanId, 10); 1007 assertEquals(10, results.size()); 1008 for (int i = 0; i < 10; i++) { 1009 // check if the rows are returned and in order 1010 assertArrayEquals(Bytes.toBytes("testSmallScan" + i), results.get(i).getRow()); 1011 } 1012 1013 // check that we are at the end of the scan 1014 results = handler.getScannerRows(scanId, 10); 1015 assertEquals(0, results.size()); 1016 1017 // close scanner and check that it was indeed closed 1018 handler.closeScanner(scanId); 1019 try { 1020 handler.getScannerRows(scanId, 10); 1021 fail("Scanner id should be invalid"); 1022 } catch (TIllegalArgument e) { 1023 } 1024 } 1025 1026 @Test 1027 public void testExpiredScanner() throws Exception { 1028 Configuration conf = UTIL.getConfiguration(); 1029 conf.setLong(HBASE_CLIENT_SCANNER_TIMEOUT_PERIOD, 1000); 1030 ThriftHBaseServiceHandler handler = 1031 new ThriftHBaseServiceHandler(conf, UserProvider.instantiate(conf)); 1032 1033 TScan scan = new TScan(); 1034 ByteBuffer table = wrap(tableAname); 1035 1036 int scannerId = handler.openScanner(table, scan); 1037 handler.getScannerRows(scannerId, 1); 1038 Thread.sleep(1000); 1039 1040 try { 1041 handler.getScannerRows(scannerId, 1); 1042 fail("The scanner should be expired and have an TIllegalArgument exception here."); 1043 } catch (TIllegalArgument e) { 1044 assertEquals("Invalid scanner Id", e.getMessage()); 1045 } finally { 1046 conf.setLong(HBASE_CLIENT_SCANNER_TIMEOUT_PERIOD, 1047 DEFAULT_HBASE_CLIENT_SCANNER_TIMEOUT_PERIOD); 1048 } 1049 } 1050 1051 @Test 1052 public void testPutTTL() throws Exception { 1053 ThriftHBaseServiceHandler handler = createHandler(); 1054 byte[] rowName = Bytes.toBytes("testPutTTL"); 1055 ByteBuffer table = wrap(tableAname); 1056 List<TColumnValue> columnValues = new ArrayList<>(1); 1057 1058 // Add some dummy data 1059 columnValues 1060 .add(new TColumnValue(wrap(familyAname), wrap(qualifierAname), wrap(Bytes.toBytes(1L)))); 1061 1062 TPut put = new TPut(wrap(rowName), columnValues); 1063 put.setColumnValues(columnValues); 1064 1065 Map<ByteBuffer, ByteBuffer> attributes = new HashMap<>(); 1066 1067 // Time in ms for the kv's to live. 1068 long ttlTimeMs = 2000L; 1069 1070 // the _ttl attribute is a number of ms ttl for key values in this put. 1071 attributes.put(wrap(Bytes.toBytes("_ttl")), wrap(Bytes.toBytes(ttlTimeMs))); 1072 // Attach the attributes 1073 put.setAttributes(attributes); 1074 // Send it. 1075 handler.put(table, put); 1076 1077 // Now get the data back 1078 TGet getOne = new TGet(wrap(rowName)); 1079 TResult resultOne = handler.get(table, getOne); 1080 1081 // It's there. 1082 assertArrayEquals(rowName, resultOne.getRow()); 1083 assertEquals(1, resultOne.getColumnValuesSize()); 1084 1085 // Sleep 30 seconds just to make 100% sure that the key value should be expired. 1086 Thread.sleep(ttlTimeMs * 15); 1087 1088 TGet getTwo = new TGet(wrap(rowName)); 1089 TResult resultTwo = handler.get(table, getTwo); 1090 1091 // Nothing should be there since it's ttl'd out. 1092 assertNull(resultTwo.getRow()); 1093 assertEquals(0, resultTwo.getColumnValuesSize()); 1094 } 1095 1096 /** 1097 * Padding numbers to make comparison of sort order easier in a for loop 1098 * @param n The number to pad. 1099 * @param pad The length to pad up to. 1100 * @return The padded number as a string. 1101 */ 1102 private String pad(int n, byte pad) { 1103 String res = Integer.toString(n); 1104 while (res.length() < pad) { 1105 res = "0" + res; 1106 } 1107 return res; 1108 } 1109 1110 @Test 1111 public void testScanWithBatchSize() throws Exception { 1112 ThriftHBaseServiceHandler handler = createHandler(); 1113 ByteBuffer table = wrap(tableAname); 1114 1115 // insert data 1116 List<TColumnValue> columnValues = new ArrayList<>(100); 1117 for (int i = 0; i < 100; i++) { 1118 String colNum = pad(i, (byte) 3); 1119 TColumnValue columnValue = new TColumnValue(wrap(familyAname), 1120 wrap(Bytes.toBytes("col" + colNum)), wrap(Bytes.toBytes("val" + colNum))); 1121 columnValues.add(columnValue); 1122 } 1123 TPut put = new TPut(wrap(Bytes.toBytes("testScanWithBatchSize")), columnValues); 1124 handler.put(table, put); 1125 1126 // create scan instance 1127 TScan scan = new TScan(); 1128 List<TColumn> columns = new ArrayList<>(1); 1129 TColumn column = new TColumn(); 1130 column.setFamily(familyAname); 1131 columns.add(column); 1132 scan.setColumns(columns); 1133 scan.setStartRow(Bytes.toBytes("testScanWithBatchSize")); 1134 scan.setStopRow(Bytes.toBytes("testScanWithBatchSize\uffff")); 1135 // set batch size to 10 columns per call 1136 scan.setBatchSize(10); 1137 1138 // get scanner 1139 int scanId = handler.openScanner(table, scan); 1140 List<TResult> results = null; 1141 for (int i = 0; i < 10; i++) { 1142 // get batch for single row (10x10 is what we expect) 1143 results = handler.getScannerRows(scanId, 1); 1144 assertEquals(1, results.size()); 1145 // check length of batch 1146 List<TColumnValue> cols = results.get(0).getColumnValues(); 1147 assertEquals(10, cols.size()); 1148 // check if the columns are returned and in order 1149 for (int y = 0; y < 10; y++) { 1150 int colNum = y + (10 * i); 1151 String colNumPad = pad(colNum, (byte) 3); 1152 assertArrayEquals(Bytes.toBytes("col" + colNumPad), cols.get(y).getQualifier()); 1153 } 1154 } 1155 1156 // check that we are at the end of the scan 1157 results = handler.getScannerRows(scanId, 1); 1158 assertEquals(0, results.size()); 1159 1160 // close scanner and check that it was indeed closed 1161 handler.closeScanner(scanId); 1162 try { 1163 handler.getScannerRows(scanId, 1); 1164 fail("Scanner id should be invalid"); 1165 } catch (TIllegalArgument e) { 1166 } 1167 } 1168 1169 @Test 1170 public void testGetScannerResults() throws Exception { 1171 ThriftHBaseServiceHandler handler = createHandler(); 1172 ByteBuffer table = wrap(tableAname); 1173 1174 // insert data 1175 TColumnValue columnValue = 1176 new TColumnValue(wrap(familyAname), wrap(qualifierAname), wrap(valueAname)); 1177 List<TColumnValue> columnValues = new ArrayList<>(1); 1178 columnValues.add(columnValue); 1179 for (int i = 0; i < 20; i++) { 1180 TPut put = 1181 new TPut(wrap(Bytes.toBytes("testGetScannerResults" + pad(i, (byte) 2))), columnValues); 1182 handler.put(table, put); 1183 } 1184 1185 // create scan instance 1186 TScan scan = new TScan(); 1187 List<TColumn> columns = new ArrayList<>(1); 1188 TColumn column = new TColumn(); 1189 column.setFamily(familyAname); 1190 column.setQualifier(qualifierAname); 1191 columns.add(column); 1192 scan.setColumns(columns); 1193 scan.setStartRow(Bytes.toBytes("testGetScannerResults")); 1194 1195 // get 5 rows and check the returned results 1196 scan.setStopRow(Bytes.toBytes("testGetScannerResults05")); 1197 List<TResult> results = handler.getScannerResults(table, scan, 5); 1198 assertEquals(5, results.size()); 1199 for (int i = 0; i < 5; i++) { 1200 // check if the rows are returned and in order 1201 assertArrayEquals(Bytes.toBytes("testGetScannerResults" + pad(i, (byte) 2)), 1202 results.get(i).getRow()); 1203 } 1204 1205 // get 10 rows and check the returned results 1206 scan.setStopRow(Bytes.toBytes("testGetScannerResults10")); 1207 results = handler.getScannerResults(table, scan, 10); 1208 assertEquals(10, results.size()); 1209 for (int i = 0; i < 10; i++) { 1210 // check if the rows are returned and in order 1211 assertArrayEquals(Bytes.toBytes("testGetScannerResults" + pad(i, (byte) 2)), 1212 results.get(i).getRow()); 1213 } 1214 1215 // get 20 rows and check the returned results 1216 scan.setStopRow(Bytes.toBytes("testGetScannerResults20")); 1217 results = handler.getScannerResults(table, scan, 20); 1218 assertEquals(20, results.size()); 1219 for (int i = 0; i < 20; i++) { 1220 // check if the rows are returned and in order 1221 assertArrayEquals(Bytes.toBytes("testGetScannerResults" + pad(i, (byte) 2)), 1222 results.get(i).getRow()); 1223 } 1224 1225 // reverse scan 1226 scan = new TScan(); 1227 scan.setColumns(columns); 1228 scan.setReversed(true); 1229 scan.setStartRow(Bytes.toBytes("testGetScannerResults20")); 1230 scan.setStopRow(Bytes.toBytes("testGetScannerResults")); 1231 results = handler.getScannerResults(table, scan, 20); 1232 assertEquals(20, results.size()); 1233 for (int i = 0; i < 20; i++) { 1234 // check if the rows are returned and in order 1235 assertArrayEquals(Bytes.toBytes("testGetScannerResults" + pad(19 - i, (byte) 2)), 1236 results.get(i).getRow()); 1237 } 1238 } 1239 1240 @Test 1241 public void testFilterRegistration() throws Exception { 1242 Configuration conf = UTIL.getConfiguration(); 1243 conf.set("hbase.thrift.filters", "MyFilter:filterclass"); 1244 ThriftServer.registerFilters(conf); 1245 Map<String, String> registeredFilters = ParseFilter.getAllFilters(); 1246 assertEquals("filterclass", registeredFilters.get("MyFilter")); 1247 } 1248 1249 @Test 1250 public void testMetrics() throws Exception { 1251 Configuration conf = UTIL.getConfiguration(); 1252 ThriftMetrics metrics = getMetrics(conf); 1253 ThriftHBaseServiceHandler hbaseHandler = createHandler(); 1254 THBaseService.Iface handler = HbaseHandlerMetricsProxy.newInstance(hbaseHandler, metrics, conf); 1255 byte[] rowName = Bytes.toBytes("testMetrics"); 1256 ByteBuffer table = wrap(tableAname); 1257 1258 TGet get = new TGet(wrap(rowName)); 1259 assertFalse(handler.exists(table, get)); 1260 1261 List<TColumnValue> columnValues = new ArrayList<>(2); 1262 columnValues.add(new TColumnValue(wrap(familyAname), wrap(qualifierAname), wrap(valueAname))); 1263 columnValues.add(new TColumnValue(wrap(familyBname), wrap(qualifierBname), wrap(valueBname))); 1264 TPut put = new TPut(wrap(rowName), columnValues); 1265 put.setColumnValues(columnValues); 1266 1267 handler.put(table, put); 1268 1269 assertTrue(handler.exists(table, get)); 1270 metricsHelper.assertCounter("put_num_ops", 1, metrics.getSource()); 1271 metricsHelper.assertCounter("exists_num_ops", 2, metrics.getSource()); 1272 } 1273 1274 private static ThriftMetrics getMetrics(Configuration conf) throws Exception { 1275 ThriftMetrics m = new ThriftMetrics(conf, ThriftMetrics.ThriftServerType.TWO); 1276 m.getSource().init(); // Clear all the metrics 1277 return m; 1278 } 1279 1280 @Test 1281 public void testMetricsWithException() throws Exception { 1282 byte[] rowkey = Bytes.toBytes("row1"); 1283 byte[] family = Bytes.toBytes("f"); 1284 byte[] col = Bytes.toBytes("c"); 1285 // create a table which will throw exceptions for requests 1286 TableName tableName = TableName.valueOf(name.getMethodName()); 1287 HTableDescriptor tableDesc = new HTableDescriptor(tableName); 1288 tableDesc.addCoprocessor(ErrorThrowingGetObserver.class.getName()); 1289 tableDesc.addFamily(new HColumnDescriptor(family)); 1290 1291 Table table = UTIL.createTable(tableDesc, null); 1292 table.put(new Put(rowkey).addColumn(family, col, Bytes.toBytes("val1"))); 1293 1294 ThriftHBaseServiceHandler hbaseHandler = createHandler(); 1295 ThriftMetrics metrics = getMetrics(UTIL.getConfiguration()); 1296 THBaseService.Iface handler = HbaseHandlerMetricsProxy.newInstance(hbaseHandler, metrics, null); 1297 ByteBuffer tTableName = wrap(tableName.getName()); 1298 1299 // check metrics increment with a successful get 1300 long preGetCounter = metricsHelper.checkCounterExists("get_num_ops", metrics.getSource()) 1301 ? metricsHelper.getCounter("get_num_ops", metrics.getSource()) 1302 : 0; 1303 TGet tGet = new TGet(wrap(rowkey)); 1304 TResult tResult = handler.get(tTableName, tGet); 1305 1306 List<TColumnValue> expectedColumnValues = 1307 Lists.newArrayList(new TColumnValue(wrap(family), wrap(col), wrap(Bytes.toBytes("val1")))); 1308 assertArrayEquals(rowkey, tResult.getRow()); 1309 List<TColumnValue> returnedColumnValues = tResult.getColumnValues(); 1310 assertTColumnValuesEqual(expectedColumnValues, returnedColumnValues); 1311 1312 metricsHelper.assertCounter("get_num_ops", preGetCounter + 1, metrics.getSource()); 1313 1314 // check metrics increment when the get throws each exception type 1315 for (ErrorThrowingGetObserver.ErrorType type : ErrorThrowingGetObserver.ErrorType.values()) { 1316 testExceptionType(handler, metrics, tTableName, rowkey, type); 1317 } 1318 } 1319 1320 private void testExceptionType(THBaseService.Iface handler, ThriftMetrics metrics, 1321 ByteBuffer tTableName, byte[] rowkey, ErrorThrowingGetObserver.ErrorType errorType) { 1322 long preGetCounter = metricsHelper.getCounter("get_num_ops", metrics.getSource()); 1323 String exceptionKey = errorType.getMetricName(); 1324 long preExceptionCounter = metricsHelper.checkCounterExists(exceptionKey, metrics.getSource()) 1325 ? metricsHelper.getCounter(exceptionKey, metrics.getSource()) 1326 : 0; 1327 TGet tGet = new TGet(wrap(rowkey)); 1328 Map<ByteBuffer, ByteBuffer> attributes = new HashMap<>(); 1329 attributes.put(wrap(Bytes.toBytes(ErrorThrowingGetObserver.SHOULD_ERROR_ATTRIBUTE)), 1330 wrap(Bytes.toBytes(errorType.name()))); 1331 tGet.setAttributes(attributes); 1332 try { 1333 TResult tResult = handler.get(tTableName, tGet); 1334 fail("Get with error attribute should have thrown an exception"); 1335 } catch (TException e) { 1336 LOG.info("Received exception: ", e); 1337 metricsHelper.assertCounter("get_num_ops", preGetCounter + 1, metrics.getSource()); 1338 metricsHelper.assertCounter(exceptionKey, preExceptionCounter + 1, metrics.getSource()); 1339 } 1340 1341 } 1342 1343 /** 1344 * See HBASE-17611 Latency metrics were capped at ~ 2 seconds due to the use of an int variable to 1345 * capture the duration. 1346 */ 1347 @Test 1348 public void testMetricsPrecision() throws Exception { 1349 byte[] rowkey = Bytes.toBytes("row1"); 1350 byte[] family = Bytes.toBytes("f"); 1351 byte[] col = Bytes.toBytes("c"); 1352 // create a table which will throw exceptions for requests 1353 TableName tableName = TableName.valueOf("testMetricsPrecision"); 1354 HTableDescriptor tableDesc = new HTableDescriptor(tableName); 1355 tableDesc.addCoprocessor(DelayingRegionObserver.class.getName()); 1356 tableDesc.addFamily(new HColumnDescriptor(family)); 1357 1358 Table table = null; 1359 try { 1360 table = UTIL.createTable(tableDesc, null); 1361 1362 table.put(new Put(rowkey).addColumn(family, col, Bytes.toBytes("val1"))); 1363 1364 ThriftHBaseServiceHandler hbaseHandler = createHandler(); 1365 ThriftMetrics metrics = getMetrics(UTIL.getConfiguration()); 1366 THBaseService.Iface handler = 1367 HbaseHandlerMetricsProxy.newInstance(hbaseHandler, metrics, null); 1368 ByteBuffer tTableName = wrap(tableName.getName()); 1369 1370 // check metrics latency with a successful get 1371 TGet tGet = new TGet(wrap(rowkey)); 1372 TResult tResult = handler.get(tTableName, tGet); 1373 1374 List<TColumnValue> expectedColumnValues = 1375 Lists.newArrayList(new TColumnValue(wrap(family), wrap(col), wrap(Bytes.toBytes("val1")))); 1376 assertArrayEquals(rowkey, tResult.getRow()); 1377 List<TColumnValue> returnedColumnValues = tResult.getColumnValues(); 1378 assertTColumnValuesEqual(expectedColumnValues, returnedColumnValues); 1379 1380 metricsHelper.assertGaugeGt("get_max", 3000L, metrics.getSource()); 1381 } finally { 1382 if (table != null) { 1383 try { 1384 table.close(); 1385 } catch (IOException ignored) { 1386 } 1387 UTIL.deleteTable(tableName); 1388 } 1389 } 1390 } 1391 1392 @Test 1393 public void testAttribute() throws Exception { 1394 byte[] rowName = Bytes.toBytes("testAttribute"); 1395 byte[] attributeKey = Bytes.toBytes("attribute1"); 1396 byte[] attributeValue = Bytes.toBytes("value1"); 1397 Map<ByteBuffer, ByteBuffer> attributes = new HashMap<>(); 1398 attributes.put(wrap(attributeKey), wrap(attributeValue)); 1399 1400 TGet tGet = new TGet(wrap(rowName)); 1401 tGet.setAttributes(attributes); 1402 Get get = getFromThrift(tGet); 1403 assertArrayEquals(get.getAttribute("attribute1"), attributeValue); 1404 1405 List<TColumnValue> columnValues = new ArrayList<>(1); 1406 columnValues.add(new TColumnValue(wrap(familyAname), wrap(qualifierAname), wrap(valueAname))); 1407 TPut tPut = new TPut(wrap(rowName), columnValues); 1408 tPut.setAttributes(attributes); 1409 Put put = putFromThrift(tPut); 1410 assertArrayEquals(put.getAttribute("attribute1"), attributeValue); 1411 1412 TScan tScan = new TScan(); 1413 tScan.setAttributes(attributes); 1414 Scan scan = scanFromThrift(tScan); 1415 assertArrayEquals(scan.getAttribute("attribute1"), attributeValue); 1416 1417 List<TColumnIncrement> incrementColumns = new ArrayList<>(1); 1418 incrementColumns.add(new TColumnIncrement(wrap(familyAname), wrap(qualifierAname))); 1419 TIncrement tIncrement = new TIncrement(wrap(rowName), incrementColumns); 1420 tIncrement.setAttributes(attributes); 1421 Increment increment = incrementFromThrift(tIncrement); 1422 assertArrayEquals(increment.getAttribute("attribute1"), attributeValue); 1423 1424 TDelete tDelete = new TDelete(wrap(rowName)); 1425 tDelete.setAttributes(attributes); 1426 Delete delete = deleteFromThrift(tDelete); 1427 assertArrayEquals(delete.getAttribute("attribute1"), attributeValue); 1428 } 1429 1430 /** 1431 * Put valueA to a row, make sure put has happened, then create a mutation object to put valueB 1432 * and delete ValueA, then check that the row value is only valueB. 1433 */ 1434 @Test 1435 public void testMutateRow() throws Exception { 1436 ThriftHBaseServiceHandler handler = createHandler(); 1437 byte[] rowName = Bytes.toBytes("testMutateRow"); 1438 ByteBuffer table = wrap(tableAname); 1439 1440 List<TColumnValue> columnValuesA = new ArrayList<>(1); 1441 TColumnValue columnValueA = 1442 new TColumnValue(wrap(familyAname), wrap(qualifierAname), wrap(valueAname)); 1443 columnValuesA.add(columnValueA); 1444 TPut putA = new TPut(wrap(rowName), columnValuesA); 1445 putA.setColumnValues(columnValuesA); 1446 1447 handler.put(table, putA); 1448 1449 TGet get = new TGet(wrap(rowName)); 1450 TResult result = handler.get(table, get); 1451 assertArrayEquals(rowName, result.getRow()); 1452 List<TColumnValue> returnedColumnValues = result.getColumnValues(); 1453 1454 List<TColumnValue> expectedColumnValues = new ArrayList<>(1); 1455 expectedColumnValues.add(columnValueA); 1456 assertTColumnValuesEqual(expectedColumnValues, returnedColumnValues); 1457 1458 List<TColumnValue> columnValuesB = new ArrayList<>(1); 1459 TColumnValue columnValueB = 1460 new TColumnValue(wrap(familyAname), wrap(qualifierBname), wrap(valueBname)); 1461 columnValuesB.add(columnValueB); 1462 TPut putB = new TPut(wrap(rowName), columnValuesB); 1463 putB.setColumnValues(columnValuesB); 1464 1465 TDelete delete = new TDelete(wrap(rowName)); 1466 List<TColumn> deleteColumns = new ArrayList<>(1); 1467 TColumn deleteColumn = new TColumn(wrap(familyAname)); 1468 deleteColumn.setQualifier(qualifierAname); 1469 deleteColumns.add(deleteColumn); 1470 delete.setColumns(deleteColumns); 1471 1472 List<TMutation> mutations = new ArrayList<>(2); 1473 TMutation mutationA = TMutation.put(putB); 1474 mutations.add(mutationA); 1475 1476 TMutation mutationB = TMutation.deleteSingle(delete); 1477 mutations.add(mutationB); 1478 1479 TRowMutations tRowMutations = new TRowMutations(wrap(rowName), mutations); 1480 handler.mutateRow(table, tRowMutations); 1481 1482 result = handler.get(table, get); 1483 assertArrayEquals(rowName, result.getRow()); 1484 returnedColumnValues = result.getColumnValues(); 1485 1486 expectedColumnValues = new ArrayList<>(1); 1487 expectedColumnValues.add(columnValueB); 1488 assertTColumnValuesEqual(expectedColumnValues, returnedColumnValues); 1489 } 1490 1491 /** 1492 * Create TPut, TDelete , TIncrement objects, set durability then call ThriftUtility functions to 1493 * get Put , Delete and Increment respectively. Use getDurability to make sure the returned 1494 * objects have the appropriate durability setting. 1495 */ 1496 @Test 1497 public void testDurability() throws Exception { 1498 byte[] rowName = Bytes.toBytes("testDurability"); 1499 List<TColumnValue> columnValues = new ArrayList<>(1); 1500 columnValues.add(new TColumnValue(wrap(familyAname), wrap(qualifierAname), wrap(valueAname))); 1501 1502 List<TColumnIncrement> incrementColumns = new ArrayList<>(1); 1503 incrementColumns.add(new TColumnIncrement(wrap(familyAname), wrap(qualifierAname))); 1504 1505 TDelete tDelete = new TDelete(wrap(rowName)); 1506 tDelete.setDurability(TDurability.SKIP_WAL); 1507 Delete delete = deleteFromThrift(tDelete); 1508 assertEquals(Durability.SKIP_WAL, delete.getDurability()); 1509 1510 tDelete.setDurability(TDurability.ASYNC_WAL); 1511 delete = deleteFromThrift(tDelete); 1512 assertEquals(Durability.ASYNC_WAL, delete.getDurability()); 1513 1514 tDelete.setDurability(TDurability.SYNC_WAL); 1515 delete = deleteFromThrift(tDelete); 1516 assertEquals(Durability.SYNC_WAL, delete.getDurability()); 1517 1518 tDelete.setDurability(TDurability.FSYNC_WAL); 1519 delete = deleteFromThrift(tDelete); 1520 assertEquals(Durability.FSYNC_WAL, delete.getDurability()); 1521 1522 TPut tPut = new TPut(wrap(rowName), columnValues); 1523 tPut.setDurability(TDurability.SKIP_WAL); 1524 Put put = putFromThrift(tPut); 1525 assertEquals(Durability.SKIP_WAL, put.getDurability()); 1526 1527 tPut.setDurability(TDurability.ASYNC_WAL); 1528 put = putFromThrift(tPut); 1529 assertEquals(Durability.ASYNC_WAL, put.getDurability()); 1530 1531 tPut.setDurability(TDurability.SYNC_WAL); 1532 put = putFromThrift(tPut); 1533 assertEquals(Durability.SYNC_WAL, put.getDurability()); 1534 1535 tPut.setDurability(TDurability.FSYNC_WAL); 1536 put = putFromThrift(tPut); 1537 assertEquals(Durability.FSYNC_WAL, put.getDurability()); 1538 1539 TIncrement tIncrement = new TIncrement(wrap(rowName), incrementColumns); 1540 1541 tIncrement.setDurability(TDurability.SKIP_WAL); 1542 Increment increment = incrementFromThrift(tIncrement); 1543 assertEquals(Durability.SKIP_WAL, increment.getDurability()); 1544 1545 tIncrement.setDurability(TDurability.ASYNC_WAL); 1546 increment = incrementFromThrift(tIncrement); 1547 assertEquals(Durability.ASYNC_WAL, increment.getDurability()); 1548 1549 tIncrement.setDurability(TDurability.SYNC_WAL); 1550 increment = incrementFromThrift(tIncrement); 1551 assertEquals(Durability.SYNC_WAL, increment.getDurability()); 1552 1553 tIncrement.setDurability(TDurability.FSYNC_WAL); 1554 increment = incrementFromThrift(tIncrement); 1555 assertEquals(Durability.FSYNC_WAL, increment.getDurability()); 1556 } 1557 1558 @Test 1559 public void testCheckAndMutate() throws Exception { 1560 ThriftHBaseServiceHandler handler = createHandler(); 1561 ByteBuffer table = wrap(tableAname); 1562 ByteBuffer row = wrap(Bytes.toBytes("row")); 1563 ByteBuffer family = wrap(familyAname); 1564 ByteBuffer qualifier = wrap(qualifierAname); 1565 ByteBuffer value = wrap(valueAname); 1566 1567 // Create a mutation to write to 'B', our "mutate" of "checkAndMutate" 1568 List<TColumnValue> columnValuesB = new ArrayList<>(1); 1569 TColumnValue columnValueB = new TColumnValue(family, wrap(qualifierBname), wrap(valueBname)); 1570 columnValuesB.add(columnValueB); 1571 TPut putB = new TPut(row, columnValuesB); 1572 putB.setColumnValues(columnValuesB); 1573 1574 TRowMutations tRowMutations = 1575 new TRowMutations(row, Arrays.<TMutation> asList(TMutation.put(putB))); 1576 1577 // Empty table when we begin 1578 TResult result = handler.get(table, new TGet(row)); 1579 assertEquals(0, result.getColumnValuesSize()); 1580 1581 // checkAndMutate -- condition should fail because the value doesn't exist. 1582 assertFalse("Expected condition to not pass", handler.checkAndMutate(table, row, family, 1583 qualifier, TCompareOp.EQUAL, value, tRowMutations)); 1584 1585 List<TColumnValue> columnValuesA = new ArrayList<>(1); 1586 TColumnValue columnValueA = new TColumnValue(family, qualifier, value); 1587 columnValuesA.add(columnValueA); 1588 1589 // Put an update 'A' 1590 handler.put(table, new TPut(row, columnValuesA)); 1591 1592 // Verify that the update is there 1593 result = handler.get(table, new TGet(row)); 1594 assertEquals(1, result.getColumnValuesSize()); 1595 assertTColumnValueEqual(columnValueA, result.getColumnValues().get(0)); 1596 1597 // checkAndMutate -- condition should pass since we added the value 1598 assertTrue("Expected condition to pass", handler.checkAndMutate(table, row, family, qualifier, 1599 TCompareOp.EQUAL, value, tRowMutations)); 1600 1601 result = handler.get(table, new TGet(row)); 1602 assertEquals(2, result.getColumnValuesSize()); 1603 assertTColumnValueEqual(columnValueA, result.getColumnValues().get(0)); 1604 assertTColumnValueEqual(columnValueB, result.getColumnValues().get(1)); 1605 } 1606 1607 @Test 1608 public void testConsistency() throws Exception { 1609 byte[] rowName = Bytes.toBytes("testConsistency"); 1610 TGet tGet = new TGet(wrap(rowName)); 1611 tGet.setConsistency(TConsistency.STRONG); 1612 Get get = getFromThrift(tGet); 1613 assertEquals(Consistency.STRONG, get.getConsistency()); 1614 1615 tGet.setConsistency(TConsistency.TIMELINE); 1616 tGet.setTargetReplicaId(1); 1617 get = getFromThrift(tGet); 1618 assertEquals(Consistency.TIMELINE, get.getConsistency()); 1619 assertEquals(1, get.getReplicaId()); 1620 1621 TScan tScan = new TScan(); 1622 tScan.setConsistency(TConsistency.STRONG); 1623 Scan scan = scanFromThrift(tScan); 1624 assertEquals(Consistency.STRONG, scan.getConsistency()); 1625 1626 tScan.setConsistency(TConsistency.TIMELINE); 1627 tScan.setTargetReplicaId(1); 1628 scan = scanFromThrift(tScan); 1629 assertEquals(Consistency.TIMELINE, scan.getConsistency()); 1630 assertEquals(1, scan.getReplicaId()); 1631 1632 TResult tResult = new TResult(); 1633 assertFalse(tResult.isSetStale()); 1634 tResult.setStale(true); 1635 assertTrue(tResult.isSetStale()); 1636 } 1637 1638 @Test 1639 public void testDDLOpertions() throws Exception { 1640 String namespace = "testDDLOpertionsNamespace"; 1641 String table = "testDDLOpertionsTable"; 1642 TTableName tTableName = new TTableName(); 1643 tTableName.setNs(Bytes.toBytes(namespace)); 1644 tTableName.setQualifier(Bytes.toBytes(table)); 1645 ThriftHBaseServiceHandler handler = createHandler(); 1646 // create name space 1647 TNamespaceDescriptor namespaceDescriptor = new TNamespaceDescriptor(); 1648 namespaceDescriptor.setName(namespace); 1649 namespaceDescriptor.putToConfiguration("key1", "value1"); 1650 namespaceDescriptor.putToConfiguration("key2", "value2"); 1651 handler.createNamespace(namespaceDescriptor); 1652 // list namespace 1653 List<TNamespaceDescriptor> namespaceDescriptors = handler.listNamespaceDescriptors(); 1654 // should have 3 namespace, default hbase and testDDLOpertionsNamespace 1655 assertTrue(namespaceDescriptors.size() == 3); 1656 // modify namesapce 1657 namespaceDescriptor.putToConfiguration("kye3", "value3"); 1658 handler.modifyNamespace(namespaceDescriptor); 1659 // get namespace 1660 TNamespaceDescriptor namespaceDescriptorReturned = handler.getNamespaceDescriptor(namespace); 1661 assertTrue(namespaceDescriptorReturned.getConfiguration().size() == 3); 1662 // create table 1663 TTableDescriptor tableDescriptor = new TTableDescriptor(); 1664 tableDescriptor.setTableName(tTableName); 1665 TColumnFamilyDescriptor columnFamilyDescriptor1 = new TColumnFamilyDescriptor(); 1666 columnFamilyDescriptor1.setName(familyAname); 1667 columnFamilyDescriptor1.setDataBlockEncoding(TDataBlockEncoding.DIFF); 1668 tableDescriptor.addToColumns(columnFamilyDescriptor1); 1669 List<ByteBuffer> splitKeys = new ArrayList<>(); 1670 splitKeys.add(ByteBuffer.wrap(Bytes.toBytes(5))); 1671 handler.createTable(tableDescriptor, splitKeys); 1672 // modify table 1673 tableDescriptor.setDurability(TDurability.ASYNC_WAL); 1674 handler.modifyTable(tableDescriptor); 1675 // modify column family 1676 columnFamilyDescriptor1.setInMemory(true); 1677 handler.modifyColumnFamily(tTableName, columnFamilyDescriptor1); 1678 // add column family 1679 TColumnFamilyDescriptor columnFamilyDescriptor2 = new TColumnFamilyDescriptor(); 1680 columnFamilyDescriptor2.setName(familyBname); 1681 columnFamilyDescriptor2.setDataBlockEncoding(TDataBlockEncoding.PREFIX); 1682 handler.addColumnFamily(tTableName, columnFamilyDescriptor2); 1683 // get table descriptor 1684 TTableDescriptor tableDescriptorReturned = handler.getTableDescriptor(tTableName); 1685 assertTrue(tableDescriptorReturned.getColumns().size() == 2); 1686 assertTrue(tableDescriptorReturned.getDurability() == TDurability.ASYNC_WAL); 1687 TColumnFamilyDescriptor columnFamilyDescriptor1Returned = tableDescriptorReturned.getColumns() 1688 .stream().filter(desc -> Bytes.equals(desc.getName(), familyAname)).findFirst().get(); 1689 assertTrue(columnFamilyDescriptor1Returned.isInMemory() == true); 1690 // delete column family 1691 handler.deleteColumnFamily(tTableName, ByteBuffer.wrap(familyBname)); 1692 tableDescriptorReturned = handler.getTableDescriptor(tTableName); 1693 assertTrue(tableDescriptorReturned.getColumns().size() == 1); 1694 // disable table 1695 handler.disableTable(tTableName); 1696 assertTrue(handler.isTableDisabled(tTableName)); 1697 // enable table 1698 handler.enableTable(tTableName); 1699 assertTrue(handler.isTableEnabled(tTableName)); 1700 assertTrue(handler.isTableAvailable(tTableName)); 1701 // truncate table 1702 handler.disableTable(tTableName); 1703 handler.truncateTable(tTableName, true); 1704 assertTrue(handler.isTableAvailable(tTableName)); 1705 // delete table 1706 handler.disableTable(tTableName); 1707 handler.deleteTable(tTableName); 1708 assertFalse(handler.tableExists(tTableName)); 1709 // delete namespace 1710 handler.deleteNamespace(namespace); 1711 namespaceDescriptors = handler.listNamespaceDescriptors(); 1712 // should have 2 namespace, default and hbase 1713 assertTrue(namespaceDescriptors.size() == 2); 1714 } 1715 1716 @Test 1717 public void testGetTableDescriptor() throws Exception { 1718 ThriftHBaseServiceHandler handler = createHandler(); 1719 TTableDescriptor tableDescriptor = 1720 handler.getTableDescriptor(ThriftUtilities.tableNameFromHBase(TableName.valueOf(tableAname))); 1721 TableDescriptor table = ThriftUtilities.tableDescriptorFromThrift(tableDescriptor); 1722 assertTrue(table.getTableName().equals(TableName.valueOf(tableAname))); 1723 assertTrue(table.getColumnFamilies().length == 2); 1724 assertTrue(table.getColumnFamily(familyAname).getMaxVersions() == 3); 1725 assertTrue(table.getColumnFamily(familyBname).getMaxVersions() == 2); 1726 } 1727 1728 @Test 1729 public void testGetThriftServerType() throws Exception { 1730 ThriftHBaseServiceHandler handler = createHandler(); 1731 assertEquals(TThriftServerType.TWO, handler.getThriftServerType()); 1732 } 1733 1734 /** 1735 * Verify that thrift2 client calling thrift server can get the thrift server type correctly. 1736 */ 1737 @Test 1738 public void testGetThriftServerOneType() throws Exception { 1739 1740 // start a thrift server 1741 HBaseThriftTestingUtility THRIFT_TEST_UTIL = new HBaseThriftTestingUtility(); 1742 1743 LOG.info("Starting HBase Thrift server One"); 1744 THRIFT_TEST_UTIL.startThriftServer(UTIL.getConfiguration(), ThriftServerType.ONE); 1745 try (TTransport transport = 1746 new TSocket(InetAddress.getLocalHost().getHostName(), THRIFT_TEST_UTIL.getServerPort())) { 1747 TProtocol protocol = new TBinaryProtocol(transport); 1748 // This is our thrift2 client. 1749 THBaseService.Iface client = new THBaseService.Client(protocol); 1750 // open the transport 1751 transport.open(); 1752 assertEquals(TThriftServerType.ONE.name(), client.getThriftServerType().name()); 1753 } finally { 1754 THRIFT_TEST_UTIL.stopThriftServer(); 1755 } 1756 } 1757 1758 @Test 1759 public void testSlowLogResponses() throws Exception { 1760 1761 // start a thrift server 1762 HBaseThriftTestingUtility THRIFT_TEST_UTIL = new HBaseThriftTestingUtility(); 1763 Configuration configuration = UTIL.getConfiguration(); 1764 configuration.setBoolean("hbase.regionserver.slowlog.buffer.enabled", true); 1765 1766 THRIFT_TEST_UTIL.startThriftServer(configuration, ThriftServerType.ONE); 1767 ThriftHBaseServiceHandler thriftHBaseServiceHandler = 1768 new ThriftHBaseServiceHandler(configuration, UserProvider.instantiate(configuration)); 1769 Collection<ServerName> serverNames = UTIL.getAdmin().getRegionServers(); 1770 Set<TServerName> tServerNames = 1771 ThriftUtilities.getServerNamesFromHBase(new HashSet<>(serverNames)); 1772 List<Boolean> clearedResponses = thriftHBaseServiceHandler.clearSlowLogResponses(tServerNames); 1773 clearedResponses.forEach(Assert::assertTrue); 1774 TLogQueryFilter tLogQueryFilter = new TLogQueryFilter(); 1775 tLogQueryFilter.setLimit(15); 1776 Assert.assertEquals(tLogQueryFilter.getFilterByOperator(), TFilterByOperator.OR); 1777 LogQueryFilter logQueryFilter = ThriftUtilities.getSlowLogQueryFromThrift(tLogQueryFilter); 1778 Assert.assertEquals(logQueryFilter.getFilterByOperator(), LogQueryFilter.FilterByOperator.OR); 1779 tLogQueryFilter.setFilterByOperator(TFilterByOperator.AND); 1780 logQueryFilter = ThriftUtilities.getSlowLogQueryFromThrift(tLogQueryFilter); 1781 Assert.assertEquals(logQueryFilter.getFilterByOperator(), LogQueryFilter.FilterByOperator.AND); 1782 List<TOnlineLogRecord> tLogRecords = 1783 thriftHBaseServiceHandler.getSlowLogResponses(tServerNames, tLogQueryFilter); 1784 assertEquals(tLogRecords.size(), 0); 1785 } 1786 1787 public static class DelayingRegionObserver implements RegionCoprocessor, RegionObserver { 1788 private static final Logger LOG = LoggerFactory.getLogger(DelayingRegionObserver.class); 1789 // sleep time in msec 1790 private long delayMillis; 1791 1792 @Override 1793 public Optional<RegionObserver> getRegionObserver() { 1794 return Optional.of(this); 1795 } 1796 1797 @Override 1798 public void start(CoprocessorEnvironment e) throws IOException { 1799 this.delayMillis = e.getConfiguration().getLong("delayingregionobserver.delay", 3000); 1800 } 1801 1802 @Override 1803 public void preGetOp(ObserverContext<RegionCoprocessorEnvironment> e, Get get, 1804 List<Cell> results) throws IOException { 1805 try { 1806 long start = EnvironmentEdgeManager.currentTime(); 1807 TimeUnit.MILLISECONDS.sleep(delayMillis); 1808 if (LOG.isTraceEnabled()) { 1809 LOG.trace("Slept for " + (EnvironmentEdgeManager.currentTime() - start) + " msec"); 1810 } 1811 } catch (InterruptedException ie) { 1812 throw new InterruptedIOException("Interrupted while sleeping"); 1813 } 1814 } 1815 } 1816}