1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.hadoop.hbase.master.procedure;
20
21 import org.apache.commons.logging.Log;
22 import org.apache.commons.logging.LogFactory;
23 import org.apache.hadoop.conf.Configuration;
24 import org.apache.hadoop.hbase.HBaseTestingUtility;
25 import org.apache.hadoop.hbase.HTableDescriptor;
26 import org.apache.hadoop.hbase.HRegionInfo;
27 import org.apache.hadoop.hbase.ProcedureInfo;
28 import org.apache.hadoop.hbase.TableName;
29 import org.apache.hadoop.hbase.TableNotDisabledException;
30 import org.apache.hadoop.hbase.TableNotFoundException;
31 import org.apache.hadoop.hbase.procedure2.ProcedureExecutor;
32 import org.apache.hadoop.hbase.procedure2.ProcedureTestingUtility;
33 import org.apache.hadoop.hbase.protobuf.generated.MasterProcedureProtos.TruncateTableState;
34 import org.apache.hadoop.hbase.testclassification.MediumTests;
35 import org.apache.hadoop.hbase.util.Bytes;
36
37 import org.junit.After;
38 import org.junit.AfterClass;
39 import org.junit.Before;
40 import org.junit.BeforeClass;
41 import org.junit.Test;
42 import org.junit.experimental.categories.Category;
43
44 import static org.junit.Assert.assertEquals;
45 import static org.junit.Assert.assertFalse;
46 import static org.junit.Assert.assertTrue;
47 import static org.junit.Assert.fail;
48
49 @Category(MediumTests.class)
50 public class TestTruncateTableProcedure {
51 private static final Log LOG = LogFactory.getLog(TestTruncateTableProcedure.class);
52
53 protected static final HBaseTestingUtility UTIL = new HBaseTestingUtility();
54
55 private static void setupConf(Configuration conf) {
56 conf.setInt(MasterProcedureConstants.MASTER_PROCEDURE_THREADS, 1);
57 }
58
59 @BeforeClass
60 public static void setupCluster() throws Exception {
61 setupConf(UTIL.getConfiguration());
62 UTIL.startMiniCluster(1);
63 }
64
65 @AfterClass
66 public static void cleanupTest() throws Exception {
67 try {
68 UTIL.shutdownMiniCluster();
69 } catch (Exception e) {
70 LOG.warn("failure shutting down cluster", e);
71 }
72 }
73
74 @Before
75 public void setup() throws Exception {
76 final ProcedureExecutor<MasterProcedureEnv> procExec = getMasterProcedureExecutor();
77 ProcedureTestingUtility.setKillAndToggleBeforeStoreUpdate(procExec, false);
78 assertTrue("expected executor to be running", procExec.isRunning());
79 }
80
81 @After
82 public void tearDown() throws Exception {
83 ProcedureTestingUtility.setKillAndToggleBeforeStoreUpdate(getMasterProcedureExecutor(), false);
84 for (HTableDescriptor htd: UTIL.getHBaseAdmin().listTables()) {
85 LOG.info("Tear down, remove table=" + htd.getTableName());
86 UTIL.deleteTable(htd.getTableName());
87 }
88 }
89
90 @Test(timeout=60000)
91 public void testTruncateNotExistentTable() throws Exception {
92 final TableName tableName = TableName.valueOf("testTruncateNotExistentTable");
93
94 final ProcedureExecutor<MasterProcedureEnv> procExec = getMasterProcedureExecutor();
95 long procId = ProcedureTestingUtility.submitAndWait(procExec,
96 new TruncateTableProcedure(procExec.getEnvironment(), tableName, true));
97
98
99 ProcedureInfo result = procExec.getResult(procId);
100 assertTrue(result.isFailed());
101 LOG.debug("Truncate failed with exception: " + result.getExceptionFullMessage());
102 assertTrue(ProcedureTestingUtility.getExceptionCause(result) instanceof TableNotFoundException);
103 }
104
105 @Test(timeout=60000)
106 public void testTruncateNotDisabledTable() throws Exception {
107 final TableName tableName = TableName.valueOf("testTruncateNotDisabledTable");
108
109 final ProcedureExecutor<MasterProcedureEnv> procExec = getMasterProcedureExecutor();
110 MasterProcedureTestingUtility.createTable(procExec, tableName, null, "f");
111
112 long procId = ProcedureTestingUtility.submitAndWait(procExec,
113 new TruncateTableProcedure(procExec.getEnvironment(), tableName, false));
114
115
116 ProcedureInfo result = procExec.getResult(procId);
117 assertTrue(result.isFailed());
118 LOG.debug("Truncate failed with exception: " + result.getExceptionFullMessage());
119 assertTrue(
120 ProcedureTestingUtility.getExceptionCause(result) instanceof TableNotDisabledException);
121 }
122
123 @Test(timeout=60000)
124 public void testSimpleTruncatePreserveSplits() throws Exception {
125 final TableName tableName = TableName.valueOf("testSimpleTruncatePreserveSplits");
126 testSimpleTruncate(tableName, true);
127 }
128
129 @Test(timeout=60000)
130 public void testSimpleTruncateNoPreserveSplits() throws Exception {
131 final TableName tableName = TableName.valueOf("testSimpleTruncateNoPreserveSplits");
132 testSimpleTruncate(tableName, false);
133 }
134
135 private void testSimpleTruncate(final TableName tableName, final boolean preserveSplits)
136 throws Exception {
137 final String[] families = new String[] { "f1", "f2" };
138 final byte[][] splitKeys = new byte[][] {
139 Bytes.toBytes("a"), Bytes.toBytes("b"), Bytes.toBytes("c")
140 };
141
142 HRegionInfo[] regions = MasterProcedureTestingUtility.createTable(
143 getMasterProcedureExecutor(), tableName, splitKeys, families);
144
145 MasterProcedureTestingUtility.loadData(
146 UTIL.getConnection(), tableName, 100, splitKeys, families);
147 assertEquals(100, UTIL.countRows(tableName));
148
149 UTIL.getHBaseAdmin().disableTable(tableName);
150
151
152 final ProcedureExecutor<MasterProcedureEnv> procExec = getMasterProcedureExecutor();
153 long procId = ProcedureTestingUtility.submitAndWait(procExec,
154 new TruncateTableProcedure(procExec.getEnvironment(), tableName, preserveSplits));
155 ProcedureTestingUtility.assertProcNotFailed(procExec, procId);
156
157 UTIL.waitUntilAllRegionsAssigned(tableName);
158
159
160 if (preserveSplits) {
161 assertEquals(1 + splitKeys.length, UTIL.getHBaseAdmin().getTableRegions(tableName).size());
162 } else {
163 regions = UTIL.getHBaseAdmin().getTableRegions(tableName).toArray(new HRegionInfo[1]);
164 assertEquals(1, regions.length);
165 }
166 MasterProcedureTestingUtility.validateTableCreation(
167 UTIL.getHBaseCluster().getMaster(), tableName, regions, families);
168
169
170 assertEquals(0, UTIL.countRows(tableName));
171
172
173 MasterProcedureTestingUtility.loadData(
174 UTIL.getConnection(), tableName, 50, splitKeys, families);
175 assertEquals(50, UTIL.countRows(tableName));
176 }
177
178 @Test(timeout=60000)
179 public void testRecoveryAndDoubleExecutionPreserveSplits() throws Exception {
180 final TableName tableName = TableName.valueOf("testRecoveryAndDoubleExecutionPreserveSplits");
181 testRecoveryAndDoubleExecution(tableName, true);
182 }
183
184 @Test(timeout=60000)
185 public void testRecoveryAndDoubleExecutionNoPreserveSplits() throws Exception {
186 final TableName tableName = TableName.valueOf("testRecoveryAndDoubleExecutionNoPreserveSplits");
187 testRecoveryAndDoubleExecution(tableName, false);
188 }
189
190 private void testRecoveryAndDoubleExecution(final TableName tableName,
191 final boolean preserveSplits) throws Exception {
192 final String[] families = new String[] { "f1", "f2" };
193
194
195 final byte[][] splitKeys = new byte[][] {
196 Bytes.toBytes("a"), Bytes.toBytes("b"), Bytes.toBytes("c")
197 };
198 HRegionInfo[] regions = MasterProcedureTestingUtility.createTable(
199 getMasterProcedureExecutor(), tableName, splitKeys, families);
200
201 MasterProcedureTestingUtility.loadData(
202 UTIL.getConnection(), tableName, 100, splitKeys, families);
203 assertEquals(100, UTIL.countRows(tableName));
204
205 UTIL.getHBaseAdmin().disableTable(tableName);
206
207 final ProcedureExecutor<MasterProcedureEnv> procExec = getMasterProcedureExecutor();
208 ProcedureTestingUtility.waitNoProcedureRunning(procExec);
209 ProcedureTestingUtility.setKillAndToggleBeforeStoreUpdate(procExec, true);
210
211
212 long procId = procExec.submitProcedure(
213 new TruncateTableProcedure(procExec.getEnvironment(), tableName, preserveSplits));
214
215
216
217
218 MasterProcedureTestingUtility.testRecoveryAndDoubleExecution(
219 procExec, procId, 7, TruncateTableState.values());
220
221 ProcedureTestingUtility.setKillAndToggleBeforeStoreUpdate(procExec, false);
222 UTIL.waitUntilAllRegionsAssigned(tableName);
223
224
225 if (preserveSplits) {
226 assertEquals(1 + splitKeys.length, UTIL.getHBaseAdmin().getTableRegions(tableName).size());
227 } else {
228 regions = UTIL.getHBaseAdmin().getTableRegions(tableName).toArray(new HRegionInfo[1]);
229 assertEquals(1, regions.length);
230 }
231 MasterProcedureTestingUtility.validateTableCreation(
232 UTIL.getHBaseCluster().getMaster(), tableName, regions, families);
233
234
235 assertEquals(0, UTIL.countRows(tableName));
236
237
238 MasterProcedureTestingUtility.loadData(
239 UTIL.getConnection(), tableName, 50, splitKeys, families);
240 assertEquals(50, UTIL.countRows(tableName));
241 }
242
243 private ProcedureExecutor<MasterProcedureEnv> getMasterProcedureExecutor() {
244 return UTIL.getHBaseCluster().getMaster().getMasterProcedureExecutor();
245 }
246 }