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