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