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
.junit
.Assert
.assertArrayEquals
;
21 import static org
.junit
.Assert
.assertEquals
;
22 import static org
.junit
.Assert
.assertFalse
;
23 import static org
.junit
.Assert
.assertNotNull
;
24 import static org
.junit
.Assert
.assertNull
;
25 import static org
.junit
.Assert
.assertTrue
;
26 import static org
.junit
.Assert
.fail
;
28 import java
.io
.IOException
;
29 import java
.util
.ArrayList
;
30 import java
.util
.Arrays
;
31 import java
.util
.Collection
;
32 import java
.util
.LinkedList
;
33 import java
.util
.List
;
35 import java
.util
.NavigableMap
;
36 import java
.util
.concurrent
.Callable
;
37 import java
.util
.concurrent
.ExecutorService
;
38 import java
.util
.concurrent
.Executors
;
39 import java
.util
.concurrent
.atomic
.AtomicReference
;
40 import org
.apache
.commons
.lang3
.ArrayUtils
;
41 import org
.apache
.hadoop
.conf
.Configuration
;
42 import org
.apache
.hadoop
.fs
.Path
;
43 import org
.apache
.hadoop
.hbase
.Cell
;
44 import org
.apache
.hadoop
.hbase
.CellScanner
;
45 import org
.apache
.hadoop
.hbase
.CellUtil
;
46 import org
.apache
.hadoop
.hbase
.CompareOperator
;
47 import org
.apache
.hadoop
.hbase
.DoNotRetryIOException
;
48 import org
.apache
.hadoop
.hbase
.HBaseClassTestRule
;
49 import org
.apache
.hadoop
.hbase
.HConstants
;
50 import org
.apache
.hadoop
.hbase
.HRegionLocation
;
51 import org
.apache
.hadoop
.hbase
.KeyValue
;
52 import org
.apache
.hadoop
.hbase
.PrivateCellUtil
;
53 import org
.apache
.hadoop
.hbase
.ServerName
;
54 import org
.apache
.hadoop
.hbase
.TableName
;
55 import org
.apache
.hadoop
.hbase
.TableNameTestRule
;
56 import org
.apache
.hadoop
.hbase
.Waiter
;
57 import org
.apache
.hadoop
.hbase
.client
.metrics
.ScanMetrics
;
58 import org
.apache
.hadoop
.hbase
.coprocessor
.MultiRowMutationEndpoint
;
59 import org
.apache
.hadoop
.hbase
.filter
.BinaryComparator
;
60 import org
.apache
.hadoop
.hbase
.filter
.Filter
;
61 import org
.apache
.hadoop
.hbase
.filter
.FilterList
;
62 import org
.apache
.hadoop
.hbase
.filter
.FirstKeyOnlyFilter
;
63 import org
.apache
.hadoop
.hbase
.filter
.InclusiveStopFilter
;
64 import org
.apache
.hadoop
.hbase
.filter
.KeyOnlyFilter
;
65 import org
.apache
.hadoop
.hbase
.filter
.QualifierFilter
;
66 import org
.apache
.hadoop
.hbase
.filter
.RegexStringComparator
;
67 import org
.apache
.hadoop
.hbase
.filter
.RowFilter
;
68 import org
.apache
.hadoop
.hbase
.filter
.SubstringComparator
;
69 import org
.apache
.hadoop
.hbase
.filter
.ValueFilter
;
70 import org
.apache
.hadoop
.hbase
.io
.TimeRange
;
71 import org
.apache
.hadoop
.hbase
.io
.hfile
.BlockCache
;
72 import org
.apache
.hadoop
.hbase
.io
.hfile
.CacheConfig
;
73 import org
.apache
.hadoop
.hbase
.ipc
.CoprocessorRpcChannel
;
74 import org
.apache
.hadoop
.hbase
.regionserver
.HRegion
;
75 import org
.apache
.hadoop
.hbase
.regionserver
.HRegionServer
;
76 import org
.apache
.hadoop
.hbase
.regionserver
.HStore
;
77 import org
.apache
.hadoop
.hbase
.regionserver
.NoSuchColumnFamilyException
;
78 import org
.apache
.hadoop
.hbase
.testclassification
.ClientTests
;
79 import org
.apache
.hadoop
.hbase
.testclassification
.LargeTests
;
80 import org
.apache
.hadoop
.hbase
.util
.Bytes
;
81 import org
.apache
.hadoop
.hbase
.util
.EnvironmentEdgeManager
;
82 import org
.apache
.hadoop
.hbase
.util
.FSUtils
;
83 import org
.junit
.AfterClass
;
84 import org
.junit
.ClassRule
;
85 import org
.junit
.Ignore
;
86 import org
.junit
.Rule
;
87 import org
.junit
.Test
;
88 import org
.junit
.experimental
.categories
.Category
;
89 import org
.junit
.runner
.RunWith
;
90 import org
.junit
.runners
.Parameterized
;
91 import org
.slf4j
.Logger
;
92 import org
.slf4j
.LoggerFactory
;
94 import org
.apache
.hadoop
.hbase
.shaded
.protobuf
.ProtobufUtil
;
95 import org
.apache
.hadoop
.hbase
.shaded
.protobuf
.generated
.ClientProtos
.MutationProto
;
96 import org
.apache
.hadoop
.hbase
.shaded
.protobuf
.generated
.ClientProtos
.MutationProto
.MutationType
;
97 import org
.apache
.hadoop
.hbase
.shaded
.protobuf
.generated
.MultiRowMutationProtos
.MultiRowMutationService
;
98 import org
.apache
.hadoop
.hbase
.shaded
.protobuf
.generated
.MultiRowMutationProtos
.MutateRowsRequest
;
101 * Run tests that use the HBase clients; {@link Table}.
102 * Sets up the HBase mini cluster once at start and runs through all client tests.
103 * Each creates a table named for the method and does its stuff against that.
105 * Parameterized to run with different registry implementations.
107 @Category({LargeTests
.class, ClientTests
.class})
108 @SuppressWarnings ("deprecation")
109 @RunWith(Parameterized
.class)
110 public class TestFromClientSide5
extends FromClientSideBase
{
111 private static final Logger LOG
= LoggerFactory
.getLogger(TestFromClientSide5
.class);
114 public static final HBaseClassTestRule CLASS_RULE
=
115 HBaseClassTestRule
.forClass(TestFromClientSide5
.class);
117 public TableNameTestRule name
= new TableNameTestRule();
119 // To keep the child classes happy.
120 TestFromClientSide5() {}
122 public TestFromClientSide5(Class registry
, int numHedgedReqs
) throws Exception
{
123 initialize(registry
, numHedgedReqs
, MultiRowMutationEndpoint
.class);
126 @Parameterized.Parameters
127 public static Collection
parameters() {
128 return Arrays
.asList(new Object
[][] {
129 { MasterRegistry
.class, 1},
130 { MasterRegistry
.class, 2},
131 { ZKConnectionRegistry
.class, 1}
135 @AfterClass public static void tearDownAfterClass() throws Exception
{
140 public void testGetClosestRowBefore() throws IOException
, InterruptedException
{
141 final TableName tableName
= name
.getTableName();
142 final byte[] firstRow
= Bytes
.toBytes("row111");
143 final byte[] secondRow
= Bytes
.toBytes("row222");
144 final byte[] thirdRow
= Bytes
.toBytes("row333");
145 final byte[] forthRow
= Bytes
.toBytes("row444");
146 final byte[] beforeFirstRow
= Bytes
.toBytes("row");
147 final byte[] beforeSecondRow
= Bytes
.toBytes("row22");
148 final byte[] beforeThirdRow
= Bytes
.toBytes("row33");
149 final byte[] beforeForthRow
= Bytes
.toBytes("row44");
152 TEST_UTIL
.createTable(tableName
,
153 new byte[][] { HConstants
.CATALOG_FAMILY
, Bytes
.toBytes("info2") }, 1, 1024);
154 RegionLocator locator
= TEST_UTIL
.getConnection().getRegionLocator(tableName
)) {
156 // set block size to 64 to making 2 kvs into one block, bypassing the walkForwardInSingleRow
157 // in Store.rowAtOrBeforeFromStoreFile
158 String regionName
= locator
.getAllRegionLocations().get(0).getRegion().getEncodedName();
159 HRegion region
= TEST_UTIL
.getRSForFirstRegionInTable(tableName
).getRegion(regionName
);
160 Put put1
= new Put(firstRow
);
161 Put put2
= new Put(secondRow
);
162 Put put3
= new Put(thirdRow
);
163 Put put4
= new Put(forthRow
);
164 byte[] one
= new byte[] { 1 };
165 byte[] two
= new byte[] { 2 };
166 byte[] three
= new byte[] { 3 };
167 byte[] four
= new byte[] { 4 };
169 put1
.addColumn(HConstants
.CATALOG_FAMILY
, null, one
);
170 put2
.addColumn(HConstants
.CATALOG_FAMILY
, null, two
);
171 put3
.addColumn(HConstants
.CATALOG_FAMILY
, null, three
);
172 put4
.addColumn(HConstants
.CATALOG_FAMILY
, null, four
);
181 // Test before first that null is returned
182 result
= getReverseScanResult(table
, beforeFirstRow
);
185 // Test at first that first is returned
186 result
= getReverseScanResult(table
, firstRow
);
187 assertTrue(result
.containsColumn(HConstants
.CATALOG_FAMILY
, null));
188 assertTrue(Bytes
.equals(result
.getRow(), firstRow
));
189 assertTrue(Bytes
.equals(result
.getValue(HConstants
.CATALOG_FAMILY
, null), one
));
191 // Test in between first and second that first is returned
192 result
= getReverseScanResult(table
, beforeSecondRow
);
193 assertTrue(result
.containsColumn(HConstants
.CATALOG_FAMILY
, null));
194 assertTrue(Bytes
.equals(result
.getRow(), firstRow
));
195 assertTrue(Bytes
.equals(result
.getValue(HConstants
.CATALOG_FAMILY
, null), one
));
197 // Test at second make sure second is returned
198 result
= getReverseScanResult(table
, secondRow
);
199 assertTrue(result
.containsColumn(HConstants
.CATALOG_FAMILY
, null));
200 assertTrue(Bytes
.equals(result
.getRow(), secondRow
));
201 assertTrue(Bytes
.equals(result
.getValue(HConstants
.CATALOG_FAMILY
, null), two
));
203 // Test in second and third, make sure second is returned
204 result
= getReverseScanResult(table
, beforeThirdRow
);
205 assertTrue(result
.containsColumn(HConstants
.CATALOG_FAMILY
, null));
206 assertTrue(Bytes
.equals(result
.getRow(), secondRow
));
207 assertTrue(Bytes
.equals(result
.getValue(HConstants
.CATALOG_FAMILY
, null), two
));
209 // Test at third make sure third is returned
210 result
= getReverseScanResult(table
, thirdRow
);
211 assertTrue(result
.containsColumn(HConstants
.CATALOG_FAMILY
, null));
212 assertTrue(Bytes
.equals(result
.getRow(), thirdRow
));
213 assertTrue(Bytes
.equals(result
.getValue(HConstants
.CATALOG_FAMILY
, null), three
));
215 // Test in third and forth, make sure third is returned
216 result
= getReverseScanResult(table
, beforeForthRow
);
217 assertTrue(result
.containsColumn(HConstants
.CATALOG_FAMILY
, null));
218 assertTrue(Bytes
.equals(result
.getRow(), thirdRow
));
219 assertTrue(Bytes
.equals(result
.getValue(HConstants
.CATALOG_FAMILY
, null), three
));
221 // Test at forth make sure forth is returned
222 result
= getReverseScanResult(table
, forthRow
);
223 assertTrue(result
.containsColumn(HConstants
.CATALOG_FAMILY
, null));
224 assertTrue(Bytes
.equals(result
.getRow(), forthRow
));
225 assertTrue(Bytes
.equals(result
.getValue(HConstants
.CATALOG_FAMILY
, null), four
));
227 // Test after forth make sure forth is returned
228 result
= getReverseScanResult(table
, Bytes
.add(forthRow
, one
));
229 assertTrue(result
.containsColumn(HConstants
.CATALOG_FAMILY
, null));
230 assertTrue(Bytes
.equals(result
.getRow(), forthRow
));
231 assertTrue(Bytes
.equals(result
.getValue(HConstants
.CATALOG_FAMILY
, null), four
));
235 private Result
getReverseScanResult(Table table
, byte[] row
) throws IOException
{
236 Scan scan
= new Scan().withStartRow(row
);
238 scan
.setReversed(true);
240 scan
.addFamily(HConstants
.CATALOG_FAMILY
);
241 try (ResultScanner scanner
= table
.getScanner(scan
)) {
242 return scanner
.next();
250 public void testScanVariableReuse() {
251 Scan scan
= new Scan();
252 scan
.addFamily(FAMILY
);
253 scan
.addColumn(FAMILY
, ROW
);
255 assertEquals(1, scan
.getFamilyMap().get(FAMILY
).size());
258 scan
.addFamily(FAMILY
);
260 assertNull(scan
.getFamilyMap().get(FAMILY
));
261 assertTrue(scan
.getFamilyMap().containsKey(FAMILY
));
265 public void testMultiRowMutation() throws Exception
{
266 LOG
.info("Starting testMultiRowMutation");
267 final TableName tableName
= name
.getTableName();
268 final byte [] ROW1
= Bytes
.toBytes("testRow1");
270 try (Table t
= TEST_UTIL
.createTable(tableName
, FAMILY
)) {
271 Put p
= new Put(ROW
);
272 p
.addColumn(FAMILY
, QUALIFIER
, VALUE
);
273 MutationProto m1
= ProtobufUtil
.toMutation(MutationType
.PUT
, p
);
276 p
.addColumn(FAMILY
, QUALIFIER
, VALUE
);
277 MutationProto m2
= ProtobufUtil
.toMutation(MutationType
.PUT
, p
);
279 MutateRowsRequest
.Builder mrmBuilder
= MutateRowsRequest
.newBuilder();
280 mrmBuilder
.addMutationRequest(m1
);
281 mrmBuilder
.addMutationRequest(m2
);
282 MutateRowsRequest mrm
= mrmBuilder
.build();
283 CoprocessorRpcChannel channel
= t
.coprocessorService(ROW
);
284 MultiRowMutationService
.BlockingInterface service
=
285 MultiRowMutationService
.newBlockingStub(channel
);
286 service
.mutateRows(null, mrm
);
287 Get g
= new Get(ROW
);
289 assertEquals(0, Bytes
.compareTo(VALUE
, r
.getValue(FAMILY
, QUALIFIER
)));
292 assertEquals(0, Bytes
.compareTo(VALUE
, r
.getValue(FAMILY
, QUALIFIER
)));
297 public void testRowMutation() throws Exception
{
298 LOG
.info("Starting testRowMutation");
299 final TableName tableName
= name
.getTableName();
300 try (Table t
= TEST_UTIL
.createTable(tableName
, FAMILY
)) {
301 byte[][] QUALIFIERS
= new byte[][] { Bytes
.toBytes("a"), Bytes
.toBytes("b") };
302 RowMutations arm
= new RowMutations(ROW
);
303 Put p
= new Put(ROW
);
304 p
.addColumn(FAMILY
, QUALIFIERS
[0], VALUE
);
308 Get g
= new Get(ROW
);
310 assertEquals(0, Bytes
.compareTo(VALUE
, r
.getValue(FAMILY
, QUALIFIERS
[0])));
312 arm
= new RowMutations(ROW
);
314 p
.addColumn(FAMILY
, QUALIFIERS
[1], VALUE
);
316 Delete d
= new Delete(ROW
);
317 d
.addColumns(FAMILY
, QUALIFIERS
[0]);
319 // TODO: Trying mutateRow again. The batch was failing with a one try only.
322 assertEquals(0, Bytes
.compareTo(VALUE
, r
.getValue(FAMILY
, QUALIFIERS
[1])));
323 assertNull(r
.getValue(FAMILY
, QUALIFIERS
[0]));
325 // Test that we get a region level exception
327 arm
= new RowMutations(ROW
);
329 p
.addColumn(new byte[] { 'b', 'o', 'g', 'u', 's' }, QUALIFIERS
[0], VALUE
);
332 fail("Expected NoSuchColumnFamilyException");
333 } catch (NoSuchColumnFamilyException e
) {
335 } catch (RetriesExhaustedWithDetailsException e
) {
336 for (Throwable rootCause
: e
.getCauses()) {
337 if (rootCause
instanceof NoSuchColumnFamilyException
) {
347 public void testBatchAppendWithReturnResultFalse() throws Exception
{
348 LOG
.info("Starting testBatchAppendWithReturnResultFalse");
349 final TableName tableName
= name
.getTableName();
350 try (Table table
= TEST_UTIL
.createTable(tableName
, FAMILY
)) {
351 Append append1
= new Append(Bytes
.toBytes("row1"));
352 append1
.setReturnResults(false);
353 append1
.addColumn(FAMILY
, Bytes
.toBytes("f1"), Bytes
.toBytes("value1"));
354 Append append2
= new Append(Bytes
.toBytes("row1"));
355 append2
.setReturnResults(false);
356 append2
.addColumn(FAMILY
, Bytes
.toBytes("f1"), Bytes
.toBytes("value2"));
357 List
<Append
> appends
= new ArrayList
<>();
358 appends
.add(append1
);
359 appends
.add(append2
);
360 Object
[] results
= new Object
[2];
361 table
.batch(appends
, results
);
362 assertEquals(2, results
.length
);
363 for (Object r
: results
) {
364 Result result
= (Result
) r
;
365 assertTrue(result
.isEmpty());
371 public void testAppend() throws Exception
{
372 LOG
.info("Starting testAppend");
373 final TableName tableName
= name
.getTableName();
374 try (Table t
= TEST_UTIL
.createTable(tableName
, FAMILY
)) {
375 byte[] v1
= Bytes
.toBytes("42");
376 byte[] v2
= Bytes
.toBytes("23");
377 byte[][] QUALIFIERS
= new byte[][]{
378 Bytes
.toBytes("b"), Bytes
.toBytes("a"), Bytes
.toBytes("c")
380 Append a
= new Append(ROW
);
381 a
.addColumn(FAMILY
, QUALIFIERS
[0], v1
);
382 a
.addColumn(FAMILY
, QUALIFIERS
[1], v2
);
383 a
.setReturnResults(false);
384 assertEmptyResult(t
.append(a
));
387 a
.addColumn(FAMILY
, QUALIFIERS
[0], v2
);
388 a
.addColumn(FAMILY
, QUALIFIERS
[1], v1
);
389 a
.addColumn(FAMILY
, QUALIFIERS
[2], v2
);
390 Result r
= t
.append(a
);
391 assertEquals(0, Bytes
.compareTo(Bytes
.add(v1
, v2
), r
.getValue(FAMILY
, QUALIFIERS
[0])));
392 assertEquals(0, Bytes
.compareTo(Bytes
.add(v2
, v1
), r
.getValue(FAMILY
, QUALIFIERS
[1])));
393 // QUALIFIERS[2] previously not exist, verify both value and timestamp are correct
394 assertEquals(0, Bytes
.compareTo(v2
, r
.getValue(FAMILY
, QUALIFIERS
[2])));
395 assertEquals(r
.getColumnLatestCell(FAMILY
, QUALIFIERS
[0]).getTimestamp(),
396 r
.getColumnLatestCell(FAMILY
, QUALIFIERS
[2]).getTimestamp());
399 private List
<Result
> doAppend(final boolean walUsed
) throws IOException
{
400 LOG
.info("Starting testAppend, walUsed is " + walUsed
);
401 final TableName TABLENAME
=
402 TableName
.valueOf(walUsed ?
"testAppendWithWAL" : "testAppendWithoutWAL");
403 try (Table t
= TEST_UTIL
.createTable(TABLENAME
, FAMILY
)) {
404 final byte[] row1
= Bytes
.toBytes("c");
405 final byte[] row2
= Bytes
.toBytes("b");
406 final byte[] row3
= Bytes
.toBytes("a");
407 final byte[] qual
= Bytes
.toBytes("qual");
408 Put put_0
= new Put(row2
);
409 put_0
.addColumn(FAMILY
, qual
, Bytes
.toBytes("put"));
410 Put put_1
= new Put(row3
);
411 put_1
.addColumn(FAMILY
, qual
, Bytes
.toBytes("put"));
412 Append append_0
= new Append(row1
);
413 append_0
.addColumn(FAMILY
, qual
, Bytes
.toBytes("i"));
414 Append append_1
= new Append(row1
);
415 append_1
.addColumn(FAMILY
, qual
, Bytes
.toBytes("k"));
416 Append append_2
= new Append(row1
);
417 append_2
.addColumn(FAMILY
, qual
, Bytes
.toBytes("e"));
419 append_2
.setDurability(Durability
.SKIP_WAL
);
421 Append append_3
= new Append(row1
);
422 append_3
.addColumn(FAMILY
, qual
, Bytes
.toBytes("a"));
428 List
<Result
> results
= new LinkedList
<>();
429 try (ResultScanner scanner
= t
.getScanner(s
)) {
433 for (Result r
: scanner
) {
437 TEST_UTIL
.deleteTable(TABLENAME
);
443 public void testAppendWithoutWAL() throws Exception
{
444 List
<Result
> resultsWithWal
= doAppend(true);
445 List
<Result
> resultsWithoutWal
= doAppend(false);
446 assertEquals(resultsWithWal
.size(), resultsWithoutWal
.size());
447 for (int i
= 0; i
!= resultsWithWal
.size(); ++i
) {
448 Result resultWithWal
= resultsWithWal
.get(i
);
449 Result resultWithoutWal
= resultsWithoutWal
.get(i
);
450 assertEquals(resultWithWal
.rawCells().length
, resultWithoutWal
.rawCells().length
);
451 for (int j
= 0; j
!= resultWithWal
.rawCells().length
; ++j
) {
452 Cell cellWithWal
= resultWithWal
.rawCells()[j
];
453 Cell cellWithoutWal
= resultWithoutWal
.rawCells()[j
];
454 assertArrayEquals(CellUtil
.cloneRow(cellWithWal
), CellUtil
.cloneRow(cellWithoutWal
));
455 assertArrayEquals(CellUtil
.cloneFamily(cellWithWal
), CellUtil
.cloneFamily(cellWithoutWal
));
456 assertArrayEquals(CellUtil
.cloneQualifier(cellWithWal
),
457 CellUtil
.cloneQualifier(cellWithoutWal
));
458 assertArrayEquals(CellUtil
.cloneValue(cellWithWal
), CellUtil
.cloneValue(cellWithoutWal
));
464 public void testClientPoolRoundRobin() throws IOException
{
465 final TableName tableName
= name
.getTableName();
468 int numVersions
= poolSize
* 2;
469 Configuration conf
= TEST_UTIL
.getConfiguration();
470 conf
.set(HConstants
.HBASE_CLIENT_IPC_POOL_TYPE
, "round-robin");
471 conf
.setInt(HConstants
.HBASE_CLIENT_IPC_POOL_SIZE
, poolSize
);
474 TEST_UTIL
.createTable(tableName
, new byte[][] { FAMILY
}, Integer
.MAX_VALUE
)) {
476 final long ts
= EnvironmentEdgeManager
.currentTime();
477 Get get
= new Get(ROW
);
478 get
.addColumn(FAMILY
, QUALIFIER
);
479 get
.readAllVersions();
481 for (int versions
= 1; versions
<= numVersions
; versions
++) {
482 Put put
= new Put(ROW
);
483 put
.addColumn(FAMILY
, QUALIFIER
, ts
+ versions
, VALUE
);
486 Result result
= table
.get(get
);
487 NavigableMap
<Long
, byte[]> navigableMap
= result
.getMap().get(FAMILY
)
490 assertEquals("The number of versions of '" + Bytes
.toString(FAMILY
) + ":"
491 + Bytes
.toString(QUALIFIER
) + " did not match", versions
, navigableMap
.size());
492 for (Map
.Entry
<Long
, byte[]> entry
: navigableMap
.entrySet()) {
493 assertTrue("The value at time " + entry
.getKey()
494 + " did not match what was put",
495 Bytes
.equals(VALUE
, entry
.getValue()));
501 @Ignore ("Flakey: HBASE-8989") @Test
502 public void testClientPoolThreadLocal() throws IOException
{
503 final TableName tableName
= name
.getTableName();
505 int poolSize
= Integer
.MAX_VALUE
;
507 Configuration conf
= TEST_UTIL
.getConfiguration();
508 conf
.set(HConstants
.HBASE_CLIENT_IPC_POOL_TYPE
, "thread-local");
509 conf
.setInt(HConstants
.HBASE_CLIENT_IPC_POOL_SIZE
, poolSize
);
511 try (final Table table
= TEST_UTIL
.createTable(tableName
, new byte[][] { FAMILY
}, 3)) {
513 final long ts
= EnvironmentEdgeManager
.currentTime();
514 final Get get
= new Get(ROW
);
515 get
.addColumn(FAMILY
, QUALIFIER
);
516 get
.readAllVersions();
518 for (int versions
= 1; versions
<= numVersions
; versions
++) {
519 Put put
= new Put(ROW
);
520 put
.addColumn(FAMILY
, QUALIFIER
, ts
+ versions
, VALUE
);
523 Result result
= table
.get(get
);
524 NavigableMap
<Long
, byte[]> navigableMap
= result
.getMap().get(FAMILY
)
527 assertEquals("The number of versions of '" + Bytes
.toString(FAMILY
) + ":"
528 + Bytes
.toString(QUALIFIER
) + " did not match", versions
, navigableMap
.size());
529 for (Map
.Entry
<Long
, byte[]> entry
: navigableMap
.entrySet()) {
530 assertTrue("The value at time " + entry
.getKey()
531 + " did not match what was put",
532 Bytes
.equals(VALUE
, entry
.getValue()));
536 final Object waitLock
= new Object();
537 ExecutorService executorService
= Executors
.newFixedThreadPool(numVersions
);
538 final AtomicReference
<AssertionError
> error
= new AtomicReference
<>(null);
539 for (int versions
= numVersions
; versions
< numVersions
* 2; versions
++) {
540 final int versionsCopy
= versions
;
541 executorService
.submit((Callable
<Void
>) () -> {
543 Put put
= new Put(ROW
);
544 put
.addColumn(FAMILY
, QUALIFIER
, ts
+ versionsCopy
, VALUE
);
547 Result result
= table
.get(get
);
548 NavigableMap
<Long
, byte[]> navigableMap
= result
.getMap()
549 .get(FAMILY
).get(QUALIFIER
);
551 assertEquals("The number of versions of '" + Bytes
.toString(FAMILY
) + ":"
552 + Bytes
.toString(QUALIFIER
) + " did not match " + versionsCopy
, versionsCopy
,
553 navigableMap
.size());
554 for (Map
.Entry
<Long
, byte[]> entry
: navigableMap
.entrySet()) {
555 assertTrue("The value at time " + entry
.getKey()
556 + " did not match what was put",
557 Bytes
.equals(VALUE
, entry
.getValue()));
559 synchronized (waitLock
) {
562 } catch (Exception ignored
) {
563 } catch (AssertionError e
) {
564 // the error happens in a thread, it won't fail the test,
565 // need to pass it to the caller for proper handling.
567 LOG
.error(e
.toString(), e
);
573 synchronized (waitLock
) {
574 waitLock
.notifyAll();
576 executorService
.shutdownNow();
577 assertNull(error
.get());
582 public void testCheckAndPut() throws IOException
{
583 final byte [] anotherrow
= Bytes
.toBytes("anotherrow");
584 final byte [] value2
= Bytes
.toBytes("abcd");
586 try (Table table
= TEST_UTIL
.createTable(name
.getTableName(), FAMILY
)) {
587 Put put1
= new Put(ROW
);
588 put1
.addColumn(FAMILY
, QUALIFIER
, VALUE
);
590 // row doesn't exist, so using non-null value should be considered "not match".
591 boolean ok
= table
.checkAndMutate(ROW
, FAMILY
).qualifier(QUALIFIER
)
592 .ifEquals(VALUE
).thenPut(put1
);
595 // row doesn't exist, so using "ifNotExists" should be considered "match".
596 ok
= table
.checkAndMutate(ROW
, FAMILY
).qualifier(QUALIFIER
).ifNotExists().thenPut(put1
);
599 // row now exists, so using "ifNotExists" should be considered "not match".
600 ok
= table
.checkAndMutate(ROW
, FAMILY
).qualifier(QUALIFIER
).ifNotExists().thenPut(put1
);
603 Put put2
= new Put(ROW
);
604 put2
.addColumn(FAMILY
, QUALIFIER
, value2
);
606 // row now exists, use the matching value to check
607 ok
= table
.checkAndMutate(ROW
, FAMILY
).qualifier(QUALIFIER
).ifEquals(VALUE
).thenPut(put2
);
610 Put put3
= new Put(anotherrow
);
611 put3
.addColumn(FAMILY
, QUALIFIER
, VALUE
);
613 // try to do CheckAndPut on different rows
615 table
.checkAndMutate(ROW
, FAMILY
).qualifier(QUALIFIER
).ifEquals(value2
).thenPut(put3
);
616 fail("trying to check and modify different rows should have failed.");
617 } catch (Exception ignored
) {
623 public void testCheckAndMutateWithTimeRange() throws IOException
{
624 try (Table table
= TEST_UTIL
.createTable(name
.getTableName(), FAMILY
)) {
625 final long ts
= System
.currentTimeMillis() / 2;
626 Put put
= new Put(ROW
);
627 put
.addColumn(FAMILY
, QUALIFIER
, ts
, VALUE
);
629 boolean ok
= table
.checkAndMutate(ROW
, FAMILY
).qualifier(QUALIFIER
)
634 ok
= table
.checkAndMutate(ROW
, FAMILY
).qualifier(QUALIFIER
)
635 .timeRange(TimeRange
.at(ts
+ 10000))
640 ok
= table
.checkAndMutate(ROW
, FAMILY
).qualifier(QUALIFIER
)
641 .timeRange(TimeRange
.from(ts
+ 10000))
646 ok
= table
.checkAndMutate(ROW
, FAMILY
).qualifier(QUALIFIER
)
647 .timeRange(TimeRange
.between(ts
+ 10000, ts
+ 20000))
652 ok
= table
.checkAndMutate(ROW
, FAMILY
).qualifier(QUALIFIER
)
653 .timeRange(TimeRange
.until(ts
))
658 ok
= table
.checkAndMutate(ROW
, FAMILY
).qualifier(QUALIFIER
)
659 .timeRange(TimeRange
.at(ts
))
664 ok
= table
.checkAndMutate(ROW
, FAMILY
).qualifier(QUALIFIER
)
665 .timeRange(TimeRange
.from(ts
))
670 ok
= table
.checkAndMutate(ROW
, FAMILY
).qualifier(QUALIFIER
)
671 .timeRange(TimeRange
.between(ts
, ts
+ 20000))
676 ok
= table
.checkAndMutate(ROW
, FAMILY
).qualifier(QUALIFIER
)
677 .timeRange(TimeRange
.until(ts
+ 10000))
682 RowMutations rm
= new RowMutations(ROW
)
683 .add((Mutation
) put
);
684 ok
= table
.checkAndMutate(ROW
, FAMILY
).qualifier(QUALIFIER
)
685 .timeRange(TimeRange
.at(ts
+ 10000))
690 ok
= table
.checkAndMutate(ROW
, FAMILY
).qualifier(QUALIFIER
)
691 .timeRange(TimeRange
.at(ts
))
696 Delete delete
= new Delete(ROW
)
697 .addColumn(FAMILY
, QUALIFIER
);
699 ok
= table
.checkAndMutate(ROW
, FAMILY
).qualifier(QUALIFIER
)
700 .timeRange(TimeRange
.at(ts
+ 10000))
705 ok
= table
.checkAndMutate(ROW
, FAMILY
).qualifier(QUALIFIER
)
706 .timeRange(TimeRange
.at(ts
))
714 public void testCheckAndPutWithCompareOp() throws IOException
{
715 final byte [] value1
= Bytes
.toBytes("aaaa");
716 final byte [] value2
= Bytes
.toBytes("bbbb");
717 final byte [] value3
= Bytes
.toBytes("cccc");
718 final byte [] value4
= Bytes
.toBytes("dddd");
720 try (Table table
= TEST_UTIL
.createTable(name
.getTableName(), FAMILY
)) {
722 Put put2
= new Put(ROW
);
723 put2
.addColumn(FAMILY
, QUALIFIER
, value2
);
725 Put put3
= new Put(ROW
);
726 put3
.addColumn(FAMILY
, QUALIFIER
, value3
);
728 // row doesn't exist, so using "ifNotExists" should be considered "match".
730 table
.checkAndMutate(ROW
, FAMILY
).qualifier(QUALIFIER
).ifNotExists().thenPut(put2
);
733 // cell = "bbbb", using "aaaa" to compare only LESS/LESS_OR_EQUAL/NOT_EQUAL
735 ok
= table
.checkAndMutate(ROW
, FAMILY
).qualifier(QUALIFIER
)
736 .ifMatches(CompareOperator
.GREATER
, value1
).thenPut(put2
);
738 ok
= table
.checkAndMutate(ROW
, FAMILY
).qualifier(QUALIFIER
)
739 .ifMatches(CompareOperator
.EQUAL
, value1
).thenPut(put2
);
741 ok
= table
.checkAndMutate(ROW
, FAMILY
).qualifier(QUALIFIER
)
742 .ifMatches(CompareOperator
.GREATER_OR_EQUAL
, value1
).thenPut(put2
);
744 ok
= table
.checkAndMutate(ROW
, FAMILY
).qualifier(QUALIFIER
)
745 .ifMatches(CompareOperator
.LESS
, value1
).thenPut(put2
);
747 ok
= table
.checkAndMutate(ROW
, FAMILY
).qualifier(QUALIFIER
)
748 .ifMatches(CompareOperator
.LESS_OR_EQUAL
, value1
).thenPut(put2
);
750 ok
= table
.checkAndMutate(ROW
, FAMILY
).qualifier(QUALIFIER
)
751 .ifMatches(CompareOperator
.NOT_EQUAL
, value1
).thenPut(put3
);
754 // cell = "cccc", using "dddd" to compare only LARGER/LARGER_OR_EQUAL/NOT_EQUAL
756 ok
= table
.checkAndMutate(ROW
, FAMILY
).qualifier(QUALIFIER
)
757 .ifMatches(CompareOperator
.LESS
, value4
).thenPut(put3
);
759 ok
= table
.checkAndMutate(ROW
, FAMILY
).qualifier(QUALIFIER
)
760 .ifMatches(CompareOperator
.LESS_OR_EQUAL
, value4
).thenPut(put3
);
762 ok
= table
.checkAndMutate(ROW
, FAMILY
).qualifier(QUALIFIER
)
763 .ifMatches(CompareOperator
.EQUAL
, value4
).thenPut(put3
);
765 ok
= table
.checkAndMutate(ROW
, FAMILY
).qualifier(QUALIFIER
)
766 .ifMatches(CompareOperator
.GREATER
, value4
).thenPut(put3
);
768 ok
= table
.checkAndMutate(ROW
, FAMILY
).qualifier(QUALIFIER
)
769 .ifMatches(CompareOperator
.GREATER_OR_EQUAL
, value4
).thenPut(put3
);
771 ok
= table
.checkAndMutate(ROW
, FAMILY
).qualifier(QUALIFIER
)
772 .ifMatches(CompareOperator
.NOT_EQUAL
, value4
).thenPut(put2
);
775 // cell = "bbbb", using "bbbb" to compare only GREATER_OR_EQUAL/LESS_OR_EQUAL/EQUAL
777 ok
= table
.checkAndMutate(ROW
, FAMILY
).qualifier(QUALIFIER
)
778 .ifMatches(CompareOperator
.GREATER
, value2
).thenPut(put2
);
780 ok
= table
.checkAndMutate(ROW
, FAMILY
).qualifier(QUALIFIER
)
781 .ifMatches(CompareOperator
.NOT_EQUAL
, value2
).thenPut(put2
);
783 ok
= table
.checkAndMutate(ROW
, FAMILY
).qualifier(QUALIFIER
)
784 .ifMatches(CompareOperator
.LESS
, value2
).thenPut(put2
);
786 ok
= table
.checkAndMutate(ROW
, FAMILY
).qualifier(QUALIFIER
)
787 .ifMatches(CompareOperator
.GREATER_OR_EQUAL
, value2
).thenPut(put2
);
789 ok
= table
.checkAndMutate(ROW
, FAMILY
).qualifier(QUALIFIER
)
790 .ifMatches(CompareOperator
.LESS_OR_EQUAL
, value2
).thenPut(put2
);
792 ok
= table
.checkAndMutate(ROW
, FAMILY
).qualifier(QUALIFIER
)
793 .ifMatches(CompareOperator
.EQUAL
, value2
).thenPut(put3
);
799 public void testCheckAndDelete() throws IOException
{
800 final byte [] value1
= Bytes
.toBytes("aaaa");
802 try (Table table
= TEST_UTIL
.createTable(name
.getTableName(),
805 Put put
= new Put(ROW
);
806 put
.addColumn(FAMILY
, QUALIFIER
, value1
);
809 Delete delete
= new Delete(ROW
);
810 delete
.addColumns(FAMILY
, QUALIFIER
);
812 boolean ok
= table
.checkAndMutate(ROW
, FAMILY
).qualifier(QUALIFIER
)
813 .ifEquals(value1
).thenDelete(delete
);
819 public void testCheckAndDeleteWithCompareOp() throws IOException
{
820 final byte [] value1
= Bytes
.toBytes("aaaa");
821 final byte [] value2
= Bytes
.toBytes("bbbb");
822 final byte [] value3
= Bytes
.toBytes("cccc");
823 final byte [] value4
= Bytes
.toBytes("dddd");
825 try (Table table
= TEST_UTIL
.createTable(name
.getTableName(),
828 Put put2
= new Put(ROW
);
829 put2
.addColumn(FAMILY
, QUALIFIER
, value2
);
832 Put put3
= new Put(ROW
);
833 put3
.addColumn(FAMILY
, QUALIFIER
, value3
);
835 Delete delete
= new Delete(ROW
);
836 delete
.addColumns(FAMILY
, QUALIFIER
);
838 // cell = "bbbb", using "aaaa" to compare only LESS/LESS_OR_EQUAL/NOT_EQUAL
840 boolean ok
= table
.checkAndMutate(ROW
, FAMILY
).qualifier(QUALIFIER
)
841 .ifMatches(CompareOperator
.GREATER
, value1
).thenDelete(delete
);
843 ok
= table
.checkAndMutate(ROW
, FAMILY
).qualifier(QUALIFIER
)
844 .ifMatches(CompareOperator
.EQUAL
, value1
).thenDelete(delete
);
846 ok
= table
.checkAndMutate(ROW
, FAMILY
).qualifier(QUALIFIER
)
847 .ifMatches(CompareOperator
.GREATER_OR_EQUAL
, value1
).thenDelete(delete
);
849 ok
= table
.checkAndMutate(ROW
, FAMILY
).qualifier(QUALIFIER
)
850 .ifMatches(CompareOperator
.LESS
, value1
).thenDelete(delete
);
853 ok
= table
.checkAndMutate(ROW
, FAMILY
).qualifier(QUALIFIER
)
854 .ifMatches(CompareOperator
.LESS_OR_EQUAL
, value1
).thenDelete(delete
);
857 ok
= table
.checkAndMutate(ROW
, FAMILY
).qualifier(QUALIFIER
)
858 .ifMatches(CompareOperator
.NOT_EQUAL
, value1
).thenDelete(delete
);
861 // cell = "cccc", using "dddd" to compare only LARGER/LARGER_OR_EQUAL/NOT_EQUAL
864 ok
= table
.checkAndMutate(ROW
, FAMILY
).qualifier(QUALIFIER
)
865 .ifMatches(CompareOperator
.LESS
, value4
).thenDelete(delete
);
867 ok
= table
.checkAndMutate(ROW
, FAMILY
).qualifier(QUALIFIER
)
868 .ifMatches(CompareOperator
.LESS_OR_EQUAL
, value4
).thenDelete(delete
);
870 ok
= table
.checkAndMutate(ROW
, FAMILY
).qualifier(QUALIFIER
)
871 .ifMatches(CompareOperator
.EQUAL
, value4
).thenDelete(delete
);
873 ok
= table
.checkAndMutate(ROW
, FAMILY
).qualifier(QUALIFIER
)
874 .ifMatches(CompareOperator
.GREATER
, value4
).thenDelete(delete
);
877 ok
= table
.checkAndMutate(ROW
, FAMILY
).qualifier(QUALIFIER
)
878 .ifMatches(CompareOperator
.GREATER_OR_EQUAL
, value4
).thenDelete(delete
);
881 ok
= table
.checkAndMutate(ROW
, FAMILY
).qualifier(QUALIFIER
)
882 .ifMatches(CompareOperator
.NOT_EQUAL
, value4
).thenDelete(delete
);
885 // cell = "bbbb", using "bbbb" to compare only GREATER_OR_EQUAL/LESS_OR_EQUAL/EQUAL
888 ok
= table
.checkAndMutate(ROW
, FAMILY
).qualifier(QUALIFIER
)
889 .ifMatches(CompareOperator
.GREATER
, value2
).thenDelete(delete
);
891 ok
= table
.checkAndMutate(ROW
, FAMILY
).qualifier(QUALIFIER
)
892 .ifMatches(CompareOperator
.NOT_EQUAL
, value2
).thenDelete(delete
);
894 ok
= table
.checkAndMutate(ROW
, FAMILY
).qualifier(QUALIFIER
)
895 .ifMatches(CompareOperator
.LESS
, value2
).thenDelete(delete
);
897 ok
= table
.checkAndMutate(ROW
, FAMILY
).qualifier(QUALIFIER
)
898 .ifMatches(CompareOperator
.GREATER_OR_EQUAL
, value2
).thenDelete(delete
);
901 ok
= table
.checkAndMutate(ROW
, FAMILY
).qualifier(QUALIFIER
)
902 .ifMatches(CompareOperator
.LESS_OR_EQUAL
, value2
).thenDelete(delete
);
905 ok
= table
.checkAndMutate(ROW
, FAMILY
).qualifier(QUALIFIER
)
906 .ifMatches(CompareOperator
.EQUAL
, value2
).thenDelete(delete
);
915 @SuppressWarnings({"unused", "checkstyle:EmptyBlock"})
916 public void testScanMetrics() throws Exception
{
917 final TableName tableName
= name
.getTableName();
919 // Set up test table:
921 try (Table ht
= TEST_UTIL
.createMultiRegionTable(tableName
, FAMILY
)) {
923 try (RegionLocator r
= TEST_UTIL
.getConnection().getRegionLocator(tableName
)) {
924 numOfRegions
= r
.getStartKeys().length
;
926 // Create 3 rows in the table, with rowkeys starting with "zzz*" so that
927 // scan are forced to hit all the regions.
928 Put put1
= new Put(Bytes
.toBytes("zzz1"));
929 put1
.addColumn(FAMILY
, QUALIFIER
, VALUE
);
930 Put put2
= new Put(Bytes
.toBytes("zzz2"));
931 put2
.addColumn(FAMILY
, QUALIFIER
, VALUE
);
932 Put put3
= new Put(Bytes
.toBytes("zzz3"));
933 put3
.addColumn(FAMILY
, QUALIFIER
, VALUE
);
934 ht
.put(Arrays
.asList(put1
, put2
, put3
));
936 Scan scan1
= new Scan();
938 try (ResultScanner scanner
= ht
.getScanner(scan1
)) {
939 for (Result result
: scanner
) {
943 LOG
.info("test data has " + numRecords
+ " records.");
945 // by default, scan metrics collection is turned off
946 assertNull(scanner
.getScanMetrics());
949 // turn on scan metrics
950 Scan scan2
= new Scan();
951 scan2
.setScanMetricsEnabled(true);
952 scan2
.setCaching(numRecords
+ 1);
953 try (ResultScanner scanner
= ht
.getScanner(scan2
)) {
954 for (Result result
: scanner
.next(numRecords
- 1)) {
957 // closing the scanner will set the metrics.
958 assertNotNull(scanner
.getScanMetrics());
961 // set caching to 1, because metrics are collected in each roundtrip only
963 scan2
.setScanMetricsEnabled(true);
965 try (ResultScanner scanner
= ht
.getScanner(scan2
)) {
966 // per HBASE-5717, this should still collect even if you don't run all the way to
967 // the end of the scanner. So this is asking for 2 of the 3 rows we inserted.
968 for (Result result
: scanner
.next(numRecords
- 1)) {
970 ScanMetrics scanMetrics
= scanner
.getScanMetrics();
971 assertEquals("Did not access all the regions in the table", numOfRegions
,
972 scanMetrics
.countOfRegions
.get());
975 // check byte counters
977 scan2
.setScanMetricsEnabled(true);
979 try (ResultScanner scanner
= ht
.getScanner(scan2
)) {
981 for (Result result
: scanner
.next(1)) {
982 for (Cell cell
: result
.listCells()) {
983 numBytes
+= PrivateCellUtil
.estimatedSerializedSizeOf(cell
);
987 ScanMetrics scanMetrics
= scanner
.getScanMetrics();
988 assertEquals("Did not count the result bytes", numBytes
,
989 scanMetrics
.countOfBytesInResults
.get());
992 // check byte counters on a small scan
994 scan2
.setScanMetricsEnabled(true);
996 scan2
.setSmall(true);
997 try (ResultScanner scanner
= ht
.getScanner(scan2
)) {
999 for (Result result
: scanner
.next(1)) {
1000 for (Cell cell
: result
.listCells()) {
1001 numBytes
+= PrivateCellUtil
.estimatedSerializedSizeOf(cell
);
1005 ScanMetrics scanMetrics
= scanner
.getScanMetrics();
1006 assertEquals("Did not count the result bytes", numBytes
,
1007 scanMetrics
.countOfBytesInResults
.get());
1010 // now, test that the metrics are still collected even if you don't call close, but do
1011 // run past the end of all the records
1012 /** There seems to be a timing issue here. Comment out for now. Fix when time.
1013 Scan scanWithoutClose = new Scan();
1014 scanWithoutClose.setCaching(1);
1015 scanWithoutClose.setScanMetricsEnabled(true);
1016 ResultScanner scannerWithoutClose = ht.getScanner(scanWithoutClose);
1017 for (Result result : scannerWithoutClose.next(numRecords + 1)) {
1019 ScanMetrics scanMetricsWithoutClose = getScanMetrics(scanWithoutClose);
1020 assertEquals("Did not access all the regions in the table", numOfRegions,
1021 scanMetricsWithoutClose.countOfRegions.get());
1025 // test that the metrics are collected correctly if you both run past all the records,
1026 // AND close the scanner
1027 Scan scanWithClose
= new Scan();
1028 // make sure we can set caching up to the number of a scanned values
1029 scanWithClose
.setCaching(numRecords
);
1030 scanWithClose
.setScanMetricsEnabled(true);
1031 try (ResultScanner scannerWithClose
= ht
.getScanner(scanWithClose
)) {
1032 for (Result result
: scannerWithClose
.next(numRecords
+ 1)) {
1034 scannerWithClose
.close();
1035 ScanMetrics scanMetricsWithClose
= scannerWithClose
.getScanMetrics();
1036 assertEquals("Did not access all the regions in the table", numOfRegions
,
1037 scanMetricsWithClose
.countOfRegions
.get());
1043 * Tests that cache on write works all the way up from the client-side.
1045 * Performs inserts, flushes, and compactions, verifying changes in the block
1046 * cache along the way.
1049 public void testCacheOnWriteEvictOnClose() throws Exception
{
1050 final TableName tableName
= name
.getTableName();
1051 byte [] data
= Bytes
.toBytes("data");
1052 try (Table table
= TEST_UTIL
.createTable(tableName
, FAMILY
)) {
1053 try (RegionLocator locator
= TEST_UTIL
.getConnection().getRegionLocator(tableName
)) {
1054 // get the block cache and region
1055 String regionName
= locator
.getAllRegionLocations().get(0).getRegion().getEncodedName();
1057 HRegion region
= TEST_UTIL
.getRSForFirstRegionInTable(tableName
)
1058 .getRegion(regionName
);
1059 HStore store
= region
.getStores().iterator().next();
1060 CacheConfig cacheConf
= store
.getCacheConfig();
1061 cacheConf
.setCacheDataOnWrite(true);
1062 cacheConf
.setEvictOnClose(true);
1063 BlockCache cache
= cacheConf
.getBlockCache().get();
1065 // establish baseline stats
1066 long startBlockCount
= cache
.getBlockCount();
1067 long startBlockHits
= cache
.getStats().getHitCount();
1068 long startBlockMiss
= cache
.getStats().getMissCount();
1070 // wait till baseline is stable, (minimal 500 ms)
1071 for (int i
= 0; i
< 5; i
++) {
1073 if (startBlockCount
!= cache
.getBlockCount()
1074 || startBlockHits
!= cache
.getStats().getHitCount()
1075 || startBlockMiss
!= cache
.getStats().getMissCount()) {
1076 startBlockCount
= cache
.getBlockCount();
1077 startBlockHits
= cache
.getStats().getHitCount();
1078 startBlockMiss
= cache
.getStats().getMissCount();
1084 Put put
= new Put(ROW
);
1085 put
.addColumn(FAMILY
, QUALIFIER
, data
);
1087 assertTrue(Bytes
.equals(table
.get(new Get(ROW
)).value(), data
));
1089 // data was in memstore so don't expect any changes
1090 assertEquals(startBlockCount
, cache
.getBlockCount());
1091 assertEquals(startBlockHits
, cache
.getStats().getHitCount());
1092 assertEquals(startBlockMiss
, cache
.getStats().getMissCount());
1095 LOG
.debug("Flushing cache");
1098 // expect two more blocks in cache - DATA and ROOT_INDEX
1099 // , no change in hits/misses
1100 long expectedBlockCount
= startBlockCount
+ 2;
1101 long expectedBlockHits
= startBlockHits
;
1102 long expectedBlockMiss
= startBlockMiss
;
1103 assertEquals(expectedBlockCount
, cache
.getBlockCount());
1104 assertEquals(expectedBlockHits
, cache
.getStats().getHitCount());
1105 assertEquals(expectedBlockMiss
, cache
.getStats().getMissCount());
1106 // read the data and expect same blocks, one new hit, no misses
1107 assertTrue(Bytes
.equals(table
.get(new Get(ROW
)).value(), data
));
1108 assertEquals(expectedBlockCount
, cache
.getBlockCount());
1109 assertEquals(++expectedBlockHits
, cache
.getStats().getHitCount());
1110 assertEquals(expectedBlockMiss
, cache
.getStats().getMissCount());
1111 // insert a second column, read the row, no new blocks, one new hit
1112 byte[] QUALIFIER2
= Bytes
.add(QUALIFIER
, QUALIFIER
);
1113 byte[] data2
= Bytes
.add(data
, data
);
1115 put
.addColumn(FAMILY
, QUALIFIER2
, data2
);
1117 Result r
= table
.get(new Get(ROW
));
1118 assertTrue(Bytes
.equals(r
.getValue(FAMILY
, QUALIFIER
), data
));
1119 assertTrue(Bytes
.equals(r
.getValue(FAMILY
, QUALIFIER2
), data2
));
1120 assertEquals(expectedBlockCount
, cache
.getBlockCount());
1121 assertEquals(++expectedBlockHits
, cache
.getStats().getHitCount());
1122 assertEquals(expectedBlockMiss
, cache
.getStats().getMissCount());
1123 // flush, one new block
1124 System
.out
.println("Flushing cache");
1127 // + 1 for Index Block, +1 for data block
1128 expectedBlockCount
+= 2;
1129 assertEquals(expectedBlockCount
, cache
.getBlockCount());
1130 assertEquals(expectedBlockHits
, cache
.getStats().getHitCount());
1131 assertEquals(expectedBlockMiss
, cache
.getStats().getMissCount());
1132 // compact, net minus two blocks, two hits, no misses
1133 System
.out
.println("Compacting");
1134 assertEquals(2, store
.getStorefilesCount());
1135 store
.triggerMajorCompaction();
1136 region
.compact(true);
1137 store
.closeAndArchiveCompactedFiles();
1138 waitForStoreFileCount(store
, 1, 10000); // wait 10 seconds max
1139 assertEquals(1, store
.getStorefilesCount());
1140 // evicted two data blocks and two index blocks and compaction does not cache new blocks
1141 expectedBlockCount
= 0;
1142 assertEquals(expectedBlockCount
, cache
.getBlockCount());
1143 expectedBlockHits
+= 2;
1144 assertEquals(expectedBlockMiss
, cache
.getStats().getMissCount());
1145 assertEquals(expectedBlockHits
, cache
.getStats().getHitCount());
1146 // read the row, this should be a cache miss because we don't cache data
1147 // blocks on compaction
1148 r
= table
.get(new Get(ROW
));
1149 assertTrue(Bytes
.equals(r
.getValue(FAMILY
, QUALIFIER
), data
));
1150 assertTrue(Bytes
.equals(r
.getValue(FAMILY
, QUALIFIER2
), data2
));
1151 expectedBlockCount
+= 1; // cached one data block
1152 assertEquals(expectedBlockCount
, cache
.getBlockCount());
1153 assertEquals(expectedBlockHits
, cache
.getStats().getHitCount());
1154 assertEquals(++expectedBlockMiss
, cache
.getStats().getMissCount());
1159 private void waitForStoreFileCount(HStore store
, int count
, int timeout
)
1160 throws InterruptedException
{
1161 long start
= System
.currentTimeMillis();
1162 while (start
+ timeout
> System
.currentTimeMillis() && store
.getStorefilesCount() != count
) {
1165 System
.out
.println("start=" + start
+ ", now=" + System
.currentTimeMillis() + ", cur=" +
1166 store
.getStorefilesCount());
1167 assertEquals(count
, store
.getStorefilesCount());
1171 * Tests the non cached version of getRegionLocator by moving a region.
1174 public void testNonCachedGetRegionLocation() throws Exception
{
1175 // Test Initialization.
1176 final TableName tableName
= name
.getTableName();
1177 byte [] family1
= Bytes
.toBytes("f1");
1178 byte [] family2
= Bytes
.toBytes("f2");
1179 try (Table ignored
= TEST_UTIL
.createTable(tableName
, new byte[][] {family1
, family2
}, 10);
1180 Admin admin
= TEST_UTIL
.getAdmin();
1181 RegionLocator locator
= TEST_UTIL
.getConnection().getRegionLocator(tableName
)) {
1182 List
<HRegionLocation
> allRegionLocations
= locator
.getAllRegionLocations();
1183 assertEquals(1, allRegionLocations
.size());
1184 RegionInfo regionInfo
= allRegionLocations
.get(0).getRegion();
1185 ServerName addrBefore
= allRegionLocations
.get(0).getServerName();
1186 // Verify region location before move.
1187 HRegionLocation addrCache
= locator
.getRegionLocation(regionInfo
.getStartKey(), false);
1188 HRegionLocation addrNoCache
= locator
.getRegionLocation(regionInfo
.getStartKey(), true);
1190 assertEquals(addrBefore
.getPort(), addrCache
.getPort());
1191 assertEquals(addrBefore
.getPort(), addrNoCache
.getPort());
1194 // Make sure more than one server.
1195 if (TEST_UTIL
.getMiniHBaseCluster().getLiveRegionServerThreads().size() <= 1) {
1196 TEST_UTIL
.getMiniHBaseCluster().startRegionServer();
1197 Waiter
.waitFor(TEST_UTIL
.getConfiguration(), 30000, new Waiter
.Predicate
<Exception
>() {
1198 @Override public boolean evaluate() throws Exception
{
1199 return TEST_UTIL
.getMiniHBaseCluster().getLiveRegionServerThreads().size() > 1;
1204 ServerName addrAfter
= null;
1205 // Now move the region to a different server.
1206 for (int i
= 0; i
< TEST_UTIL
.getMiniHBaseCluster().getLiveRegionServerThreads().size();
1208 HRegionServer regionServer
= TEST_UTIL
.getHBaseCluster().getRegionServer(i
);
1209 ServerName addr
= regionServer
.getServerName();
1210 if (addr
.getPort() != addrBefore
.getPort()) {
1211 admin
.move(regionInfo
.getEncodedNameAsBytes(), addr
);
1212 // Wait for the region to move.
1219 // Verify the region was moved.
1220 addrCache
= locator
.getRegionLocation(regionInfo
.getStartKey(), false);
1221 addrNoCache
= locator
.getRegionLocation(regionInfo
.getStartKey(), true);
1222 assertNotNull(addrAfter
);
1223 assertTrue(addrAfter
.getPort() != addrCache
.getPort());
1224 assertEquals(addrAfter
.getPort(), addrNoCache
.getPort());
1229 * Tests getRegionsInRange by creating some regions over which a range of
1230 * keys spans; then changing the key range.
1233 public void testGetRegionsInRange() throws Exception
{
1234 // Test Initialization.
1235 byte [] startKey
= Bytes
.toBytes("ddc");
1236 byte [] endKey
= Bytes
.toBytes("mmm");
1237 TableName tableName
= name
.getTableName();
1238 TEST_UTIL
.createMultiRegionTable(tableName
, new byte[][] { FAMILY
}, 10);
1241 try (RegionLocator r
= TEST_UTIL
.getConnection().getRegionLocator(tableName
)) {
1242 numOfRegions
= r
.getStartKeys().length
;
1244 assertEquals(26, numOfRegions
);
1246 // Get the regions in this range
1247 List
<HRegionLocation
> regionsList
= getRegionsInRange(tableName
, startKey
, endKey
);
1248 assertEquals(10, regionsList
.size());
1250 // Change the start key
1251 startKey
= Bytes
.toBytes("fff");
1252 regionsList
= getRegionsInRange(tableName
, startKey
, endKey
);
1253 assertEquals(7, regionsList
.size());
1255 // Change the end key
1256 endKey
= Bytes
.toBytes("nnn");
1257 regionsList
= getRegionsInRange(tableName
, startKey
, endKey
);
1258 assertEquals(8, regionsList
.size());
1261 regionsList
= getRegionsInRange(tableName
, HConstants
.EMPTY_START_ROW
, endKey
);
1262 assertEquals(13, regionsList
.size());
1265 regionsList
= getRegionsInRange(tableName
, startKey
, HConstants
.EMPTY_END_ROW
);
1266 assertEquals(21, regionsList
.size());
1268 // Both start and end keys empty
1269 regionsList
= getRegionsInRange(tableName
, HConstants
.EMPTY_START_ROW
,
1270 HConstants
.EMPTY_END_ROW
);
1271 assertEquals(26, regionsList
.size());
1273 // Change the end key to somewhere in the last block
1274 endKey
= Bytes
.toBytes("zzz1");
1275 regionsList
= getRegionsInRange(tableName
, startKey
, endKey
);
1276 assertEquals(21, regionsList
.size());
1278 // Change the start key to somewhere in the first block
1279 startKey
= Bytes
.toBytes("aac");
1280 regionsList
= getRegionsInRange(tableName
, startKey
, endKey
);
1281 assertEquals(26, regionsList
.size());
1283 // Make start and end key the same
1284 startKey
= Bytes
.toBytes("ccc");
1285 endKey
= Bytes
.toBytes("ccc");
1286 regionsList
= getRegionsInRange(tableName
, startKey
, endKey
);
1287 assertEquals(1, regionsList
.size());
1290 private List
<HRegionLocation
> getRegionsInRange(TableName tableName
, byte[] startKey
,
1291 byte[] endKey
) throws IOException
{
1292 List
<HRegionLocation
> regionsInRange
= new ArrayList
<>();
1293 byte[] currentKey
= startKey
;
1294 final boolean endKeyIsEndOfTable
= Bytes
.equals(endKey
, HConstants
.EMPTY_END_ROW
);
1295 try (RegionLocator r
= TEST_UTIL
.getConnection().getRegionLocator(tableName
)) {
1297 HRegionLocation regionLocation
= r
.getRegionLocation(currentKey
);
1298 regionsInRange
.add(regionLocation
);
1299 currentKey
= regionLocation
.getRegion().getEndKey();
1300 } while (!Bytes
.equals(currentKey
, HConstants
.EMPTY_END_ROW
)
1301 && (endKeyIsEndOfTable
|| Bytes
.compareTo(currentKey
, endKey
) < 0));
1302 return regionsInRange
;
1307 public void testJira6912() throws Exception
{
1308 final TableName tableName
= name
.getTableName();
1309 try (Table foo
= TEST_UTIL
.createTable(tableName
, new byte[][] {FAMILY
}, 10)) {
1311 List
<Put
> puts
= new ArrayList
<>();
1312 for (int i
= 0; i
!= 100; i
++) {
1313 Put put
= new Put(Bytes
.toBytes(i
));
1314 put
.addColumn(FAMILY
, FAMILY
, Bytes
.toBytes(i
));
1318 // If i comment this out it works
1321 Scan scan
= new Scan();
1322 scan
.withStartRow(Bytes
.toBytes(1));
1323 scan
.setStopRow(Bytes
.toBytes(3));
1324 scan
.addColumn(FAMILY
, FAMILY
);
1325 scan
.setFilter(new RowFilter(CompareOperator
.NOT_EQUAL
,
1326 new BinaryComparator(Bytes
.toBytes(1))));
1328 try (ResultScanner scanner
= foo
.getScanner(scan
)) {
1329 Result
[] bar
= scanner
.next(100);
1330 assertEquals(1, bar
.length
);
1336 public void testScan_NullQualifier() throws IOException
{
1337 try (Table table
= TEST_UTIL
.createTable(name
.getTableName(), FAMILY
)) {
1338 Put put
= new Put(ROW
);
1339 put
.addColumn(FAMILY
, QUALIFIER
, VALUE
);
1343 put
.addColumn(FAMILY
, null, VALUE
);
1345 LOG
.info("Row put");
1347 Scan scan
= new Scan();
1348 scan
.addColumn(FAMILY
, null);
1350 ResultScanner scanner
= table
.getScanner(scan
);
1351 Result
[] bar
= scanner
.next(100);
1352 assertEquals(1, bar
.length
);
1353 assertEquals(1, bar
[0].size());
1356 scan
.addFamily(FAMILY
);
1358 scanner
= table
.getScanner(scan
);
1359 bar
= scanner
.next(100);
1360 assertEquals(1, bar
.length
);
1361 assertEquals(2, bar
[0].size());
1366 public void testNegativeTimestamp() throws IOException
{
1367 try (Table table
= TEST_UTIL
.createTable(name
.getTableName(), FAMILY
)) {
1370 Put put
= new Put(ROW
, -1);
1371 put
.addColumn(FAMILY
, QUALIFIER
, VALUE
);
1373 fail("Negative timestamps should not have been allowed");
1374 } catch (IllegalArgumentException ex
) {
1375 assertTrue(ex
.getMessage().contains("negative"));
1379 Put put
= new Put(ROW
);
1381 put
.addColumn(FAMILY
, QUALIFIER
, ts
, VALUE
);
1383 fail("Negative timestamps should not have been allowed");
1384 } catch (IllegalArgumentException ex
) {
1385 assertTrue(ex
.getMessage().contains("negative"));
1389 Delete delete
= new Delete(ROW
, -1);
1390 table
.delete(delete
);
1391 fail("Negative timestamps should not have been allowed");
1392 } catch (IllegalArgumentException ex
) {
1393 assertTrue(ex
.getMessage().contains("negative"));
1397 Delete delete
= new Delete(ROW
);
1398 delete
.addFamily(FAMILY
, -1);
1399 table
.delete(delete
);
1400 fail("Negative timestamps should not have been allowed");
1401 } catch (IllegalArgumentException ex
) {
1402 assertTrue(ex
.getMessage().contains("negative"));
1406 Scan scan
= new Scan();
1407 scan
.setTimeRange(-1, 1);
1408 table
.getScanner(scan
);
1409 fail("Negative timestamps should not have been allowed");
1410 } catch (IllegalArgumentException ex
) {
1411 assertTrue(ex
.getMessage().contains("negative"));
1414 // KeyValue should allow negative timestamps for backwards compat. Otherwise, if the user
1415 // already has negative timestamps in cluster data, HBase won't be able to handle that
1417 new KeyValue(Bytes
.toBytes(42), Bytes
.toBytes(42), Bytes
.toBytes(42), -1,
1419 } catch (IllegalArgumentException ex
) {
1420 fail("KeyValue SHOULD allow negative timestamps");
1427 public void testRawScanRespectsVersions() throws Exception
{
1428 final TableName tableName
= name
.getTableName();
1429 try (Table table
= TEST_UTIL
.createTable(tableName
, FAMILY
)) {
1430 byte[] row
= Bytes
.toBytes("row");
1432 // put the same row 4 times, with different values
1433 Put p
= new Put(row
);
1434 p
.addColumn(FAMILY
, QUALIFIER
, 10, VALUE
);
1437 p
.addColumn(FAMILY
, QUALIFIER
, 11, ArrayUtils
.add(VALUE
, (byte) 2));
1441 p
.addColumn(FAMILY
, QUALIFIER
, 12, ArrayUtils
.add(VALUE
, (byte) 3));
1445 p
.addColumn(FAMILY
, QUALIFIER
, 13, ArrayUtils
.add(VALUE
, (byte) 4));
1449 Scan s
= new Scan().withStartRow(row
);
1450 // get all the possible versions
1451 s
.readAllVersions();
1454 try (ResultScanner scanner
= table
.getScanner(s
)) {
1456 for (Result r
: scanner
) {
1457 assertEquals("Found an unexpected number of results for the row!", versions
,
1458 r
.listCells().size());
1461 assertEquals("Found more than a single row when raw scanning the table with a single row!",
1465 // then if we decrease the number of versions, but keep the scan raw, we should see exactly
1466 // that number of versions
1468 s
.readVersions(versions
);
1469 try (ResultScanner scanner
= table
.getScanner(s
)) {
1471 for (Result r
: scanner
) {
1472 assertEquals("Found an unexpected number of results for the row!", versions
,
1473 r
.listCells().size());
1476 assertEquals("Found more than a single row when raw scanning the table with a single row!",
1480 // finally, if we turn off raw scanning, but max out the number of versions, we should go back
1481 // to seeing just three
1483 s
.readVersions(versions
);
1484 try (ResultScanner scanner
= table
.getScanner(s
)) {
1486 for (Result r
: scanner
) {
1487 assertEquals("Found an unexpected number of results for the row!", versions
,
1488 r
.listCells().size());
1491 assertEquals("Found more than a single row when raw scanning the table with a single row!",
1496 TEST_UTIL
.deleteTable(tableName
);
1500 public void testEmptyFilterList() throws Exception
{
1501 // Test Initialization.
1502 final TableName tableName
= name
.getTableName();
1503 try (Table table
= TEST_UTIL
.createTable(tableName
, FAMILY
)) {
1505 // Insert one row each region
1506 Put put
= new Put(Bytes
.toBytes("row"));
1507 put
.addColumn(FAMILY
, QUALIFIER
, VALUE
);
1510 List
<Result
> scanResults
= new LinkedList
<>();
1511 Scan scan
= new Scan();
1512 scan
.setFilter(new FilterList());
1513 try (ResultScanner scanner
= table
.getScanner(scan
)) {
1514 for (Result r
: scanner
) {
1518 assertEquals(1, scanResults
.size());
1519 Get g
= new Get(Bytes
.toBytes("row"));
1520 g
.setFilter(new FilterList());
1521 Result getResult
= table
.get(g
);
1522 Result scanResult
= scanResults
.get(0);
1523 assertEquals(scanResult
.rawCells().length
, getResult
.rawCells().length
);
1524 for (int i
= 0; i
!= scanResult
.rawCells().length
; ++i
) {
1525 Cell scanCell
= scanResult
.rawCells()[i
];
1526 Cell getCell
= getResult
.rawCells()[i
];
1527 assertEquals(0, Bytes
.compareTo(CellUtil
.cloneRow(scanCell
),
1528 CellUtil
.cloneRow(getCell
)));
1529 assertEquals(0, Bytes
.compareTo(CellUtil
.cloneFamily(scanCell
),
1530 CellUtil
.cloneFamily(getCell
)));
1531 assertEquals(0, Bytes
.compareTo(CellUtil
.cloneQualifier(scanCell
),
1532 CellUtil
.cloneQualifier(getCell
)));
1533 assertEquals(0, Bytes
.compareTo(CellUtil
.cloneValue(scanCell
),
1534 CellUtil
.cloneValue(getCell
)));
1540 public void testSmallScan() throws Exception
{
1541 // Test Initialization.
1542 final TableName tableName
= name
.getTableName();
1543 try (Table table
= TEST_UTIL
.createTable(tableName
, FAMILY
)) {
1545 // Insert one row each region
1547 for (int i
= 0; i
< 10; i
++) {
1548 Put put
= new Put(Bytes
.toBytes("row" + String
.format("%03d", i
)));
1549 put
.addColumn(FAMILY
, QUALIFIER
, VALUE
);
1554 try (ResultScanner scanner
= table
.getScanner(new Scan())) {
1556 for (Result r
: scanner
) {
1557 assertFalse(r
.isEmpty());
1560 assertEquals(insertNum
, count
);
1564 Scan scan
= new Scan().withStartRow(HConstants
.EMPTY_START_ROW
)
1565 .withStopRow(HConstants
.EMPTY_END_ROW
, true);
1566 scan
.setSmall(true);
1568 try (ResultScanner scanner
= table
.getScanner(scan
)) {
1570 for (Result r
: scanner
) {
1571 assertFalse(r
.isEmpty());
1574 assertEquals(insertNum
, count
);
1580 public void testSuperSimpleWithReverseScan() throws Exception
{
1581 final TableName tableName
= name
.getTableName();
1582 try (Table ht
= TEST_UTIL
.createTable(tableName
, FAMILY
)) {
1583 Put put
= new Put(Bytes
.toBytes("0-b11111-0000000000000000000"));
1584 put
.addColumn(FAMILY
, QUALIFIER
, VALUE
);
1586 put
= new Put(Bytes
.toBytes("0-b11111-0000000000000000002"));
1587 put
.addColumn(FAMILY
, QUALIFIER
, VALUE
);
1589 put
= new Put(Bytes
.toBytes("0-b11111-0000000000000000004"));
1590 put
.addColumn(FAMILY
, QUALIFIER
, VALUE
);
1592 put
= new Put(Bytes
.toBytes("0-b11111-0000000000000000006"));
1593 put
.addColumn(FAMILY
, QUALIFIER
, VALUE
);
1595 put
= new Put(Bytes
.toBytes("0-b11111-0000000000000000008"));
1596 put
.addColumn(FAMILY
, QUALIFIER
, VALUE
);
1598 put
= new Put(Bytes
.toBytes("0-b22222-0000000000000000001"));
1599 put
.addColumn(FAMILY
, QUALIFIER
, VALUE
);
1601 put
= new Put(Bytes
.toBytes("0-b22222-0000000000000000003"));
1602 put
.addColumn(FAMILY
, QUALIFIER
, VALUE
);
1604 put
= new Put(Bytes
.toBytes("0-b22222-0000000000000000005"));
1605 put
.addColumn(FAMILY
, QUALIFIER
, VALUE
);
1607 put
= new Put(Bytes
.toBytes("0-b22222-0000000000000000007"));
1608 put
.addColumn(FAMILY
, QUALIFIER
, VALUE
);
1610 put
= new Put(Bytes
.toBytes("0-b22222-0000000000000000009"));
1611 put
.addColumn(FAMILY
, QUALIFIER
, VALUE
);
1613 Scan scan
= new Scan().withStartRow(Bytes
.toBytes("0-b11111-9223372036854775807"))
1614 .withStopRow(Bytes
.toBytes("0-b11111-0000000000000000000"), true);
1615 scan
.setReversed(true);
1616 try (ResultScanner scanner
= ht
.getScanner(scan
)) {
1617 Result result
= scanner
.next();
1618 assertTrue(Bytes
.equals(result
.getRow(),
1619 Bytes
.toBytes("0-b11111-0000000000000000008")));
1625 public void testFiltersWithReverseScan() throws Exception
{
1626 final TableName tableName
= name
.getTableName();
1627 try (Table ht
= TEST_UTIL
.createTable(tableName
, FAMILY
)) {
1628 byte[][] ROWS
= makeN(ROW
, 10);
1629 byte[][] QUALIFIERS
= {Bytes
.toBytes("col0-<d2v1>-<d3v2>"),
1630 Bytes
.toBytes("col1-<d2v1>-<d3v2>"),
1631 Bytes
.toBytes("col2-<d2v1>-<d3v2>"),
1632 Bytes
.toBytes("col3-<d2v1>-<d3v2>"),
1633 Bytes
.toBytes("col4-<d2v1>-<d3v2>"),
1634 Bytes
.toBytes("col5-<d2v1>-<d3v2>"),
1635 Bytes
.toBytes("col6-<d2v1>-<d3v2>"),
1636 Bytes
.toBytes("col7-<d2v1>-<d3v2>"),
1637 Bytes
.toBytes("col8-<d2v1>-<d3v2>"),
1638 Bytes
.toBytes("col9-<d2v1>-<d3v2>")};
1639 for (int i
= 0; i
< 10; i
++) {
1640 Put put
= new Put(ROWS
[i
]);
1641 put
.addColumn(FAMILY
, QUALIFIERS
[i
], VALUE
);
1644 Scan scan
= new Scan();
1645 scan
.setReversed(true);
1646 scan
.addFamily(FAMILY
);
1647 Filter filter
= new QualifierFilter(CompareOperator
.EQUAL
,
1648 new RegexStringComparator("col[1-5]"));
1649 scan
.setFilter(filter
);
1650 try (ResultScanner scanner
= ht
.getScanner(scan
)) {
1651 int expectedIndex
= 5;
1652 for (Result result
: scanner
) {
1653 assertEquals(1, result
.size());
1654 Cell c
= result
.rawCells()[0];
1655 assertTrue(Bytes
.equals(c
.getRowArray(), c
.getRowOffset(), c
.getRowLength(),
1656 ROWS
[expectedIndex
], 0, ROWS
[expectedIndex
].length
));
1657 assertTrue(Bytes
.equals(c
.getQualifierArray(), c
.getQualifierOffset(),
1658 c
.getQualifierLength(), QUALIFIERS
[expectedIndex
], 0,
1659 QUALIFIERS
[expectedIndex
].length
));
1662 assertEquals(0, expectedIndex
);
1668 public void testKeyOnlyFilterWithReverseScan() throws Exception
{
1669 final TableName tableName
= name
.getTableName();
1670 try (Table ht
= TEST_UTIL
.createTable(tableName
, FAMILY
)) {
1671 byte[][] ROWS
= makeN(ROW
, 10);
1672 byte[][] QUALIFIERS
= {Bytes
.toBytes("col0-<d2v1>-<d3v2>"),
1673 Bytes
.toBytes("col1-<d2v1>-<d3v2>"),
1674 Bytes
.toBytes("col2-<d2v1>-<d3v2>"),
1675 Bytes
.toBytes("col3-<d2v1>-<d3v2>"),
1676 Bytes
.toBytes("col4-<d2v1>-<d3v2>"),
1677 Bytes
.toBytes("col5-<d2v1>-<d3v2>"),
1678 Bytes
.toBytes("col6-<d2v1>-<d3v2>"),
1679 Bytes
.toBytes("col7-<d2v1>-<d3v2>"),
1680 Bytes
.toBytes("col8-<d2v1>-<d3v2>"),
1681 Bytes
.toBytes("col9-<d2v1>-<d3v2>")};
1682 for (int i
= 0; i
< 10; i
++) {
1683 Put put
= new Put(ROWS
[i
]);
1684 put
.addColumn(FAMILY
, QUALIFIERS
[i
], VALUE
);
1687 Scan scan
= new Scan();
1688 scan
.setReversed(true);
1689 scan
.addFamily(FAMILY
);
1690 Filter filter
= new KeyOnlyFilter(true);
1691 scan
.setFilter(filter
);
1692 try (ResultScanner ignored
= ht
.getScanner(scan
)) {
1694 for (Result result
: ht
.getScanner(scan
)) {
1695 assertEquals(1, result
.size());
1696 assertEquals(Bytes
.SIZEOF_INT
, result
.rawCells()[0].getValueLength());
1697 assertEquals(VALUE
.length
, Bytes
.toInt(CellUtil
.cloneValue(result
.rawCells()[0])));
1700 assertEquals(10, count
);
1706 * Test simple table and non-existent row cases.
1709 public void testSimpleMissingWithReverseScan() throws Exception
{
1710 final TableName tableName
= name
.getTableName();
1711 try (Table ht
= TEST_UTIL
.createTable(tableName
, FAMILY
)) {
1712 byte[][] ROWS
= makeN(ROW
, 4);
1714 // Try to get a row on an empty table
1715 Scan scan
= new Scan();
1716 scan
.setReversed(true);
1717 Result result
= getSingleScanResult(ht
, scan
);
1718 assertNullResult(result
);
1720 scan
= new Scan().withStartRow(ROWS
[0]);
1721 scan
.setReversed(true);
1722 result
= getSingleScanResult(ht
, scan
);
1723 assertNullResult(result
);
1725 scan
= new Scan().withStartRow(ROWS
[0]).withStopRow(ROWS
[1], true);
1726 scan
.setReversed(true);
1727 result
= getSingleScanResult(ht
, scan
);
1728 assertNullResult(result
);
1731 scan
.setReversed(true);
1732 scan
.addFamily(FAMILY
);
1733 result
= getSingleScanResult(ht
, scan
);
1734 assertNullResult(result
);
1737 scan
.setReversed(true);
1738 scan
.addColumn(FAMILY
, QUALIFIER
);
1739 result
= getSingleScanResult(ht
, scan
);
1740 assertNullResult(result
);
1744 Put put
= new Put(ROWS
[2]);
1745 put
.addColumn(FAMILY
, QUALIFIER
, VALUE
);
1748 // Make sure we can scan the row
1750 scan
.setReversed(true);
1751 result
= getSingleScanResult(ht
, scan
);
1752 assertSingleResult(result
, ROWS
[2], FAMILY
, QUALIFIER
, VALUE
);
1754 scan
= new Scan().withStartRow(ROWS
[3]).withStopRow(ROWS
[0], true);
1755 scan
.setReversed(true);
1756 result
= getSingleScanResult(ht
, scan
);
1757 assertSingleResult(result
, ROWS
[2], FAMILY
, QUALIFIER
, VALUE
);
1759 scan
= new Scan().withStartRow(ROWS
[2]).withStopRow(ROWS
[1], true);
1760 scan
.setReversed(true);
1761 result
= getSingleScanResult(ht
, scan
);
1762 assertSingleResult(result
, ROWS
[2], FAMILY
, QUALIFIER
, VALUE
);
1764 // Try to scan empty rows around it
1765 // Introduced MemStore#shouldSeekForReverseScan to fix the following
1766 scan
= new Scan().withStartRow(ROWS
[1]);
1767 scan
.setReversed(true);
1768 result
= getSingleScanResult(ht
, scan
);
1769 assertNullResult(result
);
1774 public void testNullWithReverseScan() throws Exception
{
1775 final TableName tableName
= name
.getTableName();
1776 try (Table ht
= TEST_UTIL
.createTable(tableName
, FAMILY
)) {
1777 // Null qualifier (should work)
1778 Put put
= new Put(ROW
);
1779 put
.addColumn(FAMILY
, null, VALUE
);
1781 scanTestNull(ht
, ROW
, FAMILY
, VALUE
, true);
1782 Delete delete
= new Delete(ROW
);
1783 delete
.addColumns(FAMILY
, null);
1789 TEST_UTIL
.createTable(TableName
.valueOf(name
.getTableName().toString() + "2"), FAMILY
)) {
1790 // Empty qualifier, byte[0] instead of null (should work)
1791 Put put
= new Put(ROW
);
1792 put
.addColumn(FAMILY
, HConstants
.EMPTY_BYTE_ARRAY
, VALUE
);
1794 scanTestNull(ht
, ROW
, FAMILY
, VALUE
, true);
1796 scanTestNull(ht
, ROW
, FAMILY
, VALUE
, true);
1797 Delete delete
= new Delete(ROW
);
1798 delete
.addColumns(FAMILY
, HConstants
.EMPTY_BYTE_ARRAY
);
1802 put
.addColumn(FAMILY
, QUALIFIER
, null);
1804 Scan scan
= new Scan();
1805 scan
.setReversed(true);
1806 scan
.addColumn(FAMILY
, QUALIFIER
);
1807 Result result
= getSingleScanResult(ht
, scan
);
1808 assertSingleResult(result
, ROW
, FAMILY
, QUALIFIER
, null);
1813 @SuppressWarnings("checkstyle:MethodLength")
1814 public void testDeletesWithReverseScan() throws Exception
{
1815 final TableName tableName
= name
.getTableName();
1816 byte[][] ROWS
= makeNAscii(ROW
, 6);
1817 byte[][] FAMILIES
= makeNAscii(FAMILY
, 3);
1818 byte[][] VALUES
= makeN(VALUE
, 5);
1819 long[] ts
= { 1000, 2000, 3000, 4000, 5000 };
1820 try (Table ht
= TEST_UTIL
.createTable(tableName
, FAMILIES
, 3)) {
1822 Put put
= new Put(ROW
);
1823 put
.addColumn(FAMILIES
[0], QUALIFIER
, ts
[0], VALUES
[0]);
1824 put
.addColumn(FAMILIES
[0], QUALIFIER
, ts
[1], VALUES
[1]);
1827 Delete delete
= new Delete(ROW
);
1828 delete
.addFamily(FAMILIES
[0], ts
[0]);
1831 Scan scan
= new Scan().withStartRow(ROW
);
1832 scan
.setReversed(true);
1833 scan
.addFamily(FAMILIES
[0]);
1834 scan
.readVersions(Integer
.MAX_VALUE
);
1835 Result result
= getSingleScanResult(ht
, scan
);
1836 assertNResult(result
, ROW
, FAMILIES
[0], QUALIFIER
, new long[]{ts
[1]},
1837 new byte[][]{VALUES
[1]}, 0, 0);
1839 // Test delete latest version
1841 put
.addColumn(FAMILIES
[0], QUALIFIER
, ts
[4], VALUES
[4]);
1842 put
.addColumn(FAMILIES
[0], QUALIFIER
, ts
[2], VALUES
[2]);
1843 put
.addColumn(FAMILIES
[0], QUALIFIER
, ts
[3], VALUES
[3]);
1844 put
.addColumn(FAMILIES
[0], null, ts
[4], VALUES
[4]);
1845 put
.addColumn(FAMILIES
[0], null, ts
[2], VALUES
[2]);
1846 put
.addColumn(FAMILIES
[0], null, ts
[3], VALUES
[3]);
1849 delete
= new Delete(ROW
);
1850 delete
.addColumn(FAMILIES
[0], QUALIFIER
); // ts[4]
1853 scan
= new Scan().withStartRow(ROW
);
1854 scan
.setReversed(true);
1855 scan
.addColumn(FAMILIES
[0], QUALIFIER
);
1856 scan
.readVersions(Integer
.MAX_VALUE
);
1857 result
= getSingleScanResult(ht
, scan
);
1858 assertNResult(result
, ROW
, FAMILIES
[0], QUALIFIER
, new long[]{ts
[1],
1859 ts
[2], ts
[3]}, new byte[][]{VALUES
[1], VALUES
[2], VALUES
[3]}, 0, 2);
1861 // Test for HBASE-1847
1862 delete
= new Delete(ROW
);
1863 delete
.addColumn(FAMILIES
[0], null);
1866 // Cleanup null qualifier
1867 delete
= new Delete(ROW
);
1868 delete
.addColumns(FAMILIES
[0], null);
1871 // Expected client behavior might be that you can re-put deleted values
1872 // But alas, this is not to be. We can't put them back in either case.
1875 put
.addColumn(FAMILIES
[0], QUALIFIER
, ts
[0], VALUES
[0]);
1876 put
.addColumn(FAMILIES
[0], QUALIFIER
, ts
[4], VALUES
[4]);
1879 // The Scanner returns the previous values, the expected-naive-unexpected
1882 scan
= new Scan().withStartRow(ROW
);
1883 scan
.setReversed(true);
1884 scan
.addFamily(FAMILIES
[0]);
1885 scan
.readVersions(Integer
.MAX_VALUE
);
1886 result
= getSingleScanResult(ht
, scan
);
1887 assertNResult(result
, ROW
, FAMILIES
[0], QUALIFIER
, new long[]{ts
[1],
1888 ts
[2], ts
[3]}, new byte[][]{VALUES
[1], VALUES
[2], VALUES
[3]}, 0, 2);
1890 // Test deleting an entire family from one row but not the other various
1893 put
= new Put(ROWS
[0]);
1894 put
.addColumn(FAMILIES
[1], QUALIFIER
, ts
[0], VALUES
[0]);
1895 put
.addColumn(FAMILIES
[1], QUALIFIER
, ts
[1], VALUES
[1]);
1896 put
.addColumn(FAMILIES
[2], QUALIFIER
, ts
[2], VALUES
[2]);
1897 put
.addColumn(FAMILIES
[2], QUALIFIER
, ts
[3], VALUES
[3]);
1900 put
= new Put(ROWS
[1]);
1901 put
.addColumn(FAMILIES
[1], QUALIFIER
, ts
[0], VALUES
[0]);
1902 put
.addColumn(FAMILIES
[1], QUALIFIER
, ts
[1], VALUES
[1]);
1903 put
.addColumn(FAMILIES
[2], QUALIFIER
, ts
[2], VALUES
[2]);
1904 put
.addColumn(FAMILIES
[2], QUALIFIER
, ts
[3], VALUES
[3]);
1907 put
= new Put(ROWS
[2]);
1908 put
.addColumn(FAMILIES
[1], QUALIFIER
, ts
[0], VALUES
[0]);
1909 put
.addColumn(FAMILIES
[1], QUALIFIER
, ts
[1], VALUES
[1]);
1910 put
.addColumn(FAMILIES
[2], QUALIFIER
, ts
[2], VALUES
[2]);
1911 put
.addColumn(FAMILIES
[2], QUALIFIER
, ts
[3], VALUES
[3]);
1914 delete
= new Delete(ROWS
[0]);
1915 delete
.addFamily(FAMILIES
[2]);
1918 delete
= new Delete(ROWS
[1]);
1919 delete
.addColumns(FAMILIES
[1], QUALIFIER
);
1922 delete
= new Delete(ROWS
[2]);
1923 delete
.addColumn(FAMILIES
[1], QUALIFIER
);
1924 delete
.addColumn(FAMILIES
[1], QUALIFIER
);
1925 delete
.addColumn(FAMILIES
[2], QUALIFIER
);
1928 scan
= new Scan().withStartRow(ROWS
[0]);
1929 scan
.setReversed(true);
1930 scan
.addFamily(FAMILIES
[1]);
1931 scan
.addFamily(FAMILIES
[2]);
1932 scan
.readVersions(Integer
.MAX_VALUE
);
1933 result
= getSingleScanResult(ht
, scan
);
1934 assertEquals("Expected 2 keys but received " + result
.size(), 2, result
.size());
1935 assertNResult(result
, ROWS
[0], FAMILIES
[1], QUALIFIER
, new long[]{ts
[0],
1936 ts
[1]}, new byte[][]{VALUES
[0], VALUES
[1]}, 0, 1);
1938 scan
= new Scan().withStartRow(ROWS
[1]);
1939 scan
.setReversed(true);
1940 scan
.addFamily(FAMILIES
[1]);
1941 scan
.addFamily(FAMILIES
[2]);
1942 scan
.readVersions(Integer
.MAX_VALUE
);
1943 result
= getSingleScanResult(ht
, scan
);
1944 assertEquals("Expected 2 keys but received " + result
.size(), 2, result
.size());
1946 scan
= new Scan().withStartRow(ROWS
[2]);
1947 scan
.setReversed(true);
1948 scan
.addFamily(FAMILIES
[1]);
1949 scan
.addFamily(FAMILIES
[2]);
1950 scan
.readVersions(Integer
.MAX_VALUE
);
1951 result
= getSingleScanResult(ht
, scan
);
1952 assertEquals(1, result
.size());
1953 assertNResult(result
, ROWS
[2], FAMILIES
[2], QUALIFIER
,
1954 new long[]{ts
[2]}, new byte[][]{VALUES
[2]}, 0, 0);
1956 // Test if we delete the family first in one row (HBASE-1541)
1958 delete
= new Delete(ROWS
[3]);
1959 delete
.addFamily(FAMILIES
[1]);
1962 put
= new Put(ROWS
[3]);
1963 put
.addColumn(FAMILIES
[2], QUALIFIER
, VALUES
[0]);
1966 put
= new Put(ROWS
[4]);
1967 put
.addColumn(FAMILIES
[1], QUALIFIER
, VALUES
[1]);
1968 put
.addColumn(FAMILIES
[2], QUALIFIER
, VALUES
[2]);
1971 scan
= new Scan().withStartRow(ROWS
[4]);
1972 scan
.setReversed(true);
1973 scan
.addFamily(FAMILIES
[1]);
1974 scan
.addFamily(FAMILIES
[2]);
1975 scan
.readVersions(Integer
.MAX_VALUE
);
1976 ResultScanner scanner
= ht
.getScanner(scan
);
1977 result
= scanner
.next();
1978 assertEquals("Expected 2 keys but received " + result
.size(), 2, result
.size());
1979 assertTrue(Bytes
.equals(CellUtil
.cloneRow(result
.rawCells()[0]), ROWS
[4]));
1980 assertTrue(Bytes
.equals(CellUtil
.cloneRow(result
.rawCells()[1]), ROWS
[4]));
1981 assertTrue(Bytes
.equals(CellUtil
.cloneValue(result
.rawCells()[0]), VALUES
[1]));
1982 assertTrue(Bytes
.equals(CellUtil
.cloneValue(result
.rawCells()[1]), VALUES
[2]));
1983 result
= scanner
.next();
1984 assertEquals("Expected 1 key but received " + result
.size(), 1, result
.size());
1985 assertTrue(Bytes
.equals(CellUtil
.cloneRow(result
.rawCells()[0]), ROWS
[3]));
1986 assertTrue(Bytes
.equals(CellUtil
.cloneValue(result
.rawCells()[0]), VALUES
[0]));
1992 * Tests reversed scan under multi regions
1995 public void testReversedScanUnderMultiRegions() throws Exception
{
1996 // Test Initialization.
1997 final TableName tableName
= name
.getTableName();
1998 byte[] maxByteArray
= ConnectionUtils
.MAX_BYTE_ARRAY
;
1999 byte[][] splitRows
= new byte[][] { Bytes
.toBytes("005"),
2000 Bytes
.add(Bytes
.toBytes("005"), Bytes
.multiple(maxByteArray
, 16)),
2001 Bytes
.toBytes("006"),
2002 Bytes
.add(Bytes
.toBytes("006"), Bytes
.multiple(maxByteArray
, 8)),
2003 Bytes
.toBytes("007"),
2004 Bytes
.add(Bytes
.toBytes("007"), Bytes
.multiple(maxByteArray
, 4)),
2005 Bytes
.toBytes("008"), Bytes
.multiple(maxByteArray
, 2) };
2006 try (Table table
= TEST_UTIL
.createTable(tableName
, FAMILY
, splitRows
)) {
2007 TEST_UTIL
.waitUntilAllRegionsAssigned(table
.getName());
2009 try (RegionLocator l
= TEST_UTIL
.getConnection().getRegionLocator(tableName
)) {
2010 assertEquals(splitRows
.length
+ 1, l
.getAllRegionLocations().size());
2012 // Insert one row each region
2013 int insertNum
= splitRows
.length
;
2014 for (byte[] splitRow
: splitRows
) {
2015 Put put
= new Put(splitRow
);
2016 put
.addColumn(FAMILY
, QUALIFIER
, VALUE
);
2021 try (ResultScanner scanner
= table
.getScanner(new Scan())) {
2023 for (Result r
: scanner
) {
2024 assertFalse(r
.isEmpty());
2027 assertEquals(insertNum
, count
);
2031 Scan scan
= new Scan();
2032 scan
.setReversed(true);
2033 try (ResultScanner scanner
= table
.getScanner(scan
)) {
2035 byte[] lastRow
= null;
2036 for (Result r
: scanner
) {
2037 assertFalse(r
.isEmpty());
2039 byte[] thisRow
= r
.getRow();
2040 if (lastRow
!= null) {
2041 assertTrue("Error scan order, last row= " + Bytes
.toString(lastRow
)
2042 + ",this row=" + Bytes
.toString(thisRow
),
2043 Bytes
.compareTo(thisRow
, lastRow
) < 0);
2047 assertEquals(insertNum
, count
);
2053 * Tests reversed scan under multi regions
2056 public void testSmallReversedScanUnderMultiRegions() throws Exception
{
2057 // Test Initialization.
2058 final TableName tableName
= name
.getTableName();
2059 byte[][] splitRows
= new byte[][]{
2060 Bytes
.toBytes("000"), Bytes
.toBytes("002"), Bytes
.toBytes("004"),
2061 Bytes
.toBytes("006"), Bytes
.toBytes("008"), Bytes
.toBytes("010")};
2062 try (Table table
= TEST_UTIL
.createTable(tableName
, FAMILY
, splitRows
)) {
2063 TEST_UTIL
.waitUntilAllRegionsAssigned(table
.getName());
2065 try (RegionLocator l
= TEST_UTIL
.getConnection().getRegionLocator(tableName
)) {
2066 assertEquals(splitRows
.length
+ 1, l
.getAllRegionLocations().size());
2068 for (byte[] splitRow
: splitRows
) {
2069 Put put
= new Put(splitRow
);
2070 put
.addColumn(FAMILY
, QUALIFIER
, VALUE
);
2073 byte[] nextRow
= Bytes
.copy(splitRow
);
2074 nextRow
[nextRow
.length
- 1]++;
2076 put
= new Put(nextRow
);
2077 put
.addColumn(FAMILY
, QUALIFIER
, VALUE
);
2082 try (ResultScanner scanner
= table
.getScanner(new Scan())) {
2084 for (Result r
: scanner
) {
2085 assertTrue(!r
.isEmpty());
2088 assertEquals(12, count
);
2091 reverseScanTest(table
, false);
2092 reverseScanTest(table
, true);
2096 private void reverseScanTest(Table table
, boolean small
) throws IOException
{
2098 Scan scan
= new Scan();
2099 scan
.setReversed(true);
2100 try (ResultScanner scanner
= table
.getScanner(scan
)) {
2102 byte[] lastRow
= null;
2103 for (Result r
: scanner
) {
2104 assertTrue(!r
.isEmpty());
2106 byte[] thisRow
= r
.getRow();
2107 if (lastRow
!= null) {
2108 assertTrue("Error scan order, last row= " + Bytes
.toString(lastRow
)
2109 + ",this row=" + Bytes
.toString(thisRow
),
2110 Bytes
.compareTo(thisRow
, lastRow
) < 0);
2114 assertEquals(12, count
);
2118 scan
.setSmall(small
);
2119 scan
.setReversed(true);
2120 scan
.withStartRow(Bytes
.toBytes("002"));
2121 try (ResultScanner scanner
= table
.getScanner(scan
)) {
2123 byte[] lastRow
= null;
2124 for (Result r
: scanner
) {
2125 assertTrue(!r
.isEmpty());
2127 byte[] thisRow
= r
.getRow();
2128 if (lastRow
!= null) {
2129 assertTrue("Error scan order, last row= " + Bytes
.toString(lastRow
)
2130 + ",this row=" + Bytes
.toString(thisRow
),
2131 Bytes
.compareTo(thisRow
, lastRow
) < 0);
2135 assertEquals(3, count
); // 000 001 002
2139 scan
.setSmall(small
);
2140 scan
.setReversed(true);
2141 scan
.withStartRow(Bytes
.toBytes("002"));
2142 scan
.setStopRow(Bytes
.toBytes("000"));
2143 try (ResultScanner scanner
= table
.getScanner(scan
)) {
2145 byte[] lastRow
= null;
2146 for (Result r
: scanner
) {
2147 assertFalse(r
.isEmpty());
2149 byte[] thisRow
= r
.getRow();
2150 if (lastRow
!= null) {
2151 assertTrue("Error scan order, last row= " + Bytes
.toString(lastRow
)
2152 + ",this row=" + Bytes
.toString(thisRow
),
2153 Bytes
.compareTo(thisRow
, lastRow
) < 0);
2157 assertEquals(2, count
); // 001 002
2161 scan
.setSmall(small
);
2162 scan
.setReversed(true);
2163 scan
.withStartRow(Bytes
.toBytes("001"));
2164 try (ResultScanner scanner
= table
.getScanner(scan
)) {
2166 byte[] lastRow
= null;
2167 for (Result r
: scanner
) {
2168 assertFalse(r
.isEmpty());
2170 byte[] thisRow
= r
.getRow();
2171 if (lastRow
!= null) {
2172 assertTrue("Error scan order, last row= " + Bytes
.toString(lastRow
)
2173 + ",this row=" + Bytes
.toString(thisRow
),
2174 Bytes
.compareTo(thisRow
, lastRow
) < 0);
2178 assertEquals(2, count
); // 000 001
2182 scan
.setSmall(small
);
2183 scan
.setReversed(true);
2184 scan
.withStartRow(Bytes
.toBytes("000"));
2185 try (ResultScanner scanner
= table
.getScanner(scan
)) {
2187 byte[] lastRow
= null;
2188 for (Result r
: scanner
) {
2189 assertFalse(r
.isEmpty());
2191 byte[] thisRow
= r
.getRow();
2192 if (lastRow
!= null) {
2193 assertTrue("Error scan order, last row= " + Bytes
.toString(lastRow
)
2194 + ",this row=" + Bytes
.toString(thisRow
),
2195 Bytes
.compareTo(thisRow
, lastRow
) < 0);
2199 assertEquals(1, count
); // 000
2203 scan
.setSmall(small
);
2204 scan
.setReversed(true);
2205 scan
.withStartRow(Bytes
.toBytes("006"));
2206 scan
.setStopRow(Bytes
.toBytes("002"));
2207 try (ResultScanner scanner
= table
.getScanner(scan
)) {
2209 byte[] lastRow
= null;
2210 for (Result r
: scanner
) {
2211 assertFalse(r
.isEmpty());
2213 byte[] thisRow
= r
.getRow();
2214 if (lastRow
!= null) {
2215 assertTrue("Error scan order, last row= " + Bytes
.toString(lastRow
)
2216 + ",this row=" + Bytes
.toString(thisRow
),
2217 Bytes
.compareTo(thisRow
, lastRow
) < 0);
2221 assertEquals(4, count
); // 003 004 005 006
2226 public void testFilterAllRecords() throws IOException
{
2227 Scan scan
= new Scan();
2230 // Filter out any records
2231 scan
.setFilter(new FilterList(new FirstKeyOnlyFilter(), new InclusiveStopFilter(new byte[0])));
2232 try (Table table
= TEST_UTIL
.getConnection().getTable(TableName
.META_TABLE_NAME
)) {
2233 try (ResultScanner s
= table
.getScanner(scan
)) {
2234 assertNull(s
.next());
2240 public void testCellSizeLimit() throws IOException
{
2241 final TableName tableName
= TableName
.valueOf("testCellSizeLimit");
2242 TableDescriptorBuilder
.ModifyableTableDescriptor tableDescriptor
=
2243 new TableDescriptorBuilder
.ModifyableTableDescriptor(tableName
)
2244 .setValue(HRegion
.HBASE_MAX_CELL_SIZE_KEY
, Integer
.toString(10 * 1024));
2245 ColumnFamilyDescriptor familyDescriptor
=
2246 new ColumnFamilyDescriptorBuilder
.ModifyableColumnFamilyDescriptor(FAMILY
);
2248 tableDescriptor
.setColumnFamily(familyDescriptor
);
2249 try (Admin admin
= TEST_UTIL
.getAdmin()) {
2250 admin
.createTable(tableDescriptor
);
2253 try (Table t
= TEST_UTIL
.getConnection().getTable(tableName
)) {
2254 t
.put(new Put(ROW
).addColumn(FAMILY
, QUALIFIER
, Bytes
.toBytes(0L)));
2255 t
.increment(new Increment(ROW
).addColumn(FAMILY
, QUALIFIER
, 1L));
2258 try (Table t
= TEST_UTIL
.getConnection().getTable(tableName
)) {
2259 t
.put(new Put(ROW
).addColumn(FAMILY
, QUALIFIER
, new byte[9*1024]));
2262 try (Table t
= TEST_UTIL
.getConnection().getTable(tableName
)) {
2264 t
.put(new Put(ROW
).addColumn(FAMILY
, QUALIFIER
, new byte[10 * 1024]));
2265 fail("Oversize cell failed to trigger exception");
2266 } catch (IOException e
) {
2270 t
.append(new Append(ROW
).addColumn(FAMILY
, QUALIFIER
, new byte[2 * 1024]));
2271 fail("Oversize cell failed to trigger exception");
2272 } catch (IOException e
) {
2279 public void testDeleteSpecifiedVersionOfSpecifiedColumn() throws Exception
{
2280 final TableName tableName
= name
.getTableName();
2282 byte[][] VALUES
= makeN(VALUE
, 5);
2283 long[] ts
= {1000, 2000, 3000, 4000, 5000};
2285 try (Table ht
= TEST_UTIL
.createTable(tableName
, FAMILY
, 5)) {
2287 Put put
= new Put(ROW
);
2288 // Put version 1000,2000,3000,4000 of column FAMILY:QUALIFIER
2289 for (int t
= 0; t
< 4; t
++) {
2290 put
.addColumn(FAMILY
, QUALIFIER
, ts
[t
], VALUES
[t
]);
2294 Delete delete
= new Delete(ROW
);
2295 // Delete version 3000 of column FAMILY:QUALIFIER
2296 delete
.addColumn(FAMILY
, QUALIFIER
, ts
[2]);
2299 Get get
= new Get(ROW
);
2300 get
.addColumn(FAMILY
, QUALIFIER
);
2301 get
.readVersions(Integer
.MAX_VALUE
);
2302 Result result
= ht
.get(get
);
2303 // verify version 1000,2000,4000 remains for column FAMILY:QUALIFIER
2304 assertNResult(result
, ROW
, FAMILY
, QUALIFIER
, new long[]{ts
[0], ts
[1], ts
[3]}, new byte[][]{
2305 VALUES
[0], VALUES
[1], VALUES
[3]}, 0, 2);
2307 delete
= new Delete(ROW
);
2308 // Delete a version 5000 of column FAMILY:QUALIFIER which didn't exist
2309 delete
.addColumn(FAMILY
, QUALIFIER
, ts
[4]);
2313 get
.addColumn(FAMILY
, QUALIFIER
);
2314 get
.readVersions(Integer
.MAX_VALUE
);
2315 result
= ht
.get(get
);
2316 // verify version 1000,2000,4000 remains for column FAMILY:QUALIFIER
2317 assertNResult(result
, ROW
, FAMILY
, QUALIFIER
, new long[]{ts
[0], ts
[1], ts
[3]}, new byte[][]{
2318 VALUES
[0], VALUES
[1], VALUES
[3]}, 0, 2);
2323 public void testDeleteLatestVersionOfSpecifiedColumn() throws Exception
{
2324 final TableName tableName
= name
.getTableName();
2325 byte[][] VALUES
= makeN(VALUE
, 5);
2326 long[] ts
= {1000, 2000, 3000, 4000, 5000};
2327 try (Table ht
= TEST_UTIL
.createTable(tableName
, FAMILY
, 5)) {
2328 Put put
= new Put(ROW
);
2329 // Put version 1000,2000,3000,4000 of column FAMILY:QUALIFIER
2330 for (int t
= 0; t
< 4; t
++) {
2331 put
.addColumn(FAMILY
, QUALIFIER
, ts
[t
], VALUES
[t
]);
2335 Delete delete
= new Delete(ROW
);
2336 // Delete latest version of column FAMILY:QUALIFIER
2337 delete
.addColumn(FAMILY
, QUALIFIER
);
2340 Get get
= new Get(ROW
);
2341 get
.addColumn(FAMILY
, QUALIFIER
);
2342 get
.readVersions(Integer
.MAX_VALUE
);
2343 Result result
= ht
.get(get
);
2344 // verify version 1000,2000,3000 remains for column FAMILY:QUALIFIER
2345 assertNResult(result
, ROW
, FAMILY
, QUALIFIER
, new long[]{ts
[0], ts
[1], ts
[2]}, new byte[][]{
2346 VALUES
[0], VALUES
[1], VALUES
[2]}, 0, 2);
2348 delete
= new Delete(ROW
);
2349 // Delete two latest version of column FAMILY:QUALIFIER
2350 delete
.addColumn(FAMILY
, QUALIFIER
);
2351 delete
.addColumn(FAMILY
, QUALIFIER
);
2355 get
.addColumn(FAMILY
, QUALIFIER
);
2356 get
.readVersions(Integer
.MAX_VALUE
);
2357 result
= ht
.get(get
);
2358 // verify version 1000 remains for column FAMILY:QUALIFIER
2359 assertNResult(result
, ROW
, FAMILY
, QUALIFIER
, new long[]{ts
[0]}, new byte[][]{VALUES
[0]},
2363 // Put a version 5000 of column FAMILY:QUALIFIER
2364 put
.addColumn(FAMILY
, QUALIFIER
, ts
[4], VALUES
[4]);
2368 get
.addColumn(FAMILY
, QUALIFIER
);
2369 get
.readVersions(Integer
.MAX_VALUE
);
2370 result
= ht
.get(get
);
2371 // verify version 1000,5000 remains for column FAMILY:QUALIFIER
2372 assertNResult(result
, ROW
, FAMILY
, QUALIFIER
, new long[]{ts
[0], ts
[4]}, new byte[][]{
2373 VALUES
[0], VALUES
[4]}, 0, 1);
2378 * Test for HBASE-17125
2381 public void testReadWithFilter() throws Exception
{
2382 final TableName tableName
= name
.getTableName();
2383 try (Table table
= TEST_UTIL
.createTable(tableName
, FAMILY
, 3)) {
2385 byte[] VALUEA
= Bytes
.toBytes("value-a");
2386 byte[] VALUEB
= Bytes
.toBytes("value-b");
2387 long[] ts
= {1000, 2000, 3000, 4000};
2389 Put put
= new Put(ROW
);
2390 // Put version 1000,2000,3000,4000 of column FAMILY:QUALIFIER
2391 for (int t
= 0; t
<= 3; t
++) {
2393 put
.addColumn(FAMILY
, QUALIFIER
, ts
[t
], VALUEA
);
2395 put
.addColumn(FAMILY
, QUALIFIER
, ts
[t
], VALUEB
);
2401 new Scan().setFilter(new ValueFilter(CompareOperator
.EQUAL
,
2402 new SubstringComparator("value-a")))
2404 ResultScanner scanner
= table
.getScanner(scan
);
2405 Result result
= scanner
.next();
2406 // ts[0] has gone from user view. Only read ts[2] which value is less or equal to 3
2407 assertNResult(result
, ROW
, FAMILY
, QUALIFIER
, new long[]{ts
[1]}, new byte[][]{VALUEA
}, 0,
2412 .setFilter(new ValueFilter(CompareOperator
.EQUAL
,
2413 new SubstringComparator("value-a")))
2415 result
= table
.get(get
);
2416 // ts[0] has gone from user view. Only read ts[2] which value is less or equal to 3
2417 assertNResult(result
, ROW
, FAMILY
, QUALIFIER
, new long[]{ts
[1]}, new byte[][]{VALUEA
}, 0,
2420 // Test with max versions 1, it should still read ts[1]
2422 new Scan().setFilter(new ValueFilter(CompareOperator
.EQUAL
,
2423 new SubstringComparator("value-a")))
2425 scanner
= table
.getScanner(scan
);
2426 result
= scanner
.next();
2427 // ts[0] has gone from user view. Only read ts[2] which value is less or equal to 3
2428 assertNResult(result
, ROW
, FAMILY
, QUALIFIER
, new long[]{ts
[1]}, new byte[][]{VALUEA
}, 0,
2431 // Test with max versions 1, it should still read ts[1]
2434 .setFilter(new ValueFilter(CompareOperator
.EQUAL
,
2435 new SubstringComparator("value-a")))
2437 result
= table
.get(get
);
2438 // ts[0] has gone from user view. Only read ts[2] which value is less or equal to 3
2439 assertNResult(result
, ROW
, FAMILY
, QUALIFIER
, new long[]{ts
[1]}, new byte[][]{VALUEA
}, 0,
2442 // Test with max versions 5, it should still read ts[1]
2444 new Scan().setFilter(new ValueFilter(CompareOperator
.EQUAL
,
2445 new SubstringComparator("value-a")))
2447 scanner
= table
.getScanner(scan
);
2448 result
= scanner
.next();
2449 // ts[0] has gone from user view. Only read ts[2] which value is less or equal to 3
2450 assertNResult(result
, ROW
, FAMILY
, QUALIFIER
, new long[]{ts
[1]}, new byte[][]{VALUEA
}, 0,
2453 // Test with max versions 5, it should still read ts[1]
2456 .setFilter(new ValueFilter(CompareOperator
.EQUAL
,
2457 new SubstringComparator("value-a")))
2459 result
= table
.get(get
);
2460 // ts[0] has gone from user view. Only read ts[2] which value is less or equal to 3
2461 assertNResult(result
, ROW
, FAMILY
, QUALIFIER
, new long[]{ts
[1]}, new byte[][]{VALUEA
}, 0,
2467 public void testCellUtilTypeMethods() throws IOException
{
2468 final TableName tableName
= name
.getTableName();
2469 try (Table table
= TEST_UTIL
.createTable(tableName
, FAMILY
)) {
2471 final byte[] row
= Bytes
.toBytes("p");
2472 Put p
= new Put(row
);
2473 p
.addColumn(FAMILY
, QUALIFIER
, VALUE
);
2476 try (ResultScanner scanner
= table
.getScanner(new Scan())) {
2477 Result result
= scanner
.next();
2478 assertNotNull(result
);
2479 CellScanner cs
= result
.cellScanner();
2480 assertTrue(cs
.advance());
2481 Cell c
= cs
.current();
2482 assertTrue(CellUtil
.isPut(c
));
2483 assertFalse(CellUtil
.isDelete(c
));
2484 assertFalse(cs
.advance());
2485 assertNull(scanner
.next());
2488 Delete d
= new Delete(row
);
2489 d
.addColumn(FAMILY
, QUALIFIER
);
2492 Scan scan
= new Scan();
2494 try (ResultScanner scanner
= table
.getScanner(scan
)) {
2495 Result result
= scanner
.next();
2496 assertNotNull(result
);
2497 CellScanner cs
= result
.cellScanner();
2498 assertTrue(cs
.advance());
2500 // First cell should be the delete (masking the Put)
2501 Cell c
= cs
.current();
2502 assertTrue("Cell should be a Delete: " + c
, CellUtil
.isDelete(c
));
2503 assertFalse("Cell should not be a Put: " + c
, CellUtil
.isPut(c
));
2505 // Second cell should be the original Put
2506 assertTrue(cs
.advance());
2508 assertFalse("Cell should not be a Delete: " + c
, CellUtil
.isDelete(c
));
2509 assertTrue("Cell should be a Put: " + c
, CellUtil
.isPut(c
));
2511 // No more cells in this row
2512 assertFalse(cs
.advance());
2514 // No more results in this scan
2515 assertNull(scanner
.next());
2520 @Test(expected
= DoNotRetryIOException
.class)
2521 public void testCreateTableWithZeroRegionReplicas() throws Exception
{
2522 TableName tableName
= name
.getTableName();
2523 TableDescriptor desc
= TableDescriptorBuilder
.newBuilder(tableName
)
2524 .setColumnFamily(ColumnFamilyDescriptorBuilder
.of(Bytes
.toBytes("cf")))
2525 .setRegionReplication(0)
2528 TEST_UTIL
.getAdmin().createTable(desc
);
2531 @Test(expected
= DoNotRetryIOException
.class)
2532 public void testModifyTableWithZeroRegionReplicas() throws Exception
{
2533 TableName tableName
= name
.getTableName();
2534 TableDescriptor desc
= TableDescriptorBuilder
.newBuilder(tableName
)
2535 .setColumnFamily(ColumnFamilyDescriptorBuilder
.of(Bytes
.toBytes("cf")))
2538 TEST_UTIL
.getAdmin().createTable(desc
);
2539 TableDescriptor newDesc
= TableDescriptorBuilder
.newBuilder(desc
)
2540 .setRegionReplication(0)
2543 TEST_UTIL
.getAdmin().modifyTable(newDesc
);
2546 @Test(timeout
= 60000)
2547 public void testModifyTableWithMemstoreData() throws Exception
{
2548 TableName tableName
= name
.getTableName();
2549 createTableAndValidateTableSchemaModification(tableName
, true);
2552 @Test(timeout
= 60000)
2553 public void testDeleteCFWithMemstoreData() throws Exception
{
2554 TableName tableName
= name
.getTableName();
2555 createTableAndValidateTableSchemaModification(tableName
, false);
2559 * Create table and validate online schema modification
2560 * @param tableName Table name
2561 * @param modifyTable Modify table if true otherwise delete column family
2562 * @throws IOException in case of failures
2564 private void createTableAndValidateTableSchemaModification(TableName tableName
,
2565 boolean modifyTable
) throws Exception
{
2566 Admin admin
= TEST_UTIL
.getAdmin();
2567 // Create table with two Cfs
2568 byte[] cf1
= Bytes
.toBytes("cf1");
2569 byte[] cf2
= Bytes
.toBytes("cf2");
2570 TableDescriptor tableDesc
= TableDescriptorBuilder
.newBuilder(tableName
)
2571 .setColumnFamily(ColumnFamilyDescriptorBuilder
.of(cf1
))
2572 .setColumnFamily(ColumnFamilyDescriptorBuilder
.of(cf2
)).build();
2573 admin
.createTable(tableDesc
);
2575 Table t
= TEST_UTIL
.getConnection().getTable(tableName
);
2576 // Insert few records and flush the table
2577 t
.put(new Put(ROW
).addColumn(cf1
, QUALIFIER
, Bytes
.toBytes("val1")));
2578 t
.put(new Put(ROW
).addColumn(cf2
, QUALIFIER
, Bytes
.toBytes("val2")));
2579 admin
.flush(tableName
);
2580 Path tableDir
= FSUtils
.getTableDir(TEST_UTIL
.getDefaultRootDirPath(), tableName
);
2581 List
<Path
> regionDirs
= FSUtils
.getRegionDirs(TEST_UTIL
.getTestFileSystem(), tableDir
);
2582 assertEquals(1, regionDirs
.size());
2583 List
<Path
> familyDirs
= FSUtils
.getFamilyDirs(TEST_UTIL
.getTestFileSystem(), regionDirs
.get(0));
2584 assertEquals(2, familyDirs
.size());
2586 // Insert record but dont flush the table
2587 t
.put(new Put(ROW
).addColumn(cf1
, QUALIFIER
, Bytes
.toBytes("val2")));
2588 t
.put(new Put(ROW
).addColumn(cf2
, QUALIFIER
, Bytes
.toBytes("val2")));
2591 tableDesc
= TableDescriptorBuilder
.newBuilder(tableDesc
).removeColumnFamily(cf2
).build();
2592 admin
.modifyTable(tableDesc
);
2594 admin
.deleteColumnFamily(tableName
, cf2
);
2596 // After table modification or delete family there should be only one CF in FS
2597 familyDirs
= FSUtils
.getFamilyDirs(TEST_UTIL
.getTestFileSystem(), regionDirs
.get(0));
2598 assertEquals("CF dir count should be 1, but was " + familyDirs
.size(), 1, familyDirs
.size());