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