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