1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.hadoop.hbase.regionserver;
19
20 import static org.junit.Assert.assertEquals;
21 import static org.junit.Assert.assertNotNull;
22
23 import java.util.ArrayList;
24 import java.util.List;
25
26 import org.apache.hadoop.hbase.HBaseTestingUtility;
27 import org.apache.hadoop.hbase.HColumnDescriptor;
28 import org.apache.hadoop.hbase.HConstants;
29 import org.apache.hadoop.hbase.HTableDescriptor;
30 import org.apache.hadoop.hbase.TableName;
31 import org.apache.hadoop.hbase.client.Admin;
32 import org.apache.hadoop.hbase.client.Put;
33 import org.apache.hadoop.hbase.client.Scan;
34 import org.apache.hadoop.hbase.client.Table;
35 import org.apache.hadoop.hbase.master.cleaner.TimeToLiveHFileCleaner;
36 import org.apache.hadoop.hbase.regionserver.compactions.CompactionConfiguration;
37 import org.apache.hadoop.hbase.regionserver.wal.FSHLog;
38 import org.apache.hadoop.hbase.testclassification.LargeTests;
39 import org.apache.hadoop.hbase.util.Bytes;
40 import org.apache.hadoop.hbase.util.JVMClusterUtil;
41 import org.junit.After;
42 import org.junit.AfterClass;
43 import org.junit.Before;
44 import org.junit.BeforeClass;
45 import org.junit.Test;
46 import org.junit.experimental.categories.Category;
47 import org.slf4j.Logger;
48 import org.slf4j.LoggerFactory;
49
50 @Category({LargeTests.class})
51 public class TestCleanupCompactedFileAfterFailover {
52
53 private static final Logger LOG =
54 LoggerFactory.getLogger(TestCleanupCompactedFileAfterFailover.class);
55
56 private static HBaseTestingUtility TEST_UTIL;
57 private static Admin admin;
58 private static Table table;
59
60 private static TableName TABLE_NAME = TableName.valueOf("TestCleanupCompactedFileAfterFailover");
61 private static byte[] ROW = Bytes.toBytes("row");
62 private static byte[] FAMILY = Bytes.toBytes("cf");
63 private static byte[] QUALIFIER = Bytes.toBytes("cq");
64 private static byte[] VALUE = Bytes.toBytes("value");
65 private static final int RS_NUMBER = 5;
66
67 @BeforeClass
68 public static void beforeClass() throws Exception {
69 TEST_UTIL = new HBaseTestingUtility();
70
71 TEST_UTIL.getConfiguration().setInt(HConstants.HBASE_CLIENT_SCANNER_TIMEOUT_PERIOD, 1200000);
72 TEST_UTIL.getConfiguration()
73 .setInt(CompactionConfiguration.HBASE_HSTORE_COMPACTION_MIN_KEY, 100);
74 TEST_UTIL.getConfiguration().set("dfs.blocksize", "64000");
75 TEST_UTIL.getConfiguration().set("dfs.namenode.fs-limits.min-block-size", "1024");
76 TEST_UTIL.getConfiguration().set(TimeToLiveHFileCleaner.TTL_CONF_KEY, "0");
77 TEST_UTIL.startMiniCluster(RS_NUMBER);
78 admin = TEST_UTIL.getHBaseAdmin();
79 }
80
81 @AfterClass
82 public static void afterClass() throws Exception {
83 TEST_UTIL.shutdownMiniCluster();
84 }
85
86 @Before
87 public void before() throws Exception {
88 HTableDescriptor htd = new HTableDescriptor(TABLE_NAME);
89 htd.addFamily(new HColumnDescriptor(FAMILY));
90 admin.createTable(htd);
91 TEST_UTIL.waitTableAvailable(TABLE_NAME, 30000);
92 table = TEST_UTIL.getConnection().getTable(TABLE_NAME);
93 }
94
95 @After
96 public void after() throws Exception {
97 admin.disableTable(TABLE_NAME);
98 admin.deleteTable(TABLE_NAME);
99 }
100
101 @Test
102 public void testCleanupAfterFailoverWithCompactOnce() throws Exception {
103 testCleanupAfterFailover(1);
104 }
105
106 @Test
107 public void testCleanupAfterFailoverWithCompactTwice() throws Exception {
108 testCleanupAfterFailover(2);
109 }
110
111 @Test
112 public void testCleanupAfterFailoverWithCompactThreeTimes() throws Exception {
113 testCleanupAfterFailover(3);
114 }
115
116 private void testCleanupAfterFailover(int compactNum) throws Exception {
117 HRegionServer rsServedTable = null;
118 List<Region> regions = new ArrayList<>();
119 for (JVMClusterUtil.RegionServerThread rsThread : TEST_UTIL.getHBaseCluster()
120 .getLiveRegionServerThreads()) {
121 HRegionServer rs = rsThread.getRegionServer();
122 if (rs.getOnlineTables().contains(TABLE_NAME)) {
123 regions.addAll(rs.getOnlineRegions(TABLE_NAME));
124 rsServedTable = rs;
125 }
126 }
127 assertNotNull(rsServedTable);
128 assertEquals("Table should only have one region", 1, regions.size());
129 HRegion region = (HRegion)regions.get(0);
130 HStore store = (HStore)region.getStore(FAMILY);
131
132 writeDataAndFlush(3, region);
133 assertEquals(3, store.getStorefilesCount());
134
135
136 store.getScanner(new Scan(), null, Long.MAX_VALUE);
137
138 region.compact(true);
139 assertEquals(1, store.getStorefilesCount());
140
141 assertEquals(3, store.getStoreEngine().getStoreFileManager().getCompactedfiles().size());
142
143 for (int i = 1; i < compactNum; i++) {
144
145 region.compact(true);
146 assertEquals(1, store.getStorefilesCount());
147 store.closeAndArchiveCompactedFiles();
148
149 assertEquals(3, store.getStoreEngine().getStoreFileManager().getCompactedfiles().size());
150 }
151
152 int walNum = ((FSHLog)(rsServedTable.getWAL(null))).getNumLogFiles();
153
154 rsServedTable.walRoller.requestRollAll();
155
156 region.flush(true);
157
158 assertEquals("The old WAL should be archived", walNum,
159 ((FSHLog)(rsServedTable.getWAL(null))).getNumLogFiles());
160
161 rsServedTable.kill();
162
163 Thread.sleep(3000);
164 TEST_UTIL.waitTableAvailable(TABLE_NAME, 30000);
165
166 regions.clear();
167 for (JVMClusterUtil.RegionServerThread rsThread : TEST_UTIL.getHBaseCluster()
168 .getLiveRegionServerThreads()) {
169 HRegionServer rs = rsThread.getRegionServer();
170 if (rs != rsServedTable && rs.getOnlineTables().contains(TABLE_NAME)) {
171 regions.addAll(rs.getOnlineRegions(TABLE_NAME));
172 }
173 }
174 assertEquals("Table should only have one region", 1, regions.size());
175 region = (HRegion)regions.get(0);
176 store = (HStore)region.getStore(FAMILY);
177
178 assertEquals(1, store.getStorefilesCount());
179 }
180
181 private void writeDataAndFlush(int fileNum, HRegion region) throws Exception {
182 for (int i = 0; i < fileNum; i++) {
183 for (int j = 0; j < 100; j++) {
184 table.put(new Put(concat(ROW, j)).addColumn(FAMILY, QUALIFIER, concat(VALUE, j)));
185 }
186 region.flush(true);
187 }
188 }
189
190 private byte[] concat(byte[] base, int index) {
191 return Bytes.toBytes(Bytes.toString(base) + "-" + index);
192 }
193 }