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
.hamcrest
.MatcherAssert
.assertThat
;
25 import static org
.junit
.Assert
.assertArrayEquals
;
26 import static org
.junit
.Assert
.assertEquals
;
27 import static org
.junit
.Assert
.assertFalse
;
28 import static org
.junit
.Assert
.assertNotNull
;
29 import static org
.junit
.Assert
.assertNull
;
30 import static org
.junit
.Assert
.assertTrue
;
31 import static org
.junit
.Assert
.fail
;
33 import java
.io
.IOException
;
34 import java
.util
.ArrayList
;
35 import java
.util
.Arrays
;
36 import java
.util
.Collection
;
37 import java
.util
.List
;
38 import org
.apache
.hadoop
.conf
.Configuration
;
39 import org
.apache
.hadoop
.hbase
.Cell
;
40 import org
.apache
.hadoop
.hbase
.CompareOperator
;
41 import org
.apache
.hadoop
.hbase
.HBaseClassTestRule
;
42 import org
.apache
.hadoop
.hbase
.HBaseTestingUtil
;
43 import org
.apache
.hadoop
.hbase
.HConstants
;
44 import org
.apache
.hadoop
.hbase
.HRegionLocation
;
45 import org
.apache
.hadoop
.hbase
.HTestConst
;
46 import org
.apache
.hadoop
.hbase
.KeyValue
;
47 import org
.apache
.hadoop
.hbase
.SingleProcessHBaseCluster
;
48 import org
.apache
.hadoop
.hbase
.StartTestingClusterOption
;
49 import org
.apache
.hadoop
.hbase
.TableName
;
50 import org
.apache
.hadoop
.hbase
.TableNameTestRule
;
51 import org
.apache
.hadoop
.hbase
.TableNotFoundException
;
52 import org
.apache
.hadoop
.hbase
.client
.Scan
.ReadType
;
53 import org
.apache
.hadoop
.hbase
.exceptions
.DeserializationException
;
54 import org
.apache
.hadoop
.hbase
.filter
.BinaryComparator
;
55 import org
.apache
.hadoop
.hbase
.filter
.ColumnPrefixFilter
;
56 import org
.apache
.hadoop
.hbase
.filter
.ColumnRangeFilter
;
57 import org
.apache
.hadoop
.hbase
.filter
.FilterBase
;
58 import org
.apache
.hadoop
.hbase
.filter
.QualifierFilter
;
59 import org
.apache
.hadoop
.hbase
.regionserver
.HRegionServer
;
60 import org
.apache
.hadoop
.hbase
.testclassification
.ClientTests
;
61 import org
.apache
.hadoop
.hbase
.testclassification
.MediumTests
;
62 import org
.apache
.hadoop
.hbase
.util
.Bytes
;
63 import org
.apache
.hadoop
.hbase
.util
.EnvironmentEdgeManager
;
64 import org
.junit
.AfterClass
;
65 import org
.junit
.ClassRule
;
66 import org
.junit
.Rule
;
67 import org
.junit
.Test
;
68 import org
.junit
.experimental
.categories
.Category
;
69 import org
.junit
.runner
.RunWith
;
70 import org
.junit
.runners
.Parameterized
;
71 import org
.slf4j
.Logger
;
72 import org
.slf4j
.LoggerFactory
;
74 import org
.apache
.hbase
.thirdparty
.com
.google
.common
.base
.Preconditions
;
77 * A client-side test, mostly testing scanners with various parameters. Parameterized on different
78 * registry implementations.
80 @Category({MediumTests
.class, ClientTests
.class})
81 @RunWith(Parameterized
.class)
82 public class TestScannersFromClientSide
{
85 public static final HBaseClassTestRule CLASS_RULE
=
86 HBaseClassTestRule
.forClass(TestScannersFromClientSide
.class);
88 private static final Logger LOG
= LoggerFactory
.getLogger(TestScannersFromClientSide
.class);
90 private static HBaseTestingUtil TEST_UTIL
;
91 private static byte [] ROW
= Bytes
.toBytes("testRow");
92 private static byte [] FAMILY
= Bytes
.toBytes("testFamily");
93 private static byte [] QUALIFIER
= Bytes
.toBytes("testQualifier");
94 private static byte [] VALUE
= Bytes
.toBytes("testValue");
97 public TableNameTestRule name
= new TableNameTestRule();
100 public static void tearDownAfterClass() throws Exception
{
101 if (TEST_UTIL
!= null) {
102 TEST_UTIL
.shutdownMiniCluster();
106 @Parameterized.Parameters
107 public static Collection
<Object
[]> parameters() {
108 return Arrays
.asList(new Object
[][] {
109 { MasterRegistry
.class, 1},
110 { MasterRegistry
.class, 2},
111 { ZKConnectionRegistry
.class, 1}
116 * JUnit does not provide an easy way to run a hook after each parameterized run. Without that
117 * there is no easy way to restart the test cluster after each parameterized run. Annotation
118 * BeforeParam does not work either because it runs before parameterization and hence does not
119 * have access to the test parameters (which is weird).
121 * This *hack* checks if the current instance of test cluster configuration has the passed
122 * parameterized configs. In such a case, we can just reuse the cluster for test and do not need
123 * to initialize from scratch. While this is a hack, it saves a ton of time for the full
124 * test and de-flakes it.
126 private static boolean isSameParameterizedCluster(Class
<?
> registryImpl
, int numHedgedReqs
) {
127 // initialize() is called for every unit test, however we only want to reset the cluster state
128 // at the end of every parameterized run.
129 if (TEST_UTIL
== null) {
132 Configuration conf
= TEST_UTIL
.getConfiguration();
133 Class
<?
> confClass
= conf
.getClass(HConstants
.CLIENT_CONNECTION_REGISTRY_IMPL_CONF_KEY
,
134 ZKConnectionRegistry
.class);
135 int hedgedReqConfig
= conf
.getInt(MasterRegistry
.MASTER_REGISTRY_HEDGED_REQS_FANOUT_KEY
,
136 AbstractRpcBasedConnectionRegistry
.HEDGED_REQS_FANOUT_DEFAULT
);
137 return confClass
.getName().equals(registryImpl
.getName()) && numHedgedReqs
== hedgedReqConfig
;
140 public TestScannersFromClientSide(Class
<?
> registryImpl
, int numHedgedReqs
) throws Exception
{
141 if (isSameParameterizedCluster(registryImpl
, numHedgedReqs
)) {
144 if (TEST_UTIL
!= null) {
145 // We reached the end of a parameterized run, clean up the cluster.
146 TEST_UTIL
.shutdownMiniCluster();
148 TEST_UTIL
= new HBaseTestingUtil();
149 Configuration conf
= TEST_UTIL
.getConfiguration();
150 conf
.setLong(HConstants
.HBASE_CLIENT_SCANNER_MAX_RESULT_SIZE_KEY
, 10 * 1024 * 1024);
151 conf
.setClass(HConstants
.CLIENT_CONNECTION_REGISTRY_IMPL_CONF_KEY
, registryImpl
,
152 ConnectionRegistry
.class);
153 Preconditions
.checkArgument(numHedgedReqs
> 0);
154 conf
.setInt(MasterRegistry
.MASTER_REGISTRY_HEDGED_REQS_FANOUT_KEY
, numHedgedReqs
);
155 StartTestingClusterOption
.Builder builder
= StartTestingClusterOption
.builder();
156 // Multiple masters needed only when hedged reads for master registry are enabled.
157 builder
.numMasters(numHedgedReqs
> 1 ?
3 : 1).numRegionServers(3);
158 TEST_UTIL
.startMiniCluster(builder
.build());
162 * Test from client side for batch of scan
165 public void testScanBatch() throws Exception
{
166 final TableName tableName
= name
.getTableName();
167 byte [][] QUALIFIERS
= HTestConst
.makeNAscii(QUALIFIER
, 8);
169 Table ht
= TEST_UTIL
.createTable(tableName
, FAMILY
);
175 ResultScanner scanner
;
176 boolean toLog
= true;
177 List
<Cell
> kvListExp
;
179 // table: row, family, c0:0, c1:1, ... , c7:7
181 for (int i
=0; i
< QUALIFIERS
.length
; i
++) {
182 KeyValue kv
= new KeyValue(ROW
, FAMILY
, QUALIFIERS
[i
], i
, VALUE
);
187 // table: row, family, c0:0, c1:1, ..., c6:2, c6:6 , c7:7
189 KeyValue kv
= new KeyValue(ROW
, FAMILY
, QUALIFIERS
[6], 2, VALUE
);
194 delete
= new Delete(ROW
);
195 delete
.addFamily(FAMILY
, 3);
199 scan
= new Scan().withStartRow(ROW
);
200 scan
.readAllVersions();
201 scanner
= ht
.getScanner(scan
);
203 // c4:4, c5:5, c6:6, c7:7
204 kvListExp
= new ArrayList
<>();
205 kvListExp
.add(new KeyValue(ROW
, FAMILY
, QUALIFIERS
[4], 4, VALUE
));
206 kvListExp
.add(new KeyValue(ROW
, FAMILY
, QUALIFIERS
[5], 5, VALUE
));
207 kvListExp
.add(new KeyValue(ROW
, FAMILY
, QUALIFIERS
[6], 6, VALUE
));
208 kvListExp
.add(new KeyValue(ROW
, FAMILY
, QUALIFIERS
[7], 7, VALUE
));
209 result
= scanner
.next();
210 verifyResult(result
, kvListExp
, toLog
, "Testing first batch of scan");
213 scan
= new Scan().withStartRow(ROW
);
214 scan
.readAllVersions();
216 scanner
= ht
.getScanner(scan
);
218 // First batch: c4:4, c5:5
219 kvListExp
= new ArrayList
<>();
220 kvListExp
.add(new KeyValue(ROW
, FAMILY
, QUALIFIERS
[4], 4, VALUE
));
221 kvListExp
.add(new KeyValue(ROW
, FAMILY
, QUALIFIERS
[5], 5, VALUE
));
222 result
= scanner
.next();
223 verifyResult(result
, kvListExp
, toLog
, "Testing first batch of scan");
225 // Second batch: c6:6, c7:7
226 kvListExp
= new ArrayList
<>();
227 kvListExp
.add(new KeyValue(ROW
, FAMILY
, QUALIFIERS
[6], 6, VALUE
));
228 kvListExp
.add(new KeyValue(ROW
, FAMILY
, QUALIFIERS
[7], 7, VALUE
));
229 result
= scanner
.next();
230 verifyResult(result
, kvListExp
, toLog
, "Testing second batch of scan");
235 public void testMaxResultSizeIsSetToDefault() throws Exception
{
236 final TableName tableName
= name
.getTableName();
237 Table ht
= TEST_UTIL
.createTable(tableName
, FAMILY
);
239 // The max result size we expect the scan to use by default.
240 long expectedMaxResultSize
=
241 TEST_UTIL
.getConfiguration().getLong(HConstants
.HBASE_CLIENT_SCANNER_MAX_RESULT_SIZE_KEY
,
242 HConstants
.DEFAULT_HBASE_CLIENT_SCANNER_MAX_RESULT_SIZE
);
245 byte[][] ROWS
= HTestConst
.makeNAscii(ROW
, numRows
);
247 int numQualifiers
= 10;
248 byte[][] QUALIFIERS
= HTestConst
.makeNAscii(QUALIFIER
, numQualifiers
);
250 // Specify the cell size such that a single row will be larger than the default
251 // value of maxResultSize. This means that Scan RPCs should return at most a single
252 // result back to the client.
253 int cellSize
= (int) (expectedMaxResultSize
/ (numQualifiers
- 1));
254 byte[] cellValue
= Bytes
.createMaxByteArray(cellSize
);
257 List
<Put
> puts
= new ArrayList
<>();
258 for (int row
= 0; row
< ROWS
.length
; row
++) {
259 put
= new Put(ROWS
[row
]);
260 for (int qual
= 0; qual
< QUALIFIERS
.length
; qual
++) {
261 KeyValue kv
= new KeyValue(ROWS
[row
], FAMILY
, QUALIFIERS
[qual
], cellValue
);
268 // Create a scan with the default configuration.
269 Scan scan
= new Scan();
271 try (ResultScanner scanner
= ht
.getScanner(scan
)) {
272 assertThat(scanner
, instanceOf(AsyncTableResultScanner
.class));
274 AsyncTableResultScanner s
= (AsyncTableResultScanner
) scanner
;
275 // The scanner should have, at most, a single result in its cache. If there more results
277 // in the cache it means that more than the expected max result size was fetched.
278 assertTrue("The cache contains: " + s
.getCacheSize() + " results", s
.getCacheSize() <= 1);
283 * Scan on not existing table should throw the exception with correct message
286 public void testScannerForNotExistingTable() {
287 String
[] tableNames
= {"A", "Z", "A:A", "Z:Z"};
288 for(String tableName
: tableNames
) {
290 Table table
= TEST_UTIL
.getConnection().getTable(TableName
.valueOf(tableName
));
291 testSmallScan(table
, true, 1, 5);
292 fail("TableNotFoundException was not thrown");
293 } catch (TableNotFoundException e
) {
294 // We expect that the message for TableNotFoundException would have only the table name only
295 // Otherwise that would mean that localeRegionInMeta doesn't work properly
296 assertEquals(e
.getMessage(), tableName
);
297 } catch (Exception e
) {
298 fail("Unexpected exception " + e
.getMessage());
304 public void testSmallScan() throws Exception
{
305 final TableName tableName
= name
.getTableName();
308 byte[][] ROWS
= HTestConst
.makeNAscii(ROW
, numRows
);
310 int numQualifiers
= 10;
311 byte[][] QUALIFIERS
= HTestConst
.makeNAscii(QUALIFIER
, numQualifiers
);
313 Table ht
= TEST_UTIL
.createTable(tableName
, FAMILY
);
316 List
<Put
> puts
= new ArrayList
<>();
317 for (int row
= 0; row
< ROWS
.length
; row
++) {
318 put
= new Put(ROWS
[row
]);
319 for (int qual
= 0; qual
< QUALIFIERS
.length
; qual
++) {
320 KeyValue kv
= new KeyValue(ROWS
[row
], FAMILY
, QUALIFIERS
[qual
], VALUE
);
327 int expectedRows
= numRows
;
328 int expectedCols
= numRows
* numQualifiers
;
330 // Test normal and reversed
331 testSmallScan(ht
, true, expectedRows
, expectedCols
);
332 testSmallScan(ht
, false, expectedRows
, expectedCols
);
336 * Run through a variety of test configurations with a small scan
338 private void testSmallScan(
339 Table table
, boolean reversed
, int rows
, int columns
) throws Exception
{
340 Scan baseScan
= new Scan();
341 baseScan
.setReversed(reversed
);
342 baseScan
.setReadType(ReadType
.PREAD
);
344 Scan scan
= new Scan(baseScan
);
345 verifyExpectedCounts(table
, scan
, rows
, columns
);
347 scan
= new Scan(baseScan
);
348 scan
.setMaxResultSize(1);
349 verifyExpectedCounts(table
, scan
, rows
, columns
);
351 scan
= new Scan(baseScan
);
352 scan
.setMaxResultSize(1);
353 scan
.setCaching(Integer
.MAX_VALUE
);
354 verifyExpectedCounts(table
, scan
, rows
, columns
);
357 private void verifyExpectedCounts(Table table
, Scan scan
, int expectedRowCount
,
358 int expectedCellCount
) throws Exception
{
359 ResultScanner scanner
= table
.getScanner(scan
);
364 while ((r
= scanner
.next()) != null) {
366 cellCount
+= r
.rawCells().length
;
369 assertTrue("Expected row count: " + expectedRowCount
+ " Actual row count: " + rowCount
,
370 expectedRowCount
== rowCount
);
371 assertTrue("Expected cell count: " + expectedCellCount
+ " Actual cell count: " + cellCount
,
372 expectedCellCount
== cellCount
);
377 * Test from client side for get with maxResultPerCF set
380 public void testGetMaxResults() throws Exception
{
381 final TableName tableName
= name
.getTableName();
382 byte [][] FAMILIES
= HTestConst
.makeNAscii(FAMILY
, 3);
383 byte [][] QUALIFIERS
= HTestConst
.makeNAscii(QUALIFIER
, 20);
385 Table ht
= TEST_UTIL
.createTable(tableName
, FAMILIES
);
390 boolean toLog
= true;
391 List
<Cell
> kvListExp
;
393 kvListExp
= new ArrayList
<>();
394 // Insert one CF for row[0]
396 for (int i
=0; i
< 10; i
++) {
397 KeyValue kv
= new KeyValue(ROW
, FAMILIES
[0], QUALIFIERS
[i
], 1, VALUE
);
404 result
= ht
.get(get
);
405 verifyResult(result
, kvListExp
, toLog
, "Testing without setting maxResults");
408 get
.setMaxResultsPerColumnFamily(2);
409 result
= ht
.get(get
);
410 kvListExp
= new ArrayList
<>();
411 kvListExp
.add(new KeyValue(ROW
, FAMILIES
[0], QUALIFIERS
[0], 1, VALUE
));
412 kvListExp
.add(new KeyValue(ROW
, FAMILIES
[0], QUALIFIERS
[1], 1, VALUE
));
413 verifyResult(result
, kvListExp
, toLog
, "Testing basic setMaxResults");
415 // Filters: ColumnRangeFilter
417 get
.setMaxResultsPerColumnFamily(5);
418 get
.setFilter(new ColumnRangeFilter(QUALIFIERS
[2], true, QUALIFIERS
[5],
420 result
= ht
.get(get
);
421 kvListExp
= new ArrayList
<>();
422 kvListExp
.add(new KeyValue(ROW
, FAMILIES
[0], QUALIFIERS
[2], 1, VALUE
));
423 kvListExp
.add(new KeyValue(ROW
, FAMILIES
[0], QUALIFIERS
[3], 1, VALUE
));
424 kvListExp
.add(new KeyValue(ROW
, FAMILIES
[0], QUALIFIERS
[4], 1, VALUE
));
425 kvListExp
.add(new KeyValue(ROW
, FAMILIES
[0], QUALIFIERS
[5], 1, VALUE
));
426 verifyResult(result
, kvListExp
, toLog
, "Testing single CF with CRF");
428 // Insert two more CF for row[0]
429 // 20 columns for CF2, 10 columns for CF1
431 for (int i
=0; i
< QUALIFIERS
.length
; i
++) {
432 KeyValue kv
= new KeyValue(ROW
, FAMILIES
[2], QUALIFIERS
[i
], 1, VALUE
);
438 for (int i
=0; i
< 10; i
++) {
439 KeyValue kv
= new KeyValue(ROW
, FAMILIES
[1], QUALIFIERS
[i
], 1, VALUE
);
445 get
.setMaxResultsPerColumnFamily(12);
446 get
.addFamily(FAMILIES
[1]);
447 get
.addFamily(FAMILIES
[2]);
448 result
= ht
.get(get
);
449 kvListExp
= new ArrayList
<>();
450 //Exp: CF1:q0, ..., q9, CF2: q0, q1, q10, q11, ..., q19
451 for (int i
=0; i
< 10; i
++) {
452 kvListExp
.add(new KeyValue(ROW
, FAMILIES
[1], QUALIFIERS
[i
], 1, VALUE
));
454 for (int i
=0; i
< 2; i
++) {
455 kvListExp
.add(new KeyValue(ROW
, FAMILIES
[2], QUALIFIERS
[i
], 1, VALUE
));
457 for (int i
=10; i
< 20; i
++) {
458 kvListExp
.add(new KeyValue(ROW
, FAMILIES
[2], QUALIFIERS
[i
], 1, VALUE
));
460 verifyResult(result
, kvListExp
, toLog
, "Testing multiple CFs");
462 // Filters: ColumnRangeFilter and ColumnPrefixFilter
464 get
.setMaxResultsPerColumnFamily(3);
465 get
.setFilter(new ColumnRangeFilter(QUALIFIERS
[2], true, null, true));
466 result
= ht
.get(get
);
467 kvListExp
= new ArrayList
<>();
468 for (int i
=2; i
< 5; i
++) {
469 kvListExp
.add(new KeyValue(ROW
, FAMILIES
[0], QUALIFIERS
[i
], 1, VALUE
));
471 for (int i
=2; i
< 5; i
++) {
472 kvListExp
.add(new KeyValue(ROW
, FAMILIES
[1], QUALIFIERS
[i
], 1, VALUE
));
474 for (int i
=2; i
< 5; i
++) {
475 kvListExp
.add(new KeyValue(ROW
, FAMILIES
[2], QUALIFIERS
[i
], 1, VALUE
));
477 verifyResult(result
, kvListExp
, toLog
, "Testing multiple CFs + CRF");
480 get
.setMaxResultsPerColumnFamily(7);
481 get
.setFilter(new ColumnPrefixFilter(QUALIFIERS
[1]));
482 result
= ht
.get(get
);
483 kvListExp
= new ArrayList
<>();
484 kvListExp
.add(new KeyValue(ROW
, FAMILIES
[0], QUALIFIERS
[1], 1, VALUE
));
485 kvListExp
.add(new KeyValue(ROW
, FAMILIES
[1], QUALIFIERS
[1], 1, VALUE
));
486 kvListExp
.add(new KeyValue(ROW
, FAMILIES
[2], QUALIFIERS
[1], 1, VALUE
));
487 for (int i
=10; i
< 16; i
++) {
488 kvListExp
.add(new KeyValue(ROW
, FAMILIES
[2], QUALIFIERS
[i
], 1, VALUE
));
490 verifyResult(result
, kvListExp
, toLog
, "Testing multiple CFs + PFF");
495 * Test from client side for scan with maxResultPerCF set
498 public void testScanMaxResults() throws Exception
{
499 final TableName tableName
= name
.getTableName();
500 byte [][] ROWS
= HTestConst
.makeNAscii(ROW
, 2);
501 byte [][] FAMILIES
= HTestConst
.makeNAscii(FAMILY
, 3);
502 byte [][] QUALIFIERS
= HTestConst
.makeNAscii(QUALIFIER
, 10);
504 Table ht
= TEST_UTIL
.createTable(tableName
, FAMILIES
);
509 boolean toLog
= true;
510 List
<Cell
> kvListExp
, kvListScan
;
512 kvListExp
= new ArrayList
<>();
514 for (int r
=0; r
< ROWS
.length
; r
++) {
515 put
= new Put(ROWS
[r
]);
516 for (int c
=0; c
< FAMILIES
.length
; c
++) {
517 for (int q
=0; q
< QUALIFIERS
.length
; q
++) {
518 KeyValue kv
= new KeyValue(ROWS
[r
], FAMILIES
[c
], QUALIFIERS
[q
], 1, VALUE
);
529 scan
.setMaxResultsPerColumnFamily(4);
530 ResultScanner scanner
= ht
.getScanner(scan
);
531 kvListScan
= new ArrayList
<>();
532 while ((result
= scanner
.next()) != null) {
533 for (Cell kv
: result
.listCells()) {
537 result
= Result
.create(kvListScan
);
538 verifyResult(result
, kvListExp
, toLog
, "Testing scan with maxResults");
543 * Test from client side for get with rowOffset
546 public void testGetRowOffset() throws Exception
{
547 final TableName tableName
= name
.getTableName();
548 byte [][] FAMILIES
= HTestConst
.makeNAscii(FAMILY
, 3);
549 byte [][] QUALIFIERS
= HTestConst
.makeNAscii(QUALIFIER
, 20);
551 Table ht
= TEST_UTIL
.createTable(tableName
, FAMILIES
);
556 boolean toLog
= true;
557 List
<Cell
> kvListExp
;
559 // Insert one CF for row
560 kvListExp
= new ArrayList
<>();
562 for (int i
=0; i
< 10; i
++) {
563 KeyValue kv
= new KeyValue(ROW
, FAMILIES
[0], QUALIFIERS
[i
], 1, VALUE
);
565 // skipping first two kvs
573 //setting offset to 2
575 get
.setRowOffsetPerColumnFamily(2);
576 result
= ht
.get(get
);
577 verifyResult(result
, kvListExp
, toLog
, "Testing basic setRowOffset");
579 //setting offset to 20
581 get
.setRowOffsetPerColumnFamily(20);
582 result
= ht
.get(get
);
583 kvListExp
= new ArrayList
<>();
584 verifyResult(result
, kvListExp
, toLog
, "Testing offset > #kvs");
586 //offset + maxResultPerCF
588 get
.setRowOffsetPerColumnFamily(4);
589 get
.setMaxResultsPerColumnFamily(5);
590 result
= ht
.get(get
);
591 kvListExp
= new ArrayList
<>();
592 for (int i
=4; i
< 9; i
++) {
593 kvListExp
.add(new KeyValue(ROW
, FAMILIES
[0], QUALIFIERS
[i
], 1, VALUE
));
595 verifyResult(result
, kvListExp
, toLog
,
596 "Testing offset + setMaxResultsPerCF");
598 // Filters: ColumnRangeFilter
600 get
.setRowOffsetPerColumnFamily(1);
601 get
.setFilter(new ColumnRangeFilter(QUALIFIERS
[2], true, QUALIFIERS
[5],
603 result
= ht
.get(get
);
604 kvListExp
= new ArrayList
<>();
605 kvListExp
.add(new KeyValue(ROW
, FAMILIES
[0], QUALIFIERS
[3], 1, VALUE
));
606 kvListExp
.add(new KeyValue(ROW
, FAMILIES
[0], QUALIFIERS
[4], 1, VALUE
));
607 kvListExp
.add(new KeyValue(ROW
, FAMILIES
[0], QUALIFIERS
[5], 1, VALUE
));
608 verifyResult(result
, kvListExp
, toLog
, "Testing offset with CRF");
610 // Insert into two more CFs for row
611 // 10 columns for CF2, 10 columns for CF1
612 for(int j
=2; j
> 0; j
--) {
614 for (int i
=0; i
< 10; i
++) {
615 KeyValue kv
= new KeyValue(ROW
, FAMILIES
[j
], QUALIFIERS
[i
], 1, VALUE
);
622 get
.setRowOffsetPerColumnFamily(4);
623 get
.setMaxResultsPerColumnFamily(2);
624 get
.addFamily(FAMILIES
[1]);
625 get
.addFamily(FAMILIES
[2]);
626 result
= ht
.get(get
);
627 kvListExp
= new ArrayList
<>();
628 //Exp: CF1:q4, q5, CF2: q4, q5
629 kvListExp
.add(new KeyValue(ROW
, FAMILIES
[1], QUALIFIERS
[4], 1, VALUE
));
630 kvListExp
.add(new KeyValue(ROW
, FAMILIES
[1], QUALIFIERS
[5], 1, VALUE
));
631 kvListExp
.add(new KeyValue(ROW
, FAMILIES
[2], QUALIFIERS
[4], 1, VALUE
));
632 kvListExp
.add(new KeyValue(ROW
, FAMILIES
[2], QUALIFIERS
[5], 1, VALUE
));
633 verifyResult(result
, kvListExp
, toLog
,
634 "Testing offset + multiple CFs + maxResults");
638 public void testScanRawDeleteFamilyVersion() throws Exception
{
639 TableName tableName
= name
.getTableName();
640 TEST_UTIL
.createTable(tableName
, FAMILY
);
641 Configuration conf
= new Configuration(TEST_UTIL
.getConfiguration());
642 conf
.set(RPC_CODEC_CONF_KEY
, "");
643 conf
.set(DEFAULT_CODEC_CLASS
, "");
644 try (Connection connection
= ConnectionFactory
.createConnection(conf
);
645 Table table
= connection
.getTable(tableName
)) {
646 Delete delete
= new Delete(ROW
);
647 delete
.addFamilyVersion(FAMILY
, 0L);
648 table
.delete(delete
);
649 Scan scan
= new Scan().withStartRow(ROW
).setRaw(true);
650 ResultScanner scanner
= table
.getScanner(scan
);
652 while (scanner
.next() != null) {
655 assertEquals(1, count
);
657 TEST_UTIL
.deleteTable(tableName
);
662 * Test from client side for scan while the region is reopened
663 * on the same region server.
666 public void testScanOnReopenedRegion() throws Exception
{
667 final TableName tableName
= name
.getTableName();
668 byte [][] QUALIFIERS
= HTestConst
.makeNAscii(QUALIFIER
, 2);
670 Table ht
= TEST_UTIL
.createTable(tableName
, FAMILY
);
675 ResultScanner scanner
;
676 boolean toLog
= false;
677 List
<Cell
> kvListExp
;
679 // table: row, family, c0:0, c1:1
681 for (int i
=0; i
< QUALIFIERS
.length
; i
++) {
682 KeyValue kv
= new KeyValue(ROW
, FAMILY
, QUALIFIERS
[i
], i
, VALUE
);
687 scan
= new Scan().withStartRow(ROW
);
688 scanner
= ht
.getScanner(scan
);
692 try (RegionLocator locator
= TEST_UTIL
.getConnection().getRegionLocator(tableName
)) {
693 loc
= locator
.getRegionLocation(ROW
);
695 RegionInfo hri
= loc
.getRegion();
696 SingleProcessHBaseCluster cluster
= TEST_UTIL
.getMiniHBaseCluster();
697 byte[] regionName
= hri
.getRegionName();
698 int i
= cluster
.getServerWith(regionName
);
699 HRegionServer rs
= cluster
.getRegionServer(i
);
700 LOG
.info("Unassigning " + hri
);
701 TEST_UTIL
.getAdmin().unassign(hri
.getRegionName(), true);
702 long startTime
= EnvironmentEdgeManager
.currentTime();
703 long timeOut
= 10000;
704 boolean offline
= false;
706 if (rs
.getOnlineRegion(regionName
) == null) {
710 assertTrue("Timed out in closing the testing region",
711 EnvironmentEdgeManager
.currentTime() < startTime
+ timeOut
);
714 LOG
.info("Assigning " + hri
);
715 TEST_UTIL
.getAdmin().assign(hri
.getRegionName());
716 startTime
= EnvironmentEdgeManager
.currentTime();
718 rs
= cluster
.getRegionServer(cluster
.getServerWith(regionName
));
719 if (rs
!= null && rs
.getOnlineRegion(regionName
) != null) {
723 assertTrue("Timed out in open the testing region",
724 EnvironmentEdgeManager
.currentTime() < startTime
+ timeOut
);
726 assertFalse(offline
);
729 kvListExp
= new ArrayList
<>();
730 kvListExp
.add(new KeyValue(ROW
, FAMILY
, QUALIFIERS
[0], 0, VALUE
));
731 kvListExp
.add(new KeyValue(ROW
, FAMILY
, QUALIFIERS
[1], 1, VALUE
));
732 result
= scanner
.next();
733 verifyResult(result
, kvListExp
, toLog
, "Testing scan on re-opened region");
736 static void verifyResult(Result result
, List
<Cell
> expKvList
, boolean toLog
,
740 LOG
.info("Expected count: " + expKvList
.size());
741 LOG
.info("Actual count: " + result
.size());
742 if (expKvList
.isEmpty()) {
747 for (Cell kv
: result
.rawCells()) {
748 if (i
>= expKvList
.size()) {
749 break; // we will check the size later
752 Cell kvExp
= expKvList
.get(i
++);
754 LOG
.info("get kv is: " + kv
.toString());
755 LOG
.info("exp kv is: " + kvExp
.toString());
757 assertTrue("Not equal", kvExp
.equals(kv
));
760 assertEquals(expKvList
.size(), result
.size());
764 public void testReadExpiredDataForRawScan() throws IOException
{
765 TableName tableName
= name
.getTableName();
766 long ts
= EnvironmentEdgeManager
.currentTime() - 10000;
767 byte[] value
= Bytes
.toBytes("expired");
768 try (Table table
= TEST_UTIL
.createTable(tableName
, FAMILY
)) {
769 table
.put(new Put(ROW
).addColumn(FAMILY
, QUALIFIER
, ts
, value
));
770 assertArrayEquals(value
, table
.get(new Get(ROW
)).getValue(FAMILY
, QUALIFIER
));
771 TEST_UTIL
.getAdmin().modifyColumnFamily(tableName
,
772 ColumnFamilyDescriptorBuilder
.newBuilder(FAMILY
).setTimeToLive(5).build());
773 try (ResultScanner scanner
= table
.getScanner(FAMILY
)) {
774 assertNull(scanner
.next());
776 try (ResultScanner scanner
= table
.getScanner(new Scan().setRaw(true))) {
777 assertArrayEquals(value
, scanner
.next().getValue(FAMILY
, QUALIFIER
));
778 assertNull(scanner
.next());
784 public void testScanWithColumnsAndFilterAndVersion() throws IOException
{
785 TableName tableName
= name
.getTableName();
786 long now
= EnvironmentEdgeManager
.currentTime();
787 try (Table table
= TEST_UTIL
.createTable(tableName
, FAMILY
, 4)) {
788 for (int i
= 0; i
< 4; i
++) {
789 Put put
= new Put(ROW
);
790 put
.addColumn(FAMILY
, QUALIFIER
, now
+ i
, VALUE
);
794 Scan scan
= new Scan();
795 scan
.addColumn(FAMILY
, QUALIFIER
);
796 scan
.setFilter(new QualifierFilter(CompareOperator
.EQUAL
, new BinaryComparator(QUALIFIER
)));
797 scan
.readVersions(3);
799 try (ResultScanner scanner
= table
.getScanner(scan
)) {
800 Result result
= scanner
.next();
801 assertEquals(3, result
.size());
807 public void testScanWithSameStartRowStopRow() throws IOException
{
808 TableName tableName
= name
.getTableName();
809 try (Table table
= TEST_UTIL
.createTable(tableName
, FAMILY
)) {
810 table
.put(new Put(ROW
).addColumn(FAMILY
, QUALIFIER
, VALUE
));
812 Scan scan
= new Scan().withStartRow(ROW
).withStopRow(ROW
);
813 try (ResultScanner scanner
= table
.getScanner(scan
)) {
814 assertNull(scanner
.next());
817 scan
= new Scan().withStartRow(ROW
, true).withStopRow(ROW
, true);
818 try (ResultScanner scanner
= table
.getScanner(scan
)) {
819 Result result
= scanner
.next();
820 assertNotNull(result
);
821 assertArrayEquals(ROW
, result
.getRow());
822 assertArrayEquals(VALUE
, result
.getValue(FAMILY
, QUALIFIER
));
823 assertNull(scanner
.next());
826 scan
= new Scan().withStartRow(ROW
, true).withStopRow(ROW
, false);
827 try (ResultScanner scanner
= table
.getScanner(scan
)) {
828 assertNull(scanner
.next());
831 scan
= new Scan().withStartRow(ROW
, false).withStopRow(ROW
, false);
832 try (ResultScanner scanner
= table
.getScanner(scan
)) {
833 assertNull(scanner
.next());
836 scan
= new Scan().withStartRow(ROW
, false).withStopRow(ROW
, true);
837 try (ResultScanner scanner
= table
.getScanner(scan
)) {
838 assertNull(scanner
.next());
844 public void testReverseScanWithFlush() throws Exception
{
845 TableName tableName
= name
.getTableName();
846 final int BATCH_SIZE
= 10;
847 final int ROWS_TO_INSERT
= 100;
848 final byte[] LARGE_VALUE
= generateHugeValue(128 * 1024);
850 try (Table table
= TEST_UTIL
.createTable(tableName
, FAMILY
);
851 Admin admin
= TEST_UTIL
.getAdmin()) {
852 List
<Put
> putList
= new ArrayList
<>();
853 for (long i
= 0; i
< ROWS_TO_INSERT
; i
++) {
854 Put put
= new Put(Bytes
.toBytes(i
));
855 put
.addColumn(FAMILY
, QUALIFIER
, LARGE_VALUE
);
858 if (putList
.size() >= BATCH_SIZE
) {
860 admin
.flush(tableName
);
865 if (!putList
.isEmpty()) {
867 admin
.flush(tableName
);
871 Scan scan
= new Scan();
872 scan
.setReversed(true);
875 try (ResultScanner results
= table
.getScanner(scan
)) {
876 for (Result result
: results
) {
880 assertEquals("Expected " + ROWS_TO_INSERT
+ " rows in the table but it is " + count
,
881 ROWS_TO_INSERT
, count
);
886 public void testScannerWithPartialResults() throws Exception
{
887 TableName tableName
= TableName
.valueOf("testScannerWithPartialResults");
888 try (Table table
= TEST_UTIL
.createMultiRegionTable(tableName
,
889 Bytes
.toBytes("c"), 4)) {
890 List
<Put
> puts
= new ArrayList
<>();
891 byte[] largeArray
= new byte[10000];
892 Put put
= new Put(Bytes
.toBytes("aaaa0"));
893 put
.addColumn(Bytes
.toBytes("c"), Bytes
.toBytes("1"), Bytes
.toBytes("1"));
894 put
.addColumn(Bytes
.toBytes("c"), Bytes
.toBytes("2"), Bytes
.toBytes("2"));
895 put
.addColumn(Bytes
.toBytes("c"), Bytes
.toBytes("3"), Bytes
.toBytes("3"));
896 put
.addColumn(Bytes
.toBytes("c"), Bytes
.toBytes("4"), Bytes
.toBytes("4"));
898 put
= new Put(Bytes
.toBytes("aaaa1"));
899 put
.addColumn(Bytes
.toBytes("c"), Bytes
.toBytes("1"), Bytes
.toBytes("1"));
900 put
.addColumn(Bytes
.toBytes("c"), Bytes
.toBytes("2"), largeArray
);
901 put
.addColumn(Bytes
.toBytes("c"), Bytes
.toBytes("3"), largeArray
);
904 Scan scan
= new Scan();
905 scan
.addFamily(Bytes
.toBytes("c"));
906 scan
.setAttribute(Scan
.SCAN_ATTRIBUTES_TABLE_NAME
, tableName
.getName());
907 scan
.setMaxResultSize(10001);
908 scan
.withStopRow(Bytes
.toBytes("bbbb"));
909 scan
.setFilter(new LimitKVsReturnFilter());
910 ResultScanner rs
= table
.getScanner(scan
);
912 int expectedKvNumber
= 6;
913 int returnedKvNumber
= 0;
914 while((result
= rs
.next()) != null) {
915 returnedKvNumber
+= result
.listCells().size();
918 assertEquals(expectedKvNumber
, returnedKvNumber
);
922 public static class LimitKVsReturnFilter
extends FilterBase
{
924 private int cellCount
= 0;
927 public ReturnCode
filterCell(Cell v
) throws IOException
{
928 if (cellCount
>= 6) {
930 return ReturnCode
.SKIP
;
933 return ReturnCode
.INCLUDE
;
937 public boolean filterAllRemaining() throws IOException
{
946 public String
toString() {
947 return this.getClass().getSimpleName();
950 public static LimitKVsReturnFilter
parseFrom(final byte [] pbBytes
)
951 throws DeserializationException
{
952 return new LimitKVsReturnFilter();