2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
18 package org
.apache
.hadoop
.hbase
.client
;
20 import static org
.apache
.hadoop
.hbase
.HConstants
.RPC_CODEC_CONF_KEY
;
21 import static org
.apache
.hadoop
.hbase
.client
.TestFromClientSide3
.generateHugeValue
;
22 import static org
.apache
.hadoop
.hbase
.ipc
.RpcClient
.DEFAULT_CODEC_CLASS
;
23 import static org
.hamcrest
.CoreMatchers
.instanceOf
;
24 import static org
.junit
.Assert
.assertArrayEquals
;
25 import static org
.junit
.Assert
.assertEquals
;
26 import static org
.junit
.Assert
.assertFalse
;
27 import static org
.junit
.Assert
.assertNotNull
;
28 import static org
.junit
.Assert
.assertNull
;
29 import static org
.junit
.Assert
.assertThat
;
30 import static org
.junit
.Assert
.assertTrue
;
31 import static org
.junit
.Assert
.fail
;
32 import java
.io
.IOException
;
33 import java
.util
.ArrayList
;
34 import java
.util
.Arrays
;
35 import java
.util
.Collection
;
36 import java
.util
.List
;
37 import org
.apache
.hadoop
.conf
.Configuration
;
38 import org
.apache
.hadoop
.hbase
.Cell
;
39 import org
.apache
.hadoop
.hbase
.CompareOperator
;
40 import org
.apache
.hadoop
.hbase
.HBaseClassTestRule
;
41 import org
.apache
.hadoop
.hbase
.HBaseTestingUtility
;
42 import org
.apache
.hadoop
.hbase
.HConstants
;
43 import org
.apache
.hadoop
.hbase
.HRegionLocation
;
44 import org
.apache
.hadoop
.hbase
.HTestConst
;
45 import org
.apache
.hadoop
.hbase
.KeyValue
;
46 import org
.apache
.hadoop
.hbase
.MiniHBaseCluster
;
47 import org
.apache
.hadoop
.hbase
.StartMiniClusterOption
;
48 import org
.apache
.hadoop
.hbase
.TableName
;
49 import org
.apache
.hadoop
.hbase
.TableNameTestRule
;
50 import org
.apache
.hadoop
.hbase
.TableNotFoundException
;
51 import org
.apache
.hadoop
.hbase
.exceptions
.DeserializationException
;
52 import org
.apache
.hadoop
.hbase
.filter
.BinaryComparator
;
53 import org
.apache
.hadoop
.hbase
.filter
.ColumnPrefixFilter
;
54 import org
.apache
.hadoop
.hbase
.filter
.ColumnRangeFilter
;
55 import org
.apache
.hadoop
.hbase
.filter
.FilterBase
;
56 import org
.apache
.hadoop
.hbase
.filter
.QualifierFilter
;
57 import org
.apache
.hadoop
.hbase
.regionserver
.HRegionServer
;
58 import org
.apache
.hadoop
.hbase
.testclassification
.ClientTests
;
59 import org
.apache
.hadoop
.hbase
.testclassification
.MediumTests
;
60 import org
.apache
.hadoop
.hbase
.util
.Bytes
;
61 import org
.apache
.hadoop
.hbase
.util
.EnvironmentEdgeManager
;
62 import org
.junit
.AfterClass
;
63 import org
.junit
.ClassRule
;
64 import org
.junit
.Rule
;
65 import org
.junit
.Test
;
66 import org
.junit
.experimental
.categories
.Category
;
67 import org
.junit
.runner
.RunWith
;
68 import org
.junit
.runners
.Parameterized
;
69 import org
.slf4j
.Logger
;
70 import org
.slf4j
.LoggerFactory
;
71 import org
.apache
.hbase
.thirdparty
.com
.google
.common
.base
.Preconditions
;
74 * A client-side test, mostly testing scanners with various parameters. Parameterized on different
75 * registry implementations.
77 @Category({MediumTests
.class, ClientTests
.class})
78 @RunWith(Parameterized
.class)
79 public class TestScannersFromClientSide
{
82 public static final HBaseClassTestRule CLASS_RULE
=
83 HBaseClassTestRule
.forClass(TestScannersFromClientSide
.class);
85 private static final Logger LOG
= LoggerFactory
.getLogger(TestScannersFromClientSide
.class);
87 private static HBaseTestingUtility TEST_UTIL
;
88 private static byte [] ROW
= Bytes
.toBytes("testRow");
89 private static byte [] FAMILY
= Bytes
.toBytes("testFamily");
90 private static byte [] QUALIFIER
= Bytes
.toBytes("testQualifier");
91 private static byte [] VALUE
= Bytes
.toBytes("testValue");
94 public TableNameTestRule name
= new TableNameTestRule();
97 public static void tearDownAfterClass() throws Exception
{
98 if (TEST_UTIL
!= null) {
99 TEST_UTIL
.shutdownMiniCluster();
103 @Parameterized.Parameters
104 public static Collection
parameters() {
105 return Arrays
.asList(new Object
[][] {
106 { MasterRegistry
.class, 1},
107 { MasterRegistry
.class, 2},
108 { ZKConnectionRegistry
.class, 1}
113 * JUnit does not provide an easy way to run a hook after each parameterized run. Without that
114 * there is no easy way to restart the test cluster after each parameterized run. Annotation
115 * BeforeParam does not work either because it runs before parameterization and hence does not
116 * have access to the test parameters (which is weird).
118 * This *hack* checks if the current instance of test cluster configuration has the passed
119 * parameterized configs. In such a case, we can just reuse the cluster for test and do not need
120 * to initialize from scratch. While this is a hack, it saves a ton of time for the full
121 * test and de-flakes it.
123 private static boolean isSameParameterizedCluster(Class registryImpl
, int numHedgedReqs
) {
124 // initialize() is called for every unit test, however we only want to reset the cluster state
125 // at the end of every parameterized run.
126 if (TEST_UTIL
== null) {
129 Configuration conf
= TEST_UTIL
.getConfiguration();
130 Class confClass
= conf
.getClass(
131 HConstants
.CLIENT_CONNECTION_REGISTRY_IMPL_CONF_KEY
, ZKConnectionRegistry
.class);
132 int hedgedReqConfig
= conf
.getInt(HConstants
.HBASE_RPCS_HEDGED_REQS_FANOUT_KEY
,
133 HConstants
.HBASE_RPCS_HEDGED_REQS_FANOUT_DEFAULT
);
134 return confClass
.getName().equals(registryImpl
.getName()) && numHedgedReqs
== hedgedReqConfig
;
137 public TestScannersFromClientSide(Class registryImpl
, int numHedgedReqs
) throws Exception
{
138 if (isSameParameterizedCluster(registryImpl
, numHedgedReqs
)) {
141 if (TEST_UTIL
!= null) {
142 // We reached the end of a parameterized run, clean up the cluster.
143 TEST_UTIL
.shutdownMiniCluster();
145 TEST_UTIL
= new HBaseTestingUtility();
146 Configuration conf
= TEST_UTIL
.getConfiguration();
147 conf
.setLong(HConstants
.HBASE_CLIENT_SCANNER_MAX_RESULT_SIZE_KEY
, 10 * 1024 * 1024);
148 conf
.setClass(HConstants
.CLIENT_CONNECTION_REGISTRY_IMPL_CONF_KEY
, registryImpl
,
149 ConnectionRegistry
.class);
150 if (numHedgedReqs
== 1) {
151 conf
.setBoolean(HConstants
.MASTER_REGISTRY_ENABLE_HEDGED_READS_KEY
, false);
153 Preconditions
.checkArgument(numHedgedReqs
> 1);
154 conf
.setBoolean(HConstants
.MASTER_REGISTRY_ENABLE_HEDGED_READS_KEY
, true);
156 conf
.setInt(HConstants
.HBASE_RPCS_HEDGED_REQS_FANOUT_KEY
, numHedgedReqs
);
157 StartMiniClusterOption
.Builder builder
= StartMiniClusterOption
.builder();
158 // Multiple masters needed only when hedged reads for master registry are enabled.
159 builder
.numMasters(numHedgedReqs
> 1 ?
3 : 1).numRegionServers(3);
160 TEST_UTIL
.startMiniCluster(builder
.build());
164 * Test from client side for batch of scan
167 public void testScanBatch() throws Exception
{
168 final TableName tableName
= name
.getTableName();
169 byte [][] QUALIFIERS
= HTestConst
.makeNAscii(QUALIFIER
, 8);
171 Table ht
= TEST_UTIL
.createTable(tableName
, FAMILY
);
177 ResultScanner scanner
;
178 boolean toLog
= true;
179 List
<Cell
> kvListExp
;
181 // table: row, family, c0:0, c1:1, ... , c7:7
183 for (int i
=0; i
< QUALIFIERS
.length
; i
++) {
184 KeyValue kv
= new KeyValue(ROW
, FAMILY
, QUALIFIERS
[i
], i
, VALUE
);
189 // table: row, family, c0:0, c1:1, ..., c6:2, c6:6 , c7:7
191 KeyValue kv
= new KeyValue(ROW
, FAMILY
, QUALIFIERS
[6], 2, VALUE
);
196 delete
= new Delete(ROW
);
197 delete
.addFamily(FAMILY
, 3);
201 scan
= new Scan().withStartRow(ROW
);
202 scan
.readAllVersions();
203 scanner
= ht
.getScanner(scan
);
205 // c4:4, c5:5, c6:6, c7:7
206 kvListExp
= new ArrayList
<>();
207 kvListExp
.add(new KeyValue(ROW
, FAMILY
, QUALIFIERS
[4], 4, VALUE
));
208 kvListExp
.add(new KeyValue(ROW
, FAMILY
, QUALIFIERS
[5], 5, VALUE
));
209 kvListExp
.add(new KeyValue(ROW
, FAMILY
, QUALIFIERS
[6], 6, VALUE
));
210 kvListExp
.add(new KeyValue(ROW
, FAMILY
, QUALIFIERS
[7], 7, VALUE
));
211 result
= scanner
.next();
212 verifyResult(result
, kvListExp
, toLog
, "Testing first batch of scan");
215 scan
= new Scan().withStartRow(ROW
);
216 scan
.readAllVersions();
218 scanner
= ht
.getScanner(scan
);
220 // First batch: c4:4, c5:5
221 kvListExp
= new ArrayList
<>();
222 kvListExp
.add(new KeyValue(ROW
, FAMILY
, QUALIFIERS
[4], 4, VALUE
));
223 kvListExp
.add(new KeyValue(ROW
, FAMILY
, QUALIFIERS
[5], 5, VALUE
));
224 result
= scanner
.next();
225 verifyResult(result
, kvListExp
, toLog
, "Testing first batch of scan");
227 // Second batch: c6:6, c7:7
228 kvListExp
= new ArrayList
<>();
229 kvListExp
.add(new KeyValue(ROW
, FAMILY
, QUALIFIERS
[6], 6, VALUE
));
230 kvListExp
.add(new KeyValue(ROW
, FAMILY
, QUALIFIERS
[7], 7, VALUE
));
231 result
= scanner
.next();
232 verifyResult(result
, kvListExp
, toLog
, "Testing second batch of scan");
237 public void testMaxResultSizeIsSetToDefault() throws Exception
{
238 final TableName tableName
= name
.getTableName();
239 Table ht
= TEST_UTIL
.createTable(tableName
, FAMILY
);
241 // The max result size we expect the scan to use by default.
242 long expectedMaxResultSize
=
243 TEST_UTIL
.getConfiguration().getLong(HConstants
.HBASE_CLIENT_SCANNER_MAX_RESULT_SIZE_KEY
,
244 HConstants
.DEFAULT_HBASE_CLIENT_SCANNER_MAX_RESULT_SIZE
);
247 byte[][] ROWS
= HTestConst
.makeNAscii(ROW
, numRows
);
249 int numQualifiers
= 10;
250 byte[][] QUALIFIERS
= HTestConst
.makeNAscii(QUALIFIER
, numQualifiers
);
252 // Specify the cell size such that a single row will be larger than the default
253 // value of maxResultSize. This means that Scan RPCs should return at most a single
254 // result back to the client.
255 int cellSize
= (int) (expectedMaxResultSize
/ (numQualifiers
- 1));
256 byte[] cellValue
= Bytes
.createMaxByteArray(cellSize
);
259 List
<Put
> puts
= new ArrayList
<>();
260 for (int row
= 0; row
< ROWS
.length
; row
++) {
261 put
= new Put(ROWS
[row
]);
262 for (int qual
= 0; qual
< QUALIFIERS
.length
; qual
++) {
263 KeyValue kv
= new KeyValue(ROWS
[row
], FAMILY
, QUALIFIERS
[qual
], cellValue
);
270 // Create a scan with the default configuration.
271 Scan scan
= new Scan();
273 try (ResultScanner scanner
= ht
.getScanner(scan
)) {
274 assertThat(scanner
, instanceOf(AsyncTableResultScanner
.class));
276 AsyncTableResultScanner s
= (AsyncTableResultScanner
) scanner
;
277 // The scanner should have, at most, a single result in its cache. If there more results
279 // in the cache it means that more than the expected max result size was fetched.
280 assertTrue("The cache contains: " + s
.getCacheSize() + " results", s
.getCacheSize() <= 1);
285 * Scan on not existing table should throw the exception with correct message
288 public void testScannerForNotExistingTable() {
289 String
[] tableNames
= {"A", "Z", "A:A", "Z:Z"};
290 for(String tableName
: tableNames
) {
292 Table table
= TEST_UTIL
.getConnection().getTable(TableName
.valueOf(tableName
));
293 testSmallScan(table
, true, 1, 5);
294 fail("TableNotFoundException was not thrown");
295 } catch (TableNotFoundException e
) {
296 // We expect that the message for TableNotFoundException would have only the table name only
297 // Otherwise that would mean that localeRegionInMeta doesn't work properly
298 assertEquals(e
.getMessage(), tableName
);
299 } catch (Exception e
) {
300 fail("Unexpected exception " + e
.getMessage());
306 public void testSmallScan() throws Exception
{
307 final TableName tableName
= name
.getTableName();
310 byte[][] ROWS
= HTestConst
.makeNAscii(ROW
, numRows
);
312 int numQualifiers
= 10;
313 byte[][] QUALIFIERS
= HTestConst
.makeNAscii(QUALIFIER
, numQualifiers
);
315 Table ht
= TEST_UTIL
.createTable(tableName
, FAMILY
);
318 List
<Put
> puts
= new ArrayList
<>();
319 for (int row
= 0; row
< ROWS
.length
; row
++) {
320 put
= new Put(ROWS
[row
]);
321 for (int qual
= 0; qual
< QUALIFIERS
.length
; qual
++) {
322 KeyValue kv
= new KeyValue(ROWS
[row
], FAMILY
, QUALIFIERS
[qual
], VALUE
);
329 int expectedRows
= numRows
;
330 int expectedCols
= numRows
* numQualifiers
;
332 // Test normal and reversed
333 testSmallScan(ht
, true, expectedRows
, expectedCols
);
334 testSmallScan(ht
, false, expectedRows
, expectedCols
);
338 * Run through a variety of test configurations with a small scan
340 private void testSmallScan(
341 Table table
, boolean reversed
, int rows
, int columns
) throws Exception
{
342 Scan baseScan
= new Scan();
343 baseScan
.setReversed(reversed
);
344 baseScan
.setSmall(true);
346 Scan scan
= new Scan(baseScan
);
347 verifyExpectedCounts(table
, scan
, rows
, columns
);
349 scan
= new Scan(baseScan
);
350 scan
.setMaxResultSize(1);
351 verifyExpectedCounts(table
, scan
, rows
, columns
);
353 scan
= new Scan(baseScan
);
354 scan
.setMaxResultSize(1);
355 scan
.setCaching(Integer
.MAX_VALUE
);
356 verifyExpectedCounts(table
, scan
, rows
, columns
);
359 private void verifyExpectedCounts(Table table
, Scan scan
, int expectedRowCount
,
360 int expectedCellCount
) throws Exception
{
361 ResultScanner scanner
= table
.getScanner(scan
);
366 while ((r
= scanner
.next()) != null) {
368 cellCount
+= r
.rawCells().length
;
371 assertTrue("Expected row count: " + expectedRowCount
+ " Actual row count: " + rowCount
,
372 expectedRowCount
== rowCount
);
373 assertTrue("Expected cell count: " + expectedCellCount
+ " Actual cell count: " + cellCount
,
374 expectedCellCount
== cellCount
);
379 * Test from client side for get with maxResultPerCF set
382 public void testGetMaxResults() throws Exception
{
383 final TableName tableName
= name
.getTableName();
384 byte [][] FAMILIES
= HTestConst
.makeNAscii(FAMILY
, 3);
385 byte [][] QUALIFIERS
= HTestConst
.makeNAscii(QUALIFIER
, 20);
387 Table ht
= TEST_UTIL
.createTable(tableName
, FAMILIES
);
392 boolean toLog
= true;
393 List
<Cell
> kvListExp
;
395 kvListExp
= new ArrayList
<>();
396 // Insert one CF for row[0]
398 for (int i
=0; i
< 10; i
++) {
399 KeyValue kv
= new KeyValue(ROW
, FAMILIES
[0], QUALIFIERS
[i
], 1, VALUE
);
406 result
= ht
.get(get
);
407 verifyResult(result
, kvListExp
, toLog
, "Testing without setting maxResults");
410 get
.setMaxResultsPerColumnFamily(2);
411 result
= ht
.get(get
);
412 kvListExp
= new ArrayList
<>();
413 kvListExp
.add(new KeyValue(ROW
, FAMILIES
[0], QUALIFIERS
[0], 1, VALUE
));
414 kvListExp
.add(new KeyValue(ROW
, FAMILIES
[0], QUALIFIERS
[1], 1, VALUE
));
415 verifyResult(result
, kvListExp
, toLog
, "Testing basic setMaxResults");
417 // Filters: ColumnRangeFilter
419 get
.setMaxResultsPerColumnFamily(5);
420 get
.setFilter(new ColumnRangeFilter(QUALIFIERS
[2], true, QUALIFIERS
[5],
422 result
= ht
.get(get
);
423 kvListExp
= new ArrayList
<>();
424 kvListExp
.add(new KeyValue(ROW
, FAMILIES
[0], QUALIFIERS
[2], 1, VALUE
));
425 kvListExp
.add(new KeyValue(ROW
, FAMILIES
[0], QUALIFIERS
[3], 1, VALUE
));
426 kvListExp
.add(new KeyValue(ROW
, FAMILIES
[0], QUALIFIERS
[4], 1, VALUE
));
427 kvListExp
.add(new KeyValue(ROW
, FAMILIES
[0], QUALIFIERS
[5], 1, VALUE
));
428 verifyResult(result
, kvListExp
, toLog
, "Testing single CF with CRF");
430 // Insert two more CF for row[0]
431 // 20 columns for CF2, 10 columns for CF1
433 for (int i
=0; i
< QUALIFIERS
.length
; i
++) {
434 KeyValue kv
= new KeyValue(ROW
, FAMILIES
[2], QUALIFIERS
[i
], 1, VALUE
);
440 for (int i
=0; i
< 10; i
++) {
441 KeyValue kv
= new KeyValue(ROW
, FAMILIES
[1], QUALIFIERS
[i
], 1, VALUE
);
447 get
.setMaxResultsPerColumnFamily(12);
448 get
.addFamily(FAMILIES
[1]);
449 get
.addFamily(FAMILIES
[2]);
450 result
= ht
.get(get
);
451 kvListExp
= new ArrayList
<>();
452 //Exp: CF1:q0, ..., q9, CF2: q0, q1, q10, q11, ..., q19
453 for (int i
=0; i
< 10; i
++) {
454 kvListExp
.add(new KeyValue(ROW
, FAMILIES
[1], QUALIFIERS
[i
], 1, VALUE
));
456 for (int i
=0; i
< 2; i
++) {
457 kvListExp
.add(new KeyValue(ROW
, FAMILIES
[2], QUALIFIERS
[i
], 1, VALUE
));
459 for (int i
=10; i
< 20; i
++) {
460 kvListExp
.add(new KeyValue(ROW
, FAMILIES
[2], QUALIFIERS
[i
], 1, VALUE
));
462 verifyResult(result
, kvListExp
, toLog
, "Testing multiple CFs");
464 // Filters: ColumnRangeFilter and ColumnPrefixFilter
466 get
.setMaxResultsPerColumnFamily(3);
467 get
.setFilter(new ColumnRangeFilter(QUALIFIERS
[2], true, null, true));
468 result
= ht
.get(get
);
469 kvListExp
= new ArrayList
<>();
470 for (int i
=2; i
< 5; i
++) {
471 kvListExp
.add(new KeyValue(ROW
, FAMILIES
[0], QUALIFIERS
[i
], 1, VALUE
));
473 for (int i
=2; i
< 5; i
++) {
474 kvListExp
.add(new KeyValue(ROW
, FAMILIES
[1], QUALIFIERS
[i
], 1, VALUE
));
476 for (int i
=2; i
< 5; i
++) {
477 kvListExp
.add(new KeyValue(ROW
, FAMILIES
[2], QUALIFIERS
[i
], 1, VALUE
));
479 verifyResult(result
, kvListExp
, toLog
, "Testing multiple CFs + CRF");
482 get
.setMaxResultsPerColumnFamily(7);
483 get
.setFilter(new ColumnPrefixFilter(QUALIFIERS
[1]));
484 result
= ht
.get(get
);
485 kvListExp
= new ArrayList
<>();
486 kvListExp
.add(new KeyValue(ROW
, FAMILIES
[0], QUALIFIERS
[1], 1, VALUE
));
487 kvListExp
.add(new KeyValue(ROW
, FAMILIES
[1], QUALIFIERS
[1], 1, VALUE
));
488 kvListExp
.add(new KeyValue(ROW
, FAMILIES
[2], QUALIFIERS
[1], 1, VALUE
));
489 for (int i
=10; i
< 16; i
++) {
490 kvListExp
.add(new KeyValue(ROW
, FAMILIES
[2], QUALIFIERS
[i
], 1, VALUE
));
492 verifyResult(result
, kvListExp
, toLog
, "Testing multiple CFs + PFF");
497 * Test from client side for scan with maxResultPerCF set
500 public void testScanMaxResults() throws Exception
{
501 final TableName tableName
= name
.getTableName();
502 byte [][] ROWS
= HTestConst
.makeNAscii(ROW
, 2);
503 byte [][] FAMILIES
= HTestConst
.makeNAscii(FAMILY
, 3);
504 byte [][] QUALIFIERS
= HTestConst
.makeNAscii(QUALIFIER
, 10);
506 Table ht
= TEST_UTIL
.createTable(tableName
, FAMILIES
);
511 boolean toLog
= true;
512 List
<Cell
> kvListExp
, kvListScan
;
514 kvListExp
= new ArrayList
<>();
516 for (int r
=0; r
< ROWS
.length
; r
++) {
517 put
= new Put(ROWS
[r
]);
518 for (int c
=0; c
< FAMILIES
.length
; c
++) {
519 for (int q
=0; q
< QUALIFIERS
.length
; q
++) {
520 KeyValue kv
= new KeyValue(ROWS
[r
], FAMILIES
[c
], QUALIFIERS
[q
], 1, VALUE
);
531 scan
.setMaxResultsPerColumnFamily(4);
532 ResultScanner scanner
= ht
.getScanner(scan
);
533 kvListScan
= new ArrayList
<>();
534 while ((result
= scanner
.next()) != null) {
535 for (Cell kv
: result
.listCells()) {
539 result
= Result
.create(kvListScan
);
540 verifyResult(result
, kvListExp
, toLog
, "Testing scan with maxResults");
545 * Test from client side for get with rowOffset
548 public void testGetRowOffset() throws Exception
{
549 final TableName tableName
= name
.getTableName();
550 byte [][] FAMILIES
= HTestConst
.makeNAscii(FAMILY
, 3);
551 byte [][] QUALIFIERS
= HTestConst
.makeNAscii(QUALIFIER
, 20);
553 Table ht
= TEST_UTIL
.createTable(tableName
, FAMILIES
);
558 boolean toLog
= true;
559 List
<Cell
> kvListExp
;
561 // Insert one CF for row
562 kvListExp
= new ArrayList
<>();
564 for (int i
=0; i
< 10; i
++) {
565 KeyValue kv
= new KeyValue(ROW
, FAMILIES
[0], QUALIFIERS
[i
], 1, VALUE
);
567 // skipping first two kvs
575 //setting offset to 2
577 get
.setRowOffsetPerColumnFamily(2);
578 result
= ht
.get(get
);
579 verifyResult(result
, kvListExp
, toLog
, "Testing basic setRowOffset");
581 //setting offset to 20
583 get
.setRowOffsetPerColumnFamily(20);
584 result
= ht
.get(get
);
585 kvListExp
= new ArrayList
<>();
586 verifyResult(result
, kvListExp
, toLog
, "Testing offset > #kvs");
588 //offset + maxResultPerCF
590 get
.setRowOffsetPerColumnFamily(4);
591 get
.setMaxResultsPerColumnFamily(5);
592 result
= ht
.get(get
);
593 kvListExp
= new ArrayList
<>();
594 for (int i
=4; i
< 9; i
++) {
595 kvListExp
.add(new KeyValue(ROW
, FAMILIES
[0], QUALIFIERS
[i
], 1, VALUE
));
597 verifyResult(result
, kvListExp
, toLog
,
598 "Testing offset + setMaxResultsPerCF");
600 // Filters: ColumnRangeFilter
602 get
.setRowOffsetPerColumnFamily(1);
603 get
.setFilter(new ColumnRangeFilter(QUALIFIERS
[2], true, QUALIFIERS
[5],
605 result
= ht
.get(get
);
606 kvListExp
= new ArrayList
<>();
607 kvListExp
.add(new KeyValue(ROW
, FAMILIES
[0], QUALIFIERS
[3], 1, VALUE
));
608 kvListExp
.add(new KeyValue(ROW
, FAMILIES
[0], QUALIFIERS
[4], 1, VALUE
));
609 kvListExp
.add(new KeyValue(ROW
, FAMILIES
[0], QUALIFIERS
[5], 1, VALUE
));
610 verifyResult(result
, kvListExp
, toLog
, "Testing offset with CRF");
612 // Insert into two more CFs for row
613 // 10 columns for CF2, 10 columns for CF1
614 for(int j
=2; j
> 0; j
--) {
616 for (int i
=0; i
< 10; i
++) {
617 KeyValue kv
= new KeyValue(ROW
, FAMILIES
[j
], QUALIFIERS
[i
], 1, VALUE
);
624 get
.setRowOffsetPerColumnFamily(4);
625 get
.setMaxResultsPerColumnFamily(2);
626 get
.addFamily(FAMILIES
[1]);
627 get
.addFamily(FAMILIES
[2]);
628 result
= ht
.get(get
);
629 kvListExp
= new ArrayList
<>();
630 //Exp: CF1:q4, q5, CF2: q4, q5
631 kvListExp
.add(new KeyValue(ROW
, FAMILIES
[1], QUALIFIERS
[4], 1, VALUE
));
632 kvListExp
.add(new KeyValue(ROW
, FAMILIES
[1], QUALIFIERS
[5], 1, VALUE
));
633 kvListExp
.add(new KeyValue(ROW
, FAMILIES
[2], QUALIFIERS
[4], 1, VALUE
));
634 kvListExp
.add(new KeyValue(ROW
, FAMILIES
[2], QUALIFIERS
[5], 1, VALUE
));
635 verifyResult(result
, kvListExp
, toLog
,
636 "Testing offset + multiple CFs + maxResults");
640 public void testScanRawDeleteFamilyVersion() throws Exception
{
641 TableName tableName
= name
.getTableName();
642 TEST_UTIL
.createTable(tableName
, FAMILY
);
643 Configuration conf
= new Configuration(TEST_UTIL
.getConfiguration());
644 conf
.set(RPC_CODEC_CONF_KEY
, "");
645 conf
.set(DEFAULT_CODEC_CLASS
, "");
646 try (Connection connection
= ConnectionFactory
.createConnection(conf
);
647 Table table
= connection
.getTable(tableName
)) {
648 Delete delete
= new Delete(ROW
);
649 delete
.addFamilyVersion(FAMILY
, 0L);
650 table
.delete(delete
);
651 Scan scan
= new Scan().withStartRow(ROW
).setRaw(true);
652 ResultScanner scanner
= table
.getScanner(scan
);
654 while (scanner
.next() != null) {
657 assertEquals(1, count
);
659 TEST_UTIL
.deleteTable(tableName
);
664 * Test from client side for scan while the region is reopened
665 * on the same region server.
668 public void testScanOnReopenedRegion() throws Exception
{
669 final TableName tableName
= name
.getTableName();
670 byte [][] QUALIFIERS
= HTestConst
.makeNAscii(QUALIFIER
, 2);
672 Table ht
= TEST_UTIL
.createTable(tableName
, FAMILY
);
677 ResultScanner scanner
;
678 boolean toLog
= false;
679 List
<Cell
> kvListExp
;
681 // table: row, family, c0:0, c1:1
683 for (int i
=0; i
< QUALIFIERS
.length
; i
++) {
684 KeyValue kv
= new KeyValue(ROW
, FAMILY
, QUALIFIERS
[i
], i
, VALUE
);
689 scan
= new Scan().withStartRow(ROW
);
690 scanner
= ht
.getScanner(scan
);
694 try (RegionLocator locator
= TEST_UTIL
.getConnection().getRegionLocator(tableName
)) {
695 loc
= locator
.getRegionLocation(ROW
);
697 RegionInfo hri
= loc
.getRegion();
698 MiniHBaseCluster cluster
= TEST_UTIL
.getMiniHBaseCluster();
699 byte[] regionName
= hri
.getRegionName();
700 int i
= cluster
.getServerWith(regionName
);
701 HRegionServer rs
= cluster
.getRegionServer(i
);
702 LOG
.info("Unassigning " + hri
);
703 TEST_UTIL
.getAdmin().unassign(hri
.getRegionName(), true);
704 long startTime
= EnvironmentEdgeManager
.currentTime();
705 long timeOut
= 10000;
706 boolean offline
= false;
708 if (rs
.getOnlineRegion(regionName
) == null) {
712 assertTrue("Timed out in closing the testing region",
713 EnvironmentEdgeManager
.currentTime() < startTime
+ timeOut
);
716 LOG
.info("Assigning " + hri
);
717 TEST_UTIL
.getAdmin().assign(hri
.getRegionName());
718 startTime
= EnvironmentEdgeManager
.currentTime();
720 rs
= cluster
.getRegionServer(cluster
.getServerWith(regionName
));
721 if (rs
!= null && rs
.getOnlineRegion(regionName
) != null) {
725 assertTrue("Timed out in open the testing region",
726 EnvironmentEdgeManager
.currentTime() < startTime
+ timeOut
);
728 assertFalse(offline
);
731 kvListExp
= new ArrayList
<>();
732 kvListExp
.add(new KeyValue(ROW
, FAMILY
, QUALIFIERS
[0], 0, VALUE
));
733 kvListExp
.add(new KeyValue(ROW
, FAMILY
, QUALIFIERS
[1], 1, VALUE
));
734 result
= scanner
.next();
735 verifyResult(result
, kvListExp
, toLog
, "Testing scan on re-opened region");
738 static void verifyResult(Result result
, List
<Cell
> expKvList
, boolean toLog
,
742 LOG
.info("Expected count: " + expKvList
.size());
743 LOG
.info("Actual count: " + result
.size());
744 if (expKvList
.isEmpty()) {
749 for (Cell kv
: result
.rawCells()) {
750 if (i
>= expKvList
.size()) {
751 break; // we will check the size later
754 Cell kvExp
= expKvList
.get(i
++);
756 LOG
.info("get kv is: " + kv
.toString());
757 LOG
.info("exp kv is: " + kvExp
.toString());
759 assertTrue("Not equal", kvExp
.equals(kv
));
762 assertEquals(expKvList
.size(), result
.size());
766 public void testReadExpiredDataForRawScan() throws IOException
{
767 TableName tableName
= name
.getTableName();
768 long ts
= System
.currentTimeMillis() - 10000;
769 byte[] value
= Bytes
.toBytes("expired");
770 try (Table table
= TEST_UTIL
.createTable(tableName
, FAMILY
)) {
771 table
.put(new Put(ROW
).addColumn(FAMILY
, QUALIFIER
, ts
, value
));
772 assertArrayEquals(value
, table
.get(new Get(ROW
)).getValue(FAMILY
, QUALIFIER
));
773 TEST_UTIL
.getAdmin().modifyColumnFamily(tableName
,
774 new ColumnFamilyDescriptorBuilder
.ModifyableColumnFamilyDescriptor(FAMILY
)
776 try (ResultScanner scanner
= table
.getScanner(FAMILY
)) {
777 assertNull(scanner
.next());
779 try (ResultScanner scanner
= table
.getScanner(new Scan().setRaw(true))) {
780 assertArrayEquals(value
, scanner
.next().getValue(FAMILY
, QUALIFIER
));
781 assertNull(scanner
.next());
787 public void testScanWithColumnsAndFilterAndVersion() throws IOException
{
788 TableName tableName
= name
.getTableName();
789 long now
= System
.currentTimeMillis();
790 try (Table table
= TEST_UTIL
.createTable(tableName
, FAMILY
, 4)) {
791 for (int i
= 0; i
< 4; i
++) {
792 Put put
= new Put(ROW
);
793 put
.addColumn(FAMILY
, QUALIFIER
, now
+ i
, VALUE
);
797 Scan scan
= new Scan();
798 scan
.addColumn(FAMILY
, QUALIFIER
);
799 scan
.setFilter(new QualifierFilter(CompareOperator
.EQUAL
, new BinaryComparator(QUALIFIER
)));
800 scan
.readVersions(3);
802 try (ResultScanner scanner
= table
.getScanner(scan
)) {
803 Result result
= scanner
.next();
804 assertEquals(3, result
.size());
810 public void testScanWithSameStartRowStopRow() throws IOException
{
811 TableName tableName
= name
.getTableName();
812 try (Table table
= TEST_UTIL
.createTable(tableName
, FAMILY
)) {
813 table
.put(new Put(ROW
).addColumn(FAMILY
, QUALIFIER
, VALUE
));
815 Scan scan
= new Scan().withStartRow(ROW
).withStopRow(ROW
);
816 try (ResultScanner scanner
= table
.getScanner(scan
)) {
817 assertNull(scanner
.next());
820 scan
= new Scan().withStartRow(ROW
, true).withStopRow(ROW
, true);
821 try (ResultScanner scanner
= table
.getScanner(scan
)) {
822 Result result
= scanner
.next();
823 assertNotNull(result
);
824 assertArrayEquals(ROW
, result
.getRow());
825 assertArrayEquals(VALUE
, result
.getValue(FAMILY
, QUALIFIER
));
826 assertNull(scanner
.next());
829 scan
= new Scan().withStartRow(ROW
, true).withStopRow(ROW
, false);
830 try (ResultScanner scanner
= table
.getScanner(scan
)) {
831 assertNull(scanner
.next());
834 scan
= new Scan().withStartRow(ROW
, false).withStopRow(ROW
, false);
835 try (ResultScanner scanner
= table
.getScanner(scan
)) {
836 assertNull(scanner
.next());
839 scan
= new Scan().withStartRow(ROW
, false).withStopRow(ROW
, true);
840 try (ResultScanner scanner
= table
.getScanner(scan
)) {
841 assertNull(scanner
.next());
847 public void testReverseScanWithFlush() throws Exception
{
848 TableName tableName
= name
.getTableName();
849 final int BATCH_SIZE
= 10;
850 final int ROWS_TO_INSERT
= 100;
851 final byte[] LARGE_VALUE
= generateHugeValue(128 * 1024);
853 try (Table table
= TEST_UTIL
.createTable(tableName
, FAMILY
);
854 Admin admin
= TEST_UTIL
.getAdmin()) {
855 List
<Put
> putList
= new ArrayList
<>();
856 for (long i
= 0; i
< ROWS_TO_INSERT
; i
++) {
857 Put put
= new Put(Bytes
.toBytes(i
));
858 put
.addColumn(FAMILY
, QUALIFIER
, LARGE_VALUE
);
861 if (putList
.size() >= BATCH_SIZE
) {
863 admin
.flush(tableName
);
868 if (!putList
.isEmpty()) {
870 admin
.flush(tableName
);
874 Scan scan
= new Scan();
875 scan
.setReversed(true);
878 try (ResultScanner results
= table
.getScanner(scan
)) {
879 for (Result result
: results
) {
883 assertEquals("Expected " + ROWS_TO_INSERT
+ " rows in the table but it is " + count
,
884 ROWS_TO_INSERT
, count
);
889 public void testScannerWithPartialResults() throws Exception
{
890 TableName tableName
= TableName
.valueOf("testScannerWithPartialResults");
891 try (Table table
= TEST_UTIL
.createMultiRegionTable(tableName
,
892 Bytes
.toBytes("c"), 4)) {
893 List
<Put
> puts
= new ArrayList
<>();
894 byte[] largeArray
= new byte[10000];
895 Put put
= new Put(Bytes
.toBytes("aaaa0"));
896 put
.addColumn(Bytes
.toBytes("c"), Bytes
.toBytes("1"), Bytes
.toBytes("1"));
897 put
.addColumn(Bytes
.toBytes("c"), Bytes
.toBytes("2"), Bytes
.toBytes("2"));
898 put
.addColumn(Bytes
.toBytes("c"), Bytes
.toBytes("3"), Bytes
.toBytes("3"));
899 put
.addColumn(Bytes
.toBytes("c"), Bytes
.toBytes("4"), Bytes
.toBytes("4"));
901 put
= new Put(Bytes
.toBytes("aaaa1"));
902 put
.addColumn(Bytes
.toBytes("c"), Bytes
.toBytes("1"), Bytes
.toBytes("1"));
903 put
.addColumn(Bytes
.toBytes("c"), Bytes
.toBytes("2"), largeArray
);
904 put
.addColumn(Bytes
.toBytes("c"), Bytes
.toBytes("3"), largeArray
);
907 Scan scan
= new Scan();
908 scan
.addFamily(Bytes
.toBytes("c"));
909 scan
.setAttribute(Scan
.SCAN_ATTRIBUTES_TABLE_NAME
, tableName
.getName());
910 scan
.setMaxResultSize(10001);
911 scan
.setStopRow(Bytes
.toBytes("bbbb"));
912 scan
.setFilter(new LimitKVsReturnFilter());
913 ResultScanner rs
= table
.getScanner(scan
);
915 int expectedKvNumber
= 6;
916 int returnedKvNumber
= 0;
917 while((result
= rs
.next()) != null) {
918 returnedKvNumber
+= result
.listCells().size();
921 assertEquals(expectedKvNumber
, returnedKvNumber
);
925 public static class LimitKVsReturnFilter
extends FilterBase
{
927 private int cellCount
= 0;
930 public ReturnCode
filterCell(Cell v
) throws IOException
{
931 if (cellCount
>= 6) {
933 return ReturnCode
.SKIP
;
936 return ReturnCode
.INCLUDE
;
940 public boolean filterAllRemaining() throws IOException
{
949 public String
toString() {
950 return this.getClass().getSimpleName();
953 public static LimitKVsReturnFilter
parseFrom(final byte [] pbBytes
)
954 throws DeserializationException
{
955 return new LimitKVsReturnFilter();