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
.regionserver
;
20 import static org
.junit
.Assert
.assertArrayEquals
;
21 import static org
.junit
.Assert
.assertTrue
;
22 import static org
.mockito
.Mockito
.doAnswer
;
23 import static org
.mockito
.Mockito
.spy
;
25 import java
.io
.IOException
;
26 import java
.util
.Collection
;
28 import org
.apache
.commons
.lang3
.mutable
.MutableBoolean
;
29 import org
.apache
.hadoop
.hbase
.DroppedSnapshotException
;
30 import org
.apache
.hadoop
.hbase
.HBaseClassTestRule
;
31 import org
.apache
.hadoop
.hbase
.HBaseTestingUtility
;
32 import org
.apache
.hadoop
.hbase
.HConstants
;
33 import org
.apache
.hadoop
.hbase
.NamespaceDescriptor
;
34 import org
.apache
.hadoop
.hbase
.TableName
;
35 import org
.apache
.hadoop
.hbase
.client
.Admin
;
36 import org
.apache
.hadoop
.hbase
.client
.ColumnFamilyDescriptorBuilder
;
37 import org
.apache
.hadoop
.hbase
.client
.Connection
;
38 import org
.apache
.hadoop
.hbase
.client
.Get
;
39 import org
.apache
.hadoop
.hbase
.client
.Put
;
40 import org
.apache
.hadoop
.hbase
.client
.Result
;
41 import org
.apache
.hadoop
.hbase
.client
.Table
;
42 import org
.apache
.hadoop
.hbase
.client
.TableDescriptorBuilder
;
43 import org
.apache
.hadoop
.hbase
.monitoring
.MonitoredTask
;
44 import org
.apache
.hadoop
.hbase
.regionserver
.HRegion
.FlushResult
;
45 import org
.apache
.hadoop
.hbase
.regionserver
.HRegion
.PrepareFlushResult
;
46 import org
.apache
.hadoop
.hbase
.testclassification
.LargeTests
;
47 import org
.apache
.hadoop
.hbase
.util
.Bytes
;
48 import org
.apache
.hadoop
.hbase
.util
.EnvironmentEdgeManager
;
49 import org
.apache
.hadoop
.hbase
.wal
.WAL
;
50 import org
.junit
.After
;
51 import org
.junit
.Before
;
52 import org
.junit
.ClassRule
;
53 import org
.junit
.Test
;
54 import org
.junit
.experimental
.categories
.Category
;
55 import org
.mockito
.Matchers
;
56 import org
.mockito
.invocation
.InvocationOnMock
;
57 import org
.mockito
.stubbing
.Answer
;
58 import org
.slf4j
.Logger
;
59 import org
.slf4j
.LoggerFactory
;
62 * Testcase for https://issues.apache.org/jira/browse/HBASE-13811
64 @Category({ LargeTests
.class })
65 public class TestSplitWalDataLoss
{
68 public static final HBaseClassTestRule CLASS_RULE
=
69 HBaseClassTestRule
.forClass(TestSplitWalDataLoss
.class);
71 private static final Logger LOG
= LoggerFactory
.getLogger(TestSplitWalDataLoss
.class);
73 private final HBaseTestingUtility testUtil
= new HBaseTestingUtility();
75 private NamespaceDescriptor namespace
= NamespaceDescriptor
.create(getClass().getSimpleName())
78 private TableName tableName
= TableName
.valueOf(namespace
.getName(), "dataloss");
80 private byte[] family
= Bytes
.toBytes("f");
82 private byte[] qualifier
= Bytes
.toBytes("q");
85 public void setUp() throws Exception
{
86 testUtil
.getConfiguration().setInt("hbase.regionserver.msginterval", 30000);
87 testUtil
.startMiniCluster(2);
88 Admin admin
= testUtil
.getAdmin();
89 admin
.createNamespace(namespace
);
90 admin
.createTable(TableDescriptorBuilder
.newBuilder(tableName
)
91 .setColumnFamily(ColumnFamilyDescriptorBuilder
.of(family
)).build());
92 testUtil
.waitTableAvailable(tableName
);
96 public void tearDown() throws Exception
{
97 testUtil
.shutdownMiniCluster();
101 public void test() throws IOException
, InterruptedException
{
102 final HRegionServer rs
= testUtil
.getRSForFirstRegionInTable(tableName
);
103 final HRegion region
= (HRegion
) rs
.getRegions(tableName
).get(0);
104 HRegion spiedRegion
= spy(region
);
105 final MutableBoolean flushed
= new MutableBoolean(false);
106 final MutableBoolean reported
= new MutableBoolean(false);
107 doAnswer(new Answer
<FlushResult
>() {
109 public FlushResult
answer(InvocationOnMock invocation
) throws Throwable
{
110 synchronized (flushed
) {
111 flushed
.setValue(true);
114 synchronized (reported
) {
115 while (!reported
.booleanValue()) {
119 rs
.getWAL(region
.getRegionInfo()).abortCacheFlush(
120 region
.getRegionInfo().getEncodedNameAsBytes());
121 throw new DroppedSnapshotException("testcase");
123 }).when(spiedRegion
).internalFlushCacheAndCommit(Matchers
.<WAL
> any(),
124 Matchers
.<MonitoredTask
> any(), Matchers
.<PrepareFlushResult
> any(),
125 Matchers
.<Collection
<HStore
>> any());
126 // Find region key; don't pick up key for hbase:meta by mistake.
128 for (Map
.Entry
<String
, HRegion
> entry
: rs
.getOnlineRegions().entrySet()) {
129 if (entry
.getValue().getRegionInfo().getTable().equals(this.tableName
)) {
130 key
= entry
.getKey();
134 rs
.getOnlineRegions().put(key
, spiedRegion
);
135 Connection conn
= testUtil
.getConnection();
137 try (Table table
= conn
.getTable(tableName
)) {
138 table
.put(new Put(Bytes
.toBytes("row0"))
139 .addColumn(family
, qualifier
, Bytes
.toBytes("val0")));
141 long oldestSeqIdOfStore
= region
.getOldestSeqIdOfStore(family
);
142 LOG
.info("CHANGE OLDEST " + oldestSeqIdOfStore
);
143 assertTrue(oldestSeqIdOfStore
> HConstants
.NO_SEQNUM
);
144 rs
.getMemStoreFlusher().requestFlush(spiedRegion
, false, FlushLifeCycleTracker
.DUMMY
);
145 synchronized (flushed
) {
146 while (!flushed
.booleanValue()) {
150 try (Table table
= conn
.getTable(tableName
)) {
151 table
.put(new Put(Bytes
.toBytes("row1"))
152 .addColumn(family
, qualifier
, Bytes
.toBytes("val1")));
154 long now
= EnvironmentEdgeManager
.currentTime();
155 rs
.tryRegionServerReport(now
- 500, now
);
156 synchronized (reported
) {
157 reported
.setValue(true);
158 reported
.notifyAll();
160 while (testUtil
.getRSForFirstRegionInTable(tableName
) == rs
) {
163 try (Table table
= conn
.getTable(tableName
)) {
164 Result result
= table
.get(new Get(Bytes
.toBytes("row0")));
165 assertArrayEquals(Bytes
.toBytes("val0"), result
.getValue(family
, qualifier
));