HBASE-24033 Add ut for loading the corrupt recovered hfiles (#1322)
[hbase.git] / hbase-server / src / test / java / org / apache / hadoop / hbase / regionserver / TestSplitWalDataLoss.java
blob0de5cb0d8c6fe7475f1ec63fed704fe7d87012a7
1 /**
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;
27 import java.util.Map;
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;
61 /**
62 * Testcase for https://issues.apache.org/jira/browse/HBASE-13811
64 @Category({ LargeTests.class })
65 public class TestSplitWalDataLoss {
67 @ClassRule
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())
76 .build();
78 private TableName tableName = TableName.valueOf(namespace.getName(), "dataloss");
80 private byte[] family = Bytes.toBytes("f");
82 private byte[] qualifier = Bytes.toBytes("q");
84 @Before
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);
95 @After
96 public void tearDown() throws Exception {
97 testUtil.shutdownMiniCluster();
100 @Test
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>() {
108 @Override
109 public FlushResult answer(InvocationOnMock invocation) throws Throwable {
110 synchronized (flushed) {
111 flushed.setValue(true);
112 flushed.notifyAll();
114 synchronized (reported) {
115 while (!reported.booleanValue()) {
116 reported.wait();
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.
127 String key = null;
128 for (Map.Entry<String, HRegion> entry: rs.getOnlineRegions().entrySet()) {
129 if (entry.getValue().getRegionInfo().getTable().equals(this.tableName)) {
130 key = entry.getKey();
131 break;
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()) {
147 flushed.wait();
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) {
161 Thread.sleep(100);
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));