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(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(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(HConstants
.EMPTY_START_ROW
, HConstants
.EMPTY_END_ROW
);
1565 scan
.setSmall(true);
1567 try (ResultScanner scanner
= table
.getScanner(scan
)) {
1569 for (Result r
: scanner
) {
1570 assertFalse(r
.isEmpty());
1573 assertEquals(insertNum
, count
);
1579 public void testSuperSimpleWithReverseScan() throws Exception
{
1580 final TableName tableName
= name
.getTableName();
1581 try (Table ht
= TEST_UTIL
.createTable(tableName
, FAMILY
)) {
1582 Put put
= new Put(Bytes
.toBytes("0-b11111-0000000000000000000"));
1583 put
.addColumn(FAMILY
, QUALIFIER
, VALUE
);
1585 put
= new Put(Bytes
.toBytes("0-b11111-0000000000000000002"));
1586 put
.addColumn(FAMILY
, QUALIFIER
, VALUE
);
1588 put
= new Put(Bytes
.toBytes("0-b11111-0000000000000000004"));
1589 put
.addColumn(FAMILY
, QUALIFIER
, VALUE
);
1591 put
= new Put(Bytes
.toBytes("0-b11111-0000000000000000006"));
1592 put
.addColumn(FAMILY
, QUALIFIER
, VALUE
);
1594 put
= new Put(Bytes
.toBytes("0-b11111-0000000000000000008"));
1595 put
.addColumn(FAMILY
, QUALIFIER
, VALUE
);
1597 put
= new Put(Bytes
.toBytes("0-b22222-0000000000000000001"));
1598 put
.addColumn(FAMILY
, QUALIFIER
, VALUE
);
1600 put
= new Put(Bytes
.toBytes("0-b22222-0000000000000000003"));
1601 put
.addColumn(FAMILY
, QUALIFIER
, VALUE
);
1603 put
= new Put(Bytes
.toBytes("0-b22222-0000000000000000005"));
1604 put
.addColumn(FAMILY
, QUALIFIER
, VALUE
);
1606 put
= new Put(Bytes
.toBytes("0-b22222-0000000000000000007"));
1607 put
.addColumn(FAMILY
, QUALIFIER
, VALUE
);
1609 put
= new Put(Bytes
.toBytes("0-b22222-0000000000000000009"));
1610 put
.addColumn(FAMILY
, QUALIFIER
, VALUE
);
1612 Scan scan
= new Scan(Bytes
.toBytes("0-b11111-9223372036854775807"),
1613 Bytes
.toBytes("0-b11111-0000000000000000000"));
1614 scan
.setReversed(true);
1615 try (ResultScanner scanner
= ht
.getScanner(scan
)) {
1616 Result result
= scanner
.next();
1617 assertTrue(Bytes
.equals(result
.getRow(),
1618 Bytes
.toBytes("0-b11111-0000000000000000008")));
1624 public void testFiltersWithReverseScan() throws Exception
{
1625 final TableName tableName
= name
.getTableName();
1626 try (Table ht
= TEST_UTIL
.createTable(tableName
, FAMILY
)) {
1627 byte[][] ROWS
= makeN(ROW
, 10);
1628 byte[][] QUALIFIERS
= {Bytes
.toBytes("col0-<d2v1>-<d3v2>"),
1629 Bytes
.toBytes("col1-<d2v1>-<d3v2>"),
1630 Bytes
.toBytes("col2-<d2v1>-<d3v2>"),
1631 Bytes
.toBytes("col3-<d2v1>-<d3v2>"),
1632 Bytes
.toBytes("col4-<d2v1>-<d3v2>"),
1633 Bytes
.toBytes("col5-<d2v1>-<d3v2>"),
1634 Bytes
.toBytes("col6-<d2v1>-<d3v2>"),
1635 Bytes
.toBytes("col7-<d2v1>-<d3v2>"),
1636 Bytes
.toBytes("col8-<d2v1>-<d3v2>"),
1637 Bytes
.toBytes("col9-<d2v1>-<d3v2>")};
1638 for (int i
= 0; i
< 10; i
++) {
1639 Put put
= new Put(ROWS
[i
]);
1640 put
.addColumn(FAMILY
, QUALIFIERS
[i
], VALUE
);
1643 Scan scan
= new Scan();
1644 scan
.setReversed(true);
1645 scan
.addFamily(FAMILY
);
1646 Filter filter
= new QualifierFilter(CompareOperator
.EQUAL
,
1647 new RegexStringComparator("col[1-5]"));
1648 scan
.setFilter(filter
);
1649 try (ResultScanner scanner
= ht
.getScanner(scan
)) {
1650 int expectedIndex
= 5;
1651 for (Result result
: scanner
) {
1652 assertEquals(1, result
.size());
1653 Cell c
= result
.rawCells()[0];
1654 assertTrue(Bytes
.equals(c
.getRowArray(), c
.getRowOffset(), c
.getRowLength(),
1655 ROWS
[expectedIndex
], 0, ROWS
[expectedIndex
].length
));
1656 assertTrue(Bytes
.equals(c
.getQualifierArray(), c
.getQualifierOffset(),
1657 c
.getQualifierLength(), QUALIFIERS
[expectedIndex
], 0,
1658 QUALIFIERS
[expectedIndex
].length
));
1661 assertEquals(0, expectedIndex
);
1667 public void testKeyOnlyFilterWithReverseScan() throws Exception
{
1668 final TableName tableName
= name
.getTableName();
1669 try (Table ht
= TEST_UTIL
.createTable(tableName
, FAMILY
)) {
1670 byte[][] ROWS
= makeN(ROW
, 10);
1671 byte[][] QUALIFIERS
= {Bytes
.toBytes("col0-<d2v1>-<d3v2>"),
1672 Bytes
.toBytes("col1-<d2v1>-<d3v2>"),
1673 Bytes
.toBytes("col2-<d2v1>-<d3v2>"),
1674 Bytes
.toBytes("col3-<d2v1>-<d3v2>"),
1675 Bytes
.toBytes("col4-<d2v1>-<d3v2>"),
1676 Bytes
.toBytes("col5-<d2v1>-<d3v2>"),
1677 Bytes
.toBytes("col6-<d2v1>-<d3v2>"),
1678 Bytes
.toBytes("col7-<d2v1>-<d3v2>"),
1679 Bytes
.toBytes("col8-<d2v1>-<d3v2>"),
1680 Bytes
.toBytes("col9-<d2v1>-<d3v2>")};
1681 for (int i
= 0; i
< 10; i
++) {
1682 Put put
= new Put(ROWS
[i
]);
1683 put
.addColumn(FAMILY
, QUALIFIERS
[i
], VALUE
);
1686 Scan scan
= new Scan();
1687 scan
.setReversed(true);
1688 scan
.addFamily(FAMILY
);
1689 Filter filter
= new KeyOnlyFilter(true);
1690 scan
.setFilter(filter
);
1691 try (ResultScanner ignored
= ht
.getScanner(scan
)) {
1693 for (Result result
: ht
.getScanner(scan
)) {
1694 assertEquals(1, result
.size());
1695 assertEquals(Bytes
.SIZEOF_INT
, result
.rawCells()[0].getValueLength());
1696 assertEquals(VALUE
.length
, Bytes
.toInt(CellUtil
.cloneValue(result
.rawCells()[0])));
1699 assertEquals(10, count
);
1705 * Test simple table and non-existent row cases.
1708 public void testSimpleMissingWithReverseScan() throws Exception
{
1709 final TableName tableName
= name
.getTableName();
1710 try (Table ht
= TEST_UTIL
.createTable(tableName
, FAMILY
)) {
1711 byte[][] ROWS
= makeN(ROW
, 4);
1713 // Try to get a row on an empty table
1714 Scan scan
= new Scan();
1715 scan
.setReversed(true);
1716 Result result
= getSingleScanResult(ht
, scan
);
1717 assertNullResult(result
);
1719 scan
= new Scan(ROWS
[0]);
1720 scan
.setReversed(true);
1721 result
= getSingleScanResult(ht
, scan
);
1722 assertNullResult(result
);
1724 scan
= new Scan(ROWS
[0], ROWS
[1]);
1725 scan
.setReversed(true);
1726 result
= getSingleScanResult(ht
, scan
);
1727 assertNullResult(result
);
1730 scan
.setReversed(true);
1731 scan
.addFamily(FAMILY
);
1732 result
= getSingleScanResult(ht
, scan
);
1733 assertNullResult(result
);
1736 scan
.setReversed(true);
1737 scan
.addColumn(FAMILY
, QUALIFIER
);
1738 result
= getSingleScanResult(ht
, scan
);
1739 assertNullResult(result
);
1743 Put put
= new Put(ROWS
[2]);
1744 put
.addColumn(FAMILY
, QUALIFIER
, VALUE
);
1747 // Make sure we can scan the row
1749 scan
.setReversed(true);
1750 result
= getSingleScanResult(ht
, scan
);
1751 assertSingleResult(result
, ROWS
[2], FAMILY
, QUALIFIER
, VALUE
);
1753 scan
= new Scan(ROWS
[3], ROWS
[0]);
1754 scan
.setReversed(true);
1755 result
= getSingleScanResult(ht
, scan
);
1756 assertSingleResult(result
, ROWS
[2], FAMILY
, QUALIFIER
, VALUE
);
1758 scan
= new Scan(ROWS
[2], ROWS
[1]);
1759 scan
.setReversed(true);
1760 result
= getSingleScanResult(ht
, scan
);
1761 assertSingleResult(result
, ROWS
[2], FAMILY
, QUALIFIER
, VALUE
);
1763 // Try to scan empty rows around it
1764 // Introduced MemStore#shouldSeekForReverseScan to fix the following
1765 scan
= new Scan(ROWS
[1]);
1766 scan
.setReversed(true);
1767 result
= getSingleScanResult(ht
, scan
);
1768 assertNullResult(result
);
1773 public void testNullWithReverseScan() throws Exception
{
1774 final TableName tableName
= name
.getTableName();
1775 try (Table ht
= TEST_UTIL
.createTable(tableName
, FAMILY
)) {
1776 // Null qualifier (should work)
1777 Put put
= new Put(ROW
);
1778 put
.addColumn(FAMILY
, null, VALUE
);
1780 scanTestNull(ht
, ROW
, FAMILY
, VALUE
, true);
1781 Delete delete
= new Delete(ROW
);
1782 delete
.addColumns(FAMILY
, null);
1788 TEST_UTIL
.createTable(TableName
.valueOf(name
.getTableName().toString() + "2"), FAMILY
)) {
1789 // Empty qualifier, byte[0] instead of null (should work)
1790 Put put
= new Put(ROW
);
1791 put
.addColumn(FAMILY
, HConstants
.EMPTY_BYTE_ARRAY
, VALUE
);
1793 scanTestNull(ht
, ROW
, FAMILY
, VALUE
, true);
1795 scanTestNull(ht
, ROW
, FAMILY
, VALUE
, true);
1796 Delete delete
= new Delete(ROW
);
1797 delete
.addColumns(FAMILY
, HConstants
.EMPTY_BYTE_ARRAY
);
1801 put
.addColumn(FAMILY
, QUALIFIER
, null);
1803 Scan scan
= new Scan();
1804 scan
.setReversed(true);
1805 scan
.addColumn(FAMILY
, QUALIFIER
);
1806 Result result
= getSingleScanResult(ht
, scan
);
1807 assertSingleResult(result
, ROW
, FAMILY
, QUALIFIER
, null);
1812 @SuppressWarnings("checkstyle:MethodLength")
1813 public void testDeletesWithReverseScan() throws Exception
{
1814 final TableName tableName
= name
.getTableName();
1815 byte[][] ROWS
= makeNAscii(ROW
, 6);
1816 byte[][] FAMILIES
= makeNAscii(FAMILY
, 3);
1817 byte[][] VALUES
= makeN(VALUE
, 5);
1818 long[] ts
= { 1000, 2000, 3000, 4000, 5000 };
1819 try (Table ht
= TEST_UTIL
.createTable(tableName
, FAMILIES
, 3)) {
1821 Put put
= new Put(ROW
);
1822 put
.addColumn(FAMILIES
[0], QUALIFIER
, ts
[0], VALUES
[0]);
1823 put
.addColumn(FAMILIES
[0], QUALIFIER
, ts
[1], VALUES
[1]);
1826 Delete delete
= new Delete(ROW
);
1827 delete
.addFamily(FAMILIES
[0], ts
[0]);
1830 Scan scan
= new Scan(ROW
);
1831 scan
.setReversed(true);
1832 scan
.addFamily(FAMILIES
[0]);
1833 scan
.readVersions(Integer
.MAX_VALUE
);
1834 Result result
= getSingleScanResult(ht
, scan
);
1835 assertNResult(result
, ROW
, FAMILIES
[0], QUALIFIER
, new long[]{ts
[1]},
1836 new byte[][]{VALUES
[1]}, 0, 0);
1838 // Test delete latest version
1840 put
.addColumn(FAMILIES
[0], QUALIFIER
, ts
[4], VALUES
[4]);
1841 put
.addColumn(FAMILIES
[0], QUALIFIER
, ts
[2], VALUES
[2]);
1842 put
.addColumn(FAMILIES
[0], QUALIFIER
, ts
[3], VALUES
[3]);
1843 put
.addColumn(FAMILIES
[0], null, ts
[4], VALUES
[4]);
1844 put
.addColumn(FAMILIES
[0], null, ts
[2], VALUES
[2]);
1845 put
.addColumn(FAMILIES
[0], null, ts
[3], VALUES
[3]);
1848 delete
= new Delete(ROW
);
1849 delete
.addColumn(FAMILIES
[0], QUALIFIER
); // ts[4]
1852 scan
= new Scan(ROW
);
1853 scan
.setReversed(true);
1854 scan
.addColumn(FAMILIES
[0], QUALIFIER
);
1855 scan
.readVersions(Integer
.MAX_VALUE
);
1856 result
= getSingleScanResult(ht
, scan
);
1857 assertNResult(result
, ROW
, FAMILIES
[0], QUALIFIER
, new long[]{ts
[1],
1858 ts
[2], ts
[3]}, new byte[][]{VALUES
[1], VALUES
[2], VALUES
[3]}, 0, 2);
1860 // Test for HBASE-1847
1861 delete
= new Delete(ROW
);
1862 delete
.addColumn(FAMILIES
[0], null);
1865 // Cleanup null qualifier
1866 delete
= new Delete(ROW
);
1867 delete
.addColumns(FAMILIES
[0], null);
1870 // Expected client behavior might be that you can re-put deleted values
1871 // But alas, this is not to be. We can't put them back in either case.
1874 put
.addColumn(FAMILIES
[0], QUALIFIER
, ts
[0], VALUES
[0]);
1875 put
.addColumn(FAMILIES
[0], QUALIFIER
, ts
[4], VALUES
[4]);
1878 // The Scanner returns the previous values, the expected-naive-unexpected
1881 scan
= new Scan(ROW
);
1882 scan
.setReversed(true);
1883 scan
.addFamily(FAMILIES
[0]);
1884 scan
.readVersions(Integer
.MAX_VALUE
);
1885 result
= getSingleScanResult(ht
, scan
);
1886 assertNResult(result
, ROW
, FAMILIES
[0], QUALIFIER
, new long[]{ts
[1],
1887 ts
[2], ts
[3]}, new byte[][]{VALUES
[1], VALUES
[2], VALUES
[3]}, 0, 2);
1889 // Test deleting an entire family from one row but not the other various
1892 put
= new Put(ROWS
[0]);
1893 put
.addColumn(FAMILIES
[1], QUALIFIER
, ts
[0], VALUES
[0]);
1894 put
.addColumn(FAMILIES
[1], QUALIFIER
, ts
[1], VALUES
[1]);
1895 put
.addColumn(FAMILIES
[2], QUALIFIER
, ts
[2], VALUES
[2]);
1896 put
.addColumn(FAMILIES
[2], QUALIFIER
, ts
[3], VALUES
[3]);
1899 put
= new Put(ROWS
[1]);
1900 put
.addColumn(FAMILIES
[1], QUALIFIER
, ts
[0], VALUES
[0]);
1901 put
.addColumn(FAMILIES
[1], QUALIFIER
, ts
[1], VALUES
[1]);
1902 put
.addColumn(FAMILIES
[2], QUALIFIER
, ts
[2], VALUES
[2]);
1903 put
.addColumn(FAMILIES
[2], QUALIFIER
, ts
[3], VALUES
[3]);
1906 put
= new Put(ROWS
[2]);
1907 put
.addColumn(FAMILIES
[1], QUALIFIER
, ts
[0], VALUES
[0]);
1908 put
.addColumn(FAMILIES
[1], QUALIFIER
, ts
[1], VALUES
[1]);
1909 put
.addColumn(FAMILIES
[2], QUALIFIER
, ts
[2], VALUES
[2]);
1910 put
.addColumn(FAMILIES
[2], QUALIFIER
, ts
[3], VALUES
[3]);
1913 delete
= new Delete(ROWS
[0]);
1914 delete
.addFamily(FAMILIES
[2]);
1917 delete
= new Delete(ROWS
[1]);
1918 delete
.addColumns(FAMILIES
[1], QUALIFIER
);
1921 delete
= new Delete(ROWS
[2]);
1922 delete
.addColumn(FAMILIES
[1], QUALIFIER
);
1923 delete
.addColumn(FAMILIES
[1], QUALIFIER
);
1924 delete
.addColumn(FAMILIES
[2], QUALIFIER
);
1927 scan
= new Scan(ROWS
[0]);
1928 scan
.setReversed(true);
1929 scan
.addFamily(FAMILIES
[1]);
1930 scan
.addFamily(FAMILIES
[2]);
1931 scan
.readVersions(Integer
.MAX_VALUE
);
1932 result
= getSingleScanResult(ht
, scan
);
1933 assertEquals("Expected 2 keys but received " + result
.size(), 2, result
.size());
1934 assertNResult(result
, ROWS
[0], FAMILIES
[1], QUALIFIER
, new long[]{ts
[0],
1935 ts
[1]}, new byte[][]{VALUES
[0], VALUES
[1]}, 0, 1);
1937 scan
= new Scan(ROWS
[1]);
1938 scan
.setReversed(true);
1939 scan
.addFamily(FAMILIES
[1]);
1940 scan
.addFamily(FAMILIES
[2]);
1941 scan
.readVersions(Integer
.MAX_VALUE
);
1942 result
= getSingleScanResult(ht
, scan
);
1943 assertEquals("Expected 2 keys but received " + result
.size(), 2, result
.size());
1945 scan
= new Scan(ROWS
[2]);
1946 scan
.setReversed(true);
1947 scan
.addFamily(FAMILIES
[1]);
1948 scan
.addFamily(FAMILIES
[2]);
1949 scan
.readVersions(Integer
.MAX_VALUE
);
1950 result
= getSingleScanResult(ht
, scan
);
1951 assertEquals(1, result
.size());
1952 assertNResult(result
, ROWS
[2], FAMILIES
[2], QUALIFIER
,
1953 new long[]{ts
[2]}, new byte[][]{VALUES
[2]}, 0, 0);
1955 // Test if we delete the family first in one row (HBASE-1541)
1957 delete
= new Delete(ROWS
[3]);
1958 delete
.addFamily(FAMILIES
[1]);
1961 put
= new Put(ROWS
[3]);
1962 put
.addColumn(FAMILIES
[2], QUALIFIER
, VALUES
[0]);
1965 put
= new Put(ROWS
[4]);
1966 put
.addColumn(FAMILIES
[1], QUALIFIER
, VALUES
[1]);
1967 put
.addColumn(FAMILIES
[2], QUALIFIER
, VALUES
[2]);
1970 scan
= new Scan(ROWS
[4]);
1971 scan
.setReversed(true);
1972 scan
.addFamily(FAMILIES
[1]);
1973 scan
.addFamily(FAMILIES
[2]);
1974 scan
.readVersions(Integer
.MAX_VALUE
);
1975 ResultScanner scanner
= ht
.getScanner(scan
);
1976 result
= scanner
.next();
1977 assertEquals("Expected 2 keys but received " + result
.size(), 2, result
.size());
1978 assertTrue(Bytes
.equals(CellUtil
.cloneRow(result
.rawCells()[0]), ROWS
[4]));
1979 assertTrue(Bytes
.equals(CellUtil
.cloneRow(result
.rawCells()[1]), ROWS
[4]));
1980 assertTrue(Bytes
.equals(CellUtil
.cloneValue(result
.rawCells()[0]), VALUES
[1]));
1981 assertTrue(Bytes
.equals(CellUtil
.cloneValue(result
.rawCells()[1]), VALUES
[2]));
1982 result
= scanner
.next();
1983 assertEquals("Expected 1 key but received " + result
.size(), 1, result
.size());
1984 assertTrue(Bytes
.equals(CellUtil
.cloneRow(result
.rawCells()[0]), ROWS
[3]));
1985 assertTrue(Bytes
.equals(CellUtil
.cloneValue(result
.rawCells()[0]), VALUES
[0]));
1991 * Tests reversed scan under multi regions
1994 public void testReversedScanUnderMultiRegions() throws Exception
{
1995 // Test Initialization.
1996 final TableName tableName
= name
.getTableName();
1997 byte[] maxByteArray
= ConnectionUtils
.MAX_BYTE_ARRAY
;
1998 byte[][] splitRows
= new byte[][] { Bytes
.toBytes("005"),
1999 Bytes
.add(Bytes
.toBytes("005"), Bytes
.multiple(maxByteArray
, 16)),
2000 Bytes
.toBytes("006"),
2001 Bytes
.add(Bytes
.toBytes("006"), Bytes
.multiple(maxByteArray
, 8)),
2002 Bytes
.toBytes("007"),
2003 Bytes
.add(Bytes
.toBytes("007"), Bytes
.multiple(maxByteArray
, 4)),
2004 Bytes
.toBytes("008"), Bytes
.multiple(maxByteArray
, 2) };
2005 try (Table table
= TEST_UTIL
.createTable(tableName
, FAMILY
, splitRows
)) {
2006 TEST_UTIL
.waitUntilAllRegionsAssigned(table
.getName());
2008 try (RegionLocator l
= TEST_UTIL
.getConnection().getRegionLocator(tableName
)) {
2009 assertEquals(splitRows
.length
+ 1, l
.getAllRegionLocations().size());
2011 // Insert one row each region
2012 int insertNum
= splitRows
.length
;
2013 for (byte[] splitRow
: splitRows
) {
2014 Put put
= new Put(splitRow
);
2015 put
.addColumn(FAMILY
, QUALIFIER
, VALUE
);
2020 try (ResultScanner scanner
= table
.getScanner(new Scan())) {
2022 for (Result r
: scanner
) {
2023 assertFalse(r
.isEmpty());
2026 assertEquals(insertNum
, count
);
2030 Scan scan
= new Scan();
2031 scan
.setReversed(true);
2032 try (ResultScanner scanner
= table
.getScanner(scan
)) {
2034 byte[] lastRow
= null;
2035 for (Result r
: scanner
) {
2036 assertFalse(r
.isEmpty());
2038 byte[] thisRow
= r
.getRow();
2039 if (lastRow
!= null) {
2040 assertTrue("Error scan order, last row= " + Bytes
.toString(lastRow
)
2041 + ",this row=" + Bytes
.toString(thisRow
),
2042 Bytes
.compareTo(thisRow
, lastRow
) < 0);
2046 assertEquals(insertNum
, count
);
2052 * Tests reversed scan under multi regions
2055 public void testSmallReversedScanUnderMultiRegions() throws Exception
{
2056 // Test Initialization.
2057 final TableName tableName
= name
.getTableName();
2058 byte[][] splitRows
= new byte[][]{
2059 Bytes
.toBytes("000"), Bytes
.toBytes("002"), Bytes
.toBytes("004"),
2060 Bytes
.toBytes("006"), Bytes
.toBytes("008"), Bytes
.toBytes("010")};
2061 try (Table table
= TEST_UTIL
.createTable(tableName
, FAMILY
, splitRows
)) {
2062 TEST_UTIL
.waitUntilAllRegionsAssigned(table
.getName());
2064 try (RegionLocator l
= TEST_UTIL
.getConnection().getRegionLocator(tableName
)) {
2065 assertEquals(splitRows
.length
+ 1, l
.getAllRegionLocations().size());
2067 for (byte[] splitRow
: splitRows
) {
2068 Put put
= new Put(splitRow
);
2069 put
.addColumn(FAMILY
, QUALIFIER
, VALUE
);
2072 byte[] nextRow
= Bytes
.copy(splitRow
);
2073 nextRow
[nextRow
.length
- 1]++;
2075 put
= new Put(nextRow
);
2076 put
.addColumn(FAMILY
, QUALIFIER
, VALUE
);
2081 try (ResultScanner scanner
= table
.getScanner(new Scan())) {
2083 for (Result r
: scanner
) {
2084 assertTrue(!r
.isEmpty());
2087 assertEquals(12, count
);
2090 reverseScanTest(table
, false);
2091 reverseScanTest(table
, true);
2095 private void reverseScanTest(Table table
, boolean small
) throws IOException
{
2097 Scan scan
= new Scan();
2098 scan
.setReversed(true);
2099 try (ResultScanner scanner
= table
.getScanner(scan
)) {
2101 byte[] lastRow
= null;
2102 for (Result r
: scanner
) {
2103 assertTrue(!r
.isEmpty());
2105 byte[] thisRow
= r
.getRow();
2106 if (lastRow
!= null) {
2107 assertTrue("Error scan order, last row= " + Bytes
.toString(lastRow
)
2108 + ",this row=" + Bytes
.toString(thisRow
),
2109 Bytes
.compareTo(thisRow
, lastRow
) < 0);
2113 assertEquals(12, count
);
2117 scan
.setSmall(small
);
2118 scan
.setReversed(true);
2119 scan
.withStartRow(Bytes
.toBytes("002"));
2120 try (ResultScanner scanner
= table
.getScanner(scan
)) {
2122 byte[] lastRow
= null;
2123 for (Result r
: scanner
) {
2124 assertTrue(!r
.isEmpty());
2126 byte[] thisRow
= r
.getRow();
2127 if (lastRow
!= null) {
2128 assertTrue("Error scan order, last row= " + Bytes
.toString(lastRow
)
2129 + ",this row=" + Bytes
.toString(thisRow
),
2130 Bytes
.compareTo(thisRow
, lastRow
) < 0);
2134 assertEquals(3, count
); // 000 001 002
2138 scan
.setSmall(small
);
2139 scan
.setReversed(true);
2140 scan
.withStartRow(Bytes
.toBytes("002"));
2141 scan
.setStopRow(Bytes
.toBytes("000"));
2142 try (ResultScanner scanner
= table
.getScanner(scan
)) {
2144 byte[] lastRow
= null;
2145 for (Result r
: scanner
) {
2146 assertFalse(r
.isEmpty());
2148 byte[] thisRow
= r
.getRow();
2149 if (lastRow
!= null) {
2150 assertTrue("Error scan order, last row= " + Bytes
.toString(lastRow
)
2151 + ",this row=" + Bytes
.toString(thisRow
),
2152 Bytes
.compareTo(thisRow
, lastRow
) < 0);
2156 assertEquals(2, count
); // 001 002
2160 scan
.setSmall(small
);
2161 scan
.setReversed(true);
2162 scan
.withStartRow(Bytes
.toBytes("001"));
2163 try (ResultScanner scanner
= table
.getScanner(scan
)) {
2165 byte[] lastRow
= null;
2166 for (Result r
: scanner
) {
2167 assertFalse(r
.isEmpty());
2169 byte[] thisRow
= r
.getRow();
2170 if (lastRow
!= null) {
2171 assertTrue("Error scan order, last row= " + Bytes
.toString(lastRow
)
2172 + ",this row=" + Bytes
.toString(thisRow
),
2173 Bytes
.compareTo(thisRow
, lastRow
) < 0);
2177 assertEquals(2, count
); // 000 001
2181 scan
.setSmall(small
);
2182 scan
.setReversed(true);
2183 scan
.withStartRow(Bytes
.toBytes("000"));
2184 try (ResultScanner scanner
= table
.getScanner(scan
)) {
2186 byte[] lastRow
= null;
2187 for (Result r
: scanner
) {
2188 assertFalse(r
.isEmpty());
2190 byte[] thisRow
= r
.getRow();
2191 if (lastRow
!= null) {
2192 assertTrue("Error scan order, last row= " + Bytes
.toString(lastRow
)
2193 + ",this row=" + Bytes
.toString(thisRow
),
2194 Bytes
.compareTo(thisRow
, lastRow
) < 0);
2198 assertEquals(1, count
); // 000
2202 scan
.setSmall(small
);
2203 scan
.setReversed(true);
2204 scan
.withStartRow(Bytes
.toBytes("006"));
2205 scan
.setStopRow(Bytes
.toBytes("002"));
2206 try (ResultScanner scanner
= table
.getScanner(scan
)) {
2208 byte[] lastRow
= null;
2209 for (Result r
: scanner
) {
2210 assertFalse(r
.isEmpty());
2212 byte[] thisRow
= r
.getRow();
2213 if (lastRow
!= null) {
2214 assertTrue("Error scan order, last row= " + Bytes
.toString(lastRow
)
2215 + ",this row=" + Bytes
.toString(thisRow
),
2216 Bytes
.compareTo(thisRow
, lastRow
) < 0);
2220 assertEquals(4, count
); // 003 004 005 006
2225 public void testFilterAllRecords() throws IOException
{
2226 Scan scan
= new Scan();
2229 // Filter out any records
2230 scan
.setFilter(new FilterList(new FirstKeyOnlyFilter(), new InclusiveStopFilter(new byte[0])));
2231 try (Table table
= TEST_UTIL
.getConnection().getTable(TableName
.META_TABLE_NAME
)) {
2232 try (ResultScanner s
= table
.getScanner(scan
)) {
2233 assertNull(s
.next());
2239 public void testCellSizeLimit() throws IOException
{
2240 final TableName tableName
= TableName
.valueOf("testCellSizeLimit");
2241 TableDescriptorBuilder
.ModifyableTableDescriptor tableDescriptor
=
2242 new TableDescriptorBuilder
.ModifyableTableDescriptor(tableName
)
2243 .setValue(HRegion
.HBASE_MAX_CELL_SIZE_KEY
, Integer
.toString(10 * 1024));
2244 ColumnFamilyDescriptor familyDescriptor
=
2245 new ColumnFamilyDescriptorBuilder
.ModifyableColumnFamilyDescriptor(FAMILY
);
2247 tableDescriptor
.setColumnFamily(familyDescriptor
);
2248 try (Admin admin
= TEST_UTIL
.getAdmin()) {
2249 admin
.createTable(tableDescriptor
);
2252 try (Table t
= TEST_UTIL
.getConnection().getTable(tableName
)) {
2253 t
.put(new Put(ROW
).addColumn(FAMILY
, QUALIFIER
, Bytes
.toBytes(0L)));
2254 t
.increment(new Increment(ROW
).addColumn(FAMILY
, QUALIFIER
, 1L));
2257 try (Table t
= TEST_UTIL
.getConnection().getTable(tableName
)) {
2258 t
.put(new Put(ROW
).addColumn(FAMILY
, QUALIFIER
, new byte[9*1024]));
2261 try (Table t
= TEST_UTIL
.getConnection().getTable(tableName
)) {
2263 t
.put(new Put(ROW
).addColumn(FAMILY
, QUALIFIER
, new byte[10 * 1024]));
2264 fail("Oversize cell failed to trigger exception");
2265 } catch (IOException e
) {
2269 t
.append(new Append(ROW
).addColumn(FAMILY
, QUALIFIER
, new byte[2 * 1024]));
2270 fail("Oversize cell failed to trigger exception");
2271 } catch (IOException e
) {
2278 public void testDeleteSpecifiedVersionOfSpecifiedColumn() throws Exception
{
2279 final TableName tableName
= name
.getTableName();
2281 byte[][] VALUES
= makeN(VALUE
, 5);
2282 long[] ts
= {1000, 2000, 3000, 4000, 5000};
2284 try (Table ht
= TEST_UTIL
.createTable(tableName
, FAMILY
, 5)) {
2286 Put put
= new Put(ROW
);
2287 // Put version 1000,2000,3000,4000 of column FAMILY:QUALIFIER
2288 for (int t
= 0; t
< 4; t
++) {
2289 put
.addColumn(FAMILY
, QUALIFIER
, ts
[t
], VALUES
[t
]);
2293 Delete delete
= new Delete(ROW
);
2294 // Delete version 3000 of column FAMILY:QUALIFIER
2295 delete
.addColumn(FAMILY
, QUALIFIER
, ts
[2]);
2298 Get get
= new Get(ROW
);
2299 get
.addColumn(FAMILY
, QUALIFIER
);
2300 get
.readVersions(Integer
.MAX_VALUE
);
2301 Result result
= ht
.get(get
);
2302 // verify version 1000,2000,4000 remains for column FAMILY:QUALIFIER
2303 assertNResult(result
, ROW
, FAMILY
, QUALIFIER
, new long[]{ts
[0], ts
[1], ts
[3]}, new byte[][]{
2304 VALUES
[0], VALUES
[1], VALUES
[3]}, 0, 2);
2306 delete
= new Delete(ROW
);
2307 // Delete a version 5000 of column FAMILY:QUALIFIER which didn't exist
2308 delete
.addColumn(FAMILY
, QUALIFIER
, ts
[4]);
2312 get
.addColumn(FAMILY
, QUALIFIER
);
2313 get
.readVersions(Integer
.MAX_VALUE
);
2314 result
= ht
.get(get
);
2315 // verify version 1000,2000,4000 remains for column FAMILY:QUALIFIER
2316 assertNResult(result
, ROW
, FAMILY
, QUALIFIER
, new long[]{ts
[0], ts
[1], ts
[3]}, new byte[][]{
2317 VALUES
[0], VALUES
[1], VALUES
[3]}, 0, 2);
2322 public void testDeleteLatestVersionOfSpecifiedColumn() throws Exception
{
2323 final TableName tableName
= name
.getTableName();
2324 byte[][] VALUES
= makeN(VALUE
, 5);
2325 long[] ts
= {1000, 2000, 3000, 4000, 5000};
2326 try (Table ht
= TEST_UTIL
.createTable(tableName
, FAMILY
, 5)) {
2327 Put put
= new Put(ROW
);
2328 // Put version 1000,2000,3000,4000 of column FAMILY:QUALIFIER
2329 for (int t
= 0; t
< 4; t
++) {
2330 put
.addColumn(FAMILY
, QUALIFIER
, ts
[t
], VALUES
[t
]);
2334 Delete delete
= new Delete(ROW
);
2335 // Delete latest version of column FAMILY:QUALIFIER
2336 delete
.addColumn(FAMILY
, QUALIFIER
);
2339 Get get
= new Get(ROW
);
2340 get
.addColumn(FAMILY
, QUALIFIER
);
2341 get
.readVersions(Integer
.MAX_VALUE
);
2342 Result result
= ht
.get(get
);
2343 // verify version 1000,2000,3000 remains for column FAMILY:QUALIFIER
2344 assertNResult(result
, ROW
, FAMILY
, QUALIFIER
, new long[]{ts
[0], ts
[1], ts
[2]}, new byte[][]{
2345 VALUES
[0], VALUES
[1], VALUES
[2]}, 0, 2);
2347 delete
= new Delete(ROW
);
2348 // Delete two latest version of column FAMILY:QUALIFIER
2349 delete
.addColumn(FAMILY
, QUALIFIER
);
2350 delete
.addColumn(FAMILY
, QUALIFIER
);
2354 get
.addColumn(FAMILY
, QUALIFIER
);
2355 get
.readVersions(Integer
.MAX_VALUE
);
2356 result
= ht
.get(get
);
2357 // verify version 1000 remains for column FAMILY:QUALIFIER
2358 assertNResult(result
, ROW
, FAMILY
, QUALIFIER
, new long[]{ts
[0]}, new byte[][]{VALUES
[0]},
2362 // Put a version 5000 of column FAMILY:QUALIFIER
2363 put
.addColumn(FAMILY
, QUALIFIER
, ts
[4], VALUES
[4]);
2367 get
.addColumn(FAMILY
, QUALIFIER
);
2368 get
.readVersions(Integer
.MAX_VALUE
);
2369 result
= ht
.get(get
);
2370 // verify version 1000,5000 remains for column FAMILY:QUALIFIER
2371 assertNResult(result
, ROW
, FAMILY
, QUALIFIER
, new long[]{ts
[0], ts
[4]}, new byte[][]{
2372 VALUES
[0], VALUES
[4]}, 0, 1);
2377 * Test for HBASE-17125
2380 public void testReadWithFilter() throws Exception
{
2381 final TableName tableName
= name
.getTableName();
2382 try (Table table
= TEST_UTIL
.createTable(tableName
, FAMILY
, 3)) {
2384 byte[] VALUEA
= Bytes
.toBytes("value-a");
2385 byte[] VALUEB
= Bytes
.toBytes("value-b");
2386 long[] ts
= {1000, 2000, 3000, 4000};
2388 Put put
= new Put(ROW
);
2389 // Put version 1000,2000,3000,4000 of column FAMILY:QUALIFIER
2390 for (int t
= 0; t
<= 3; t
++) {
2392 put
.addColumn(FAMILY
, QUALIFIER
, ts
[t
], VALUEA
);
2394 put
.addColumn(FAMILY
, QUALIFIER
, ts
[t
], VALUEB
);
2400 new Scan().setFilter(new ValueFilter(CompareOperator
.EQUAL
,
2401 new SubstringComparator("value-a")))
2403 ResultScanner scanner
= table
.getScanner(scan
);
2404 Result result
= scanner
.next();
2405 // ts[0] has gone from user view. Only read ts[2] which value is less or equal to 3
2406 assertNResult(result
, ROW
, FAMILY
, QUALIFIER
, new long[]{ts
[1]}, new byte[][]{VALUEA
}, 0,
2411 .setFilter(new ValueFilter(CompareOperator
.EQUAL
,
2412 new SubstringComparator("value-a")))
2414 result
= table
.get(get
);
2415 // ts[0] has gone from user view. Only read ts[2] which value is less or equal to 3
2416 assertNResult(result
, ROW
, FAMILY
, QUALIFIER
, new long[]{ts
[1]}, new byte[][]{VALUEA
}, 0,
2419 // Test with max versions 1, it should still read ts[1]
2421 new Scan().setFilter(new ValueFilter(CompareOperator
.EQUAL
,
2422 new SubstringComparator("value-a")))
2424 scanner
= table
.getScanner(scan
);
2425 result
= scanner
.next();
2426 // ts[0] has gone from user view. Only read ts[2] which value is less or equal to 3
2427 assertNResult(result
, ROW
, FAMILY
, QUALIFIER
, new long[]{ts
[1]}, new byte[][]{VALUEA
}, 0,
2430 // Test with max versions 1, it should still read ts[1]
2433 .setFilter(new ValueFilter(CompareOperator
.EQUAL
,
2434 new SubstringComparator("value-a")))
2436 result
= table
.get(get
);
2437 // ts[0] has gone from user view. Only read ts[2] which value is less or equal to 3
2438 assertNResult(result
, ROW
, FAMILY
, QUALIFIER
, new long[]{ts
[1]}, new byte[][]{VALUEA
}, 0,
2441 // Test with max versions 5, it should still read ts[1]
2443 new Scan().setFilter(new ValueFilter(CompareOperator
.EQUAL
,
2444 new SubstringComparator("value-a")))
2446 scanner
= table
.getScanner(scan
);
2447 result
= scanner
.next();
2448 // ts[0] has gone from user view. Only read ts[2] which value is less or equal to 3
2449 assertNResult(result
, ROW
, FAMILY
, QUALIFIER
, new long[]{ts
[1]}, new byte[][]{VALUEA
}, 0,
2452 // Test with max versions 5, it should still read ts[1]
2455 .setFilter(new ValueFilter(CompareOperator
.EQUAL
,
2456 new SubstringComparator("value-a")))
2458 result
= table
.get(get
);
2459 // ts[0] has gone from user view. Only read ts[2] which value is less or equal to 3
2460 assertNResult(result
, ROW
, FAMILY
, QUALIFIER
, new long[]{ts
[1]}, new byte[][]{VALUEA
}, 0,
2466 public void testCellUtilTypeMethods() throws IOException
{
2467 final TableName tableName
= name
.getTableName();
2468 try (Table table
= TEST_UTIL
.createTable(tableName
, FAMILY
)) {
2470 final byte[] row
= Bytes
.toBytes("p");
2471 Put p
= new Put(row
);
2472 p
.addColumn(FAMILY
, QUALIFIER
, VALUE
);
2475 try (ResultScanner scanner
= table
.getScanner(new Scan())) {
2476 Result result
= scanner
.next();
2477 assertNotNull(result
);
2478 CellScanner cs
= result
.cellScanner();
2479 assertTrue(cs
.advance());
2480 Cell c
= cs
.current();
2481 assertTrue(CellUtil
.isPut(c
));
2482 assertFalse(CellUtil
.isDelete(c
));
2483 assertFalse(cs
.advance());
2484 assertNull(scanner
.next());
2487 Delete d
= new Delete(row
);
2488 d
.addColumn(FAMILY
, QUALIFIER
);
2491 Scan scan
= new Scan();
2493 try (ResultScanner scanner
= table
.getScanner(scan
)) {
2494 Result result
= scanner
.next();
2495 assertNotNull(result
);
2496 CellScanner cs
= result
.cellScanner();
2497 assertTrue(cs
.advance());
2499 // First cell should be the delete (masking the Put)
2500 Cell c
= cs
.current();
2501 assertTrue("Cell should be a Delete: " + c
, CellUtil
.isDelete(c
));
2502 assertFalse("Cell should not be a Put: " + c
, CellUtil
.isPut(c
));
2504 // Second cell should be the original Put
2505 assertTrue(cs
.advance());
2507 assertFalse("Cell should not be a Delete: " + c
, CellUtil
.isDelete(c
));
2508 assertTrue("Cell should be a Put: " + c
, CellUtil
.isPut(c
));
2510 // No more cells in this row
2511 assertFalse(cs
.advance());
2513 // No more results in this scan
2514 assertNull(scanner
.next());
2519 @Test(expected
= DoNotRetryIOException
.class)
2520 public void testCreateTableWithZeroRegionReplicas() throws Exception
{
2521 TableName tableName
= name
.getTableName();
2522 TableDescriptor desc
= TableDescriptorBuilder
.newBuilder(tableName
)
2523 .setColumnFamily(ColumnFamilyDescriptorBuilder
.of(Bytes
.toBytes("cf")))
2524 .setRegionReplication(0)
2527 TEST_UTIL
.getAdmin().createTable(desc
);
2530 @Test(expected
= DoNotRetryIOException
.class)
2531 public void testModifyTableWithZeroRegionReplicas() throws Exception
{
2532 TableName tableName
= name
.getTableName();
2533 TableDescriptor desc
= TableDescriptorBuilder
.newBuilder(tableName
)
2534 .setColumnFamily(ColumnFamilyDescriptorBuilder
.of(Bytes
.toBytes("cf")))
2537 TEST_UTIL
.getAdmin().createTable(desc
);
2538 TableDescriptor newDesc
= TableDescriptorBuilder
.newBuilder(desc
)
2539 .setRegionReplication(0)
2542 TEST_UTIL
.getAdmin().modifyTable(newDesc
);
2545 @Test(timeout
= 60000)
2546 public void testModifyTableWithMemstoreData() throws Exception
{
2547 TableName tableName
= name
.getTableName();
2548 createTableAndValidateTableSchemaModification(tableName
, true);
2551 @Test(timeout
= 60000)
2552 public void testDeleteCFWithMemstoreData() throws Exception
{
2553 TableName tableName
= name
.getTableName();
2554 createTableAndValidateTableSchemaModification(tableName
, false);
2558 * Create table and validate online schema modification
2559 * @param tableName Table name
2560 * @param modifyTable Modify table if true otherwise delete column family
2561 * @throws IOException in case of failures
2563 private void createTableAndValidateTableSchemaModification(TableName tableName
,
2564 boolean modifyTable
) throws Exception
{
2565 Admin admin
= TEST_UTIL
.getAdmin();
2566 // Create table with two Cfs
2567 byte[] cf1
= Bytes
.toBytes("cf1");
2568 byte[] cf2
= Bytes
.toBytes("cf2");
2569 TableDescriptor tableDesc
= TableDescriptorBuilder
.newBuilder(tableName
)
2570 .setColumnFamily(ColumnFamilyDescriptorBuilder
.of(cf1
))
2571 .setColumnFamily(ColumnFamilyDescriptorBuilder
.of(cf2
)).build();
2572 admin
.createTable(tableDesc
);
2574 Table t
= TEST_UTIL
.getConnection().getTable(tableName
);
2575 // Insert few records and flush the table
2576 t
.put(new Put(ROW
).addColumn(cf1
, QUALIFIER
, Bytes
.toBytes("val1")));
2577 t
.put(new Put(ROW
).addColumn(cf2
, QUALIFIER
, Bytes
.toBytes("val2")));
2578 admin
.flush(tableName
);
2579 Path tableDir
= FSUtils
.getTableDir(TEST_UTIL
.getDefaultRootDirPath(), tableName
);
2580 List
<Path
> regionDirs
= FSUtils
.getRegionDirs(TEST_UTIL
.getTestFileSystem(), tableDir
);
2581 assertEquals(1, regionDirs
.size());
2582 List
<Path
> familyDirs
= FSUtils
.getFamilyDirs(TEST_UTIL
.getTestFileSystem(), regionDirs
.get(0));
2583 assertEquals(2, familyDirs
.size());
2585 // Insert record but dont flush the table
2586 t
.put(new Put(ROW
).addColumn(cf1
, QUALIFIER
, Bytes
.toBytes("val2")));
2587 t
.put(new Put(ROW
).addColumn(cf2
, QUALIFIER
, Bytes
.toBytes("val2")));
2590 tableDesc
= TableDescriptorBuilder
.newBuilder(tableDesc
).removeColumnFamily(cf2
).build();
2591 admin
.modifyTable(tableDesc
);
2593 admin
.deleteColumnFamily(tableName
, cf2
);
2595 // After table modification or delete family there should be only one CF in FS
2596 familyDirs
= FSUtils
.getFamilyDirs(TEST_UTIL
.getTestFileSystem(), regionDirs
.get(0));
2597 assertEquals("CF dir count should be 1, but was " + familyDirs
.size(), 1, familyDirs
.size());