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 static org.junit.Assert.assertTrue;
22
23 import org.apache.commons.logging.Log;
24 import org.apache.commons.logging.LogFactory;
25 import org.apache.hadoop.conf.Configuration;
26 import org.apache.hadoop.hbase.HBaseTestingUtility;
27 import org.apache.hadoop.hbase.HRegionInfo;
28 import org.apache.hadoop.hbase.HTableDescriptor;
29 import org.apache.hadoop.hbase.InvalidFamilyOperationException;
30 import org.apache.hadoop.hbase.ProcedureInfo;
31 import org.apache.hadoop.hbase.TableName;
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.DeleteColumnFamilyState;
35 import org.apache.hadoop.hbase.testclassification.MediumTests;
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 @Category(MediumTests.class)
44 public class TestDeleteColumnFamilyProcedure {
45 private static final Log LOG = LogFactory.getLog(TestDeleteColumnFamilyProcedure.class);
46
47 protected static final HBaseTestingUtility UTIL = new HBaseTestingUtility();
48
49 private static void setupConf(Configuration conf) {
50 conf.setInt(MasterProcedureConstants.MASTER_PROCEDURE_THREADS, 1);
51 }
52
53 @BeforeClass
54 public static void setupCluster() throws Exception {
55 setupConf(UTIL.getConfiguration());
56 UTIL.startMiniCluster(1);
57 }
58
59 @AfterClass
60 public static void cleanupTest() throws Exception {
61 try {
62 UTIL.shutdownMiniCluster();
63 } catch (Exception e) {
64 LOG.warn("failure shutting down cluster", e);
65 }
66 }
67
68 @Before
69 public void setup() throws Exception {
70 ProcedureTestingUtility.setKillAndToggleBeforeStoreUpdate(getMasterProcedureExecutor(), false);
71 }
72
73 @After
74 public void tearDown() throws Exception {
75 ProcedureTestingUtility.setKillAndToggleBeforeStoreUpdate(getMasterProcedureExecutor(), false);
76 for (HTableDescriptor htd: UTIL.getHBaseAdmin().listTables()) {
77 LOG.info("Tear down, remove table=" + htd.getTableName());
78 UTIL.deleteTable(htd.getTableName());
79 }
80 }
81
82 @Test(timeout = 60000)
83 public void testDeleteColumnFamily() throws Exception {
84 final TableName tableName = TableName.valueOf("testDeleteColumnFamily");
85 final ProcedureExecutor<MasterProcedureEnv> procExec = getMasterProcedureExecutor();
86 final String cf1 = "cf1";
87 final String cf2 = "cf2";
88
89 MasterProcedureTestingUtility.createTable(procExec, tableName, null, cf1, cf2, "f3");
90
91
92 long procId1 =
93 procExec.submitProcedure(new DeleteColumnFamilyProcedure(procExec.getEnvironment(),
94 tableName, cf1.getBytes()));
95
96 ProcedureTestingUtility.waitProcedure(procExec, procId1);
97 ProcedureTestingUtility.assertProcNotFailed(procExec, procId1);
98
99 MasterProcedureTestingUtility.validateColumnFamilyDeletion(UTIL.getHBaseCluster().getMaster(),
100 tableName, cf1);
101
102
103 UTIL.getHBaseAdmin().disableTable(tableName);
104 long procId2 =
105 procExec.submitProcedure(new DeleteColumnFamilyProcedure(procExec.getEnvironment(),
106 tableName, cf2.getBytes()));
107
108 ProcedureTestingUtility.waitProcedure(procExec, procId2);
109 ProcedureTestingUtility.assertProcNotFailed(procExec, procId2);
110 }
111
112 @Test(timeout=60000)
113 public void testDeleteColumnFamilyTwice() throws Exception {
114 final TableName tableName = TableName.valueOf("testDeleteColumnFamilyTwice");
115 final ProcedureExecutor<MasterProcedureEnv> procExec = getMasterProcedureExecutor();
116
117 final String cf2 = "cf2";
118
119 MasterProcedureTestingUtility.createTable(procExec, tableName, null, "f1", cf2);
120
121
122 long procId1 =
123 procExec.submitProcedure(new DeleteColumnFamilyProcedure(procExec.getEnvironment(),
124 tableName, cf2.getBytes()));
125
126 ProcedureTestingUtility.waitProcedure(procExec, procId1);
127
128 ProcedureTestingUtility.assertProcNotFailed(procExec, procId1);
129
130 MasterProcedureTestingUtility.validateColumnFamilyDeletion(UTIL.getHBaseCluster().getMaster(),
131 tableName, cf2);
132
133
134 long procId2 =
135 procExec.submitProcedure(new DeleteColumnFamilyProcedure(procExec.getEnvironment(),
136 tableName, cf2.getBytes()));
137
138
139 ProcedureTestingUtility.waitProcedure(procExec, procId2);
140
141
142 ProcedureInfo result = procExec.getResult(procId2);
143 assertTrue(result.isFailed());
144 LOG.debug("Delete online failed with exception: " + result.getExceptionFullMessage());
145 assertTrue(
146 ProcedureTestingUtility.getExceptionCause(result) instanceof InvalidFamilyOperationException);
147
148
149 UTIL.getHBaseAdmin().disableTable(tableName);
150 long procId3 =
151 procExec.submitProcedure(new DeleteColumnFamilyProcedure(procExec.getEnvironment(),
152 tableName, cf2.getBytes()));
153
154 ProcedureTestingUtility.waitProcedure(procExec, procId3);
155
156 result = procExec.getResult(procId2);
157 assertTrue(result.isFailed());
158 LOG.debug("Delete offline failed with exception: " + result.getExceptionFullMessage());
159 assertTrue(
160 ProcedureTestingUtility.getExceptionCause(result) instanceof InvalidFamilyOperationException);
161 }
162
163 @Test(timeout=60000)
164 public void testDeleteNonExistingColumnFamily() throws Exception {
165 final TableName tableName = TableName.valueOf("testDeleteNonExistingColumnFamily");
166 final ProcedureExecutor<MasterProcedureEnv> procExec = getMasterProcedureExecutor();
167
168 final String cf3 = "cf3";
169
170 MasterProcedureTestingUtility.createTable(procExec, tableName, null, "f1", "f2");
171
172
173 long procId1 =
174 procExec.submitProcedure(new DeleteColumnFamilyProcedure(procExec.getEnvironment(),
175 tableName, cf3.getBytes()));
176
177 ProcedureTestingUtility.waitProcedure(procExec, procId1);
178
179 ProcedureInfo result = procExec.getResult(procId1);
180 assertTrue(result.isFailed());
181 LOG.debug("Delete failed with exception: " + result.getExceptionFullMessage());
182 assertTrue(
183 ProcedureTestingUtility.getExceptionCause(result) instanceof InvalidFamilyOperationException);
184 }
185
186 @Test(timeout=60000)
187 public void testRecoveryAndDoubleExecutionOffline() throws Exception {
188 final TableName tableName = TableName.valueOf("testRecoveryAndDoubleExecutionOffline");
189 final String cf4 = "cf4";
190
191 final ProcedureExecutor<MasterProcedureEnv> procExec = getMasterProcedureExecutor();
192
193
194 MasterProcedureTestingUtility.createTable(procExec, tableName, null, "f1", "f2", "f3", cf4);
195 UTIL.getHBaseAdmin().disableTable(tableName);
196 ProcedureTestingUtility.waitNoProcedureRunning(procExec);
197 ProcedureTestingUtility.setKillAndToggleBeforeStoreUpdate(procExec, true);
198
199
200 long procId =
201 procExec.submitProcedure(new DeleteColumnFamilyProcedure(procExec.getEnvironment(),
202 tableName, cf4.getBytes()));
203
204
205 int numberOfSteps = DeleteColumnFamilyState.values().length;
206 MasterProcedureTestingUtility.testRecoveryAndDoubleExecution(procExec, procId, numberOfSteps,
207 DeleteColumnFamilyState.values());
208
209 MasterProcedureTestingUtility.validateColumnFamilyDeletion(UTIL.getHBaseCluster().getMaster(),
210 tableName, cf4);
211 }
212
213 @Test(timeout = 60000)
214 public void testRecoveryAndDoubleExecutionOnline() throws Exception {
215 final TableName tableName = TableName.valueOf("testRecoveryAndDoubleExecutionOnline");
216 final String cf5 = "cf5";
217
218 final ProcedureExecutor<MasterProcedureEnv> procExec = getMasterProcedureExecutor();
219
220
221 MasterProcedureTestingUtility.createTable(procExec, tableName, null, "f1", "f2", "f3", cf5);
222 ProcedureTestingUtility.waitNoProcedureRunning(procExec);
223 ProcedureTestingUtility.setKillAndToggleBeforeStoreUpdate(procExec, true);
224
225
226 long procId =
227 procExec.submitProcedure(new DeleteColumnFamilyProcedure(procExec.getEnvironment(),
228 tableName, cf5.getBytes()));
229
230
231 int numberOfSteps = DeleteColumnFamilyState.values().length;
232 MasterProcedureTestingUtility.testRecoveryAndDoubleExecution(procExec, procId, numberOfSteps,
233 DeleteColumnFamilyState.values());
234
235 MasterProcedureTestingUtility.validateColumnFamilyDeletion(UTIL.getHBaseCluster().getMaster(),
236 tableName, cf5);
237 }
238
239 @Test(timeout = 60000)
240 public void testRollbackAndDoubleExecution() throws Exception {
241 final TableName tableName = TableName.valueOf("testRollbackAndDoubleExecution");
242 final String cf5 = "cf5";
243
244 final ProcedureExecutor<MasterProcedureEnv> procExec = getMasterProcedureExecutor();
245
246
247 HRegionInfo[] regions = MasterProcedureTestingUtility.createTable(
248 procExec, tableName, null, "f1", "f2", "f3", cf5);
249 ProcedureTestingUtility.waitNoProcedureRunning(procExec);
250 ProcedureTestingUtility.setKillAndToggleBeforeStoreUpdate(procExec, true);
251
252
253 long procId = procExec.submitProcedure(
254 new DeleteColumnFamilyProcedure(procExec.getEnvironment(), tableName, cf5.getBytes()));
255
256
257
258
259 int numberOfSteps = 1;
260 MasterProcedureTestingUtility.testRollbackAndDoubleExecution(
261 procExec,
262 procId,
263 numberOfSteps,
264 DeleteColumnFamilyState.values());
265
266 MasterProcedureTestingUtility.validateTableCreation(
267 UTIL.getHBaseCluster().getMaster(), tableName, regions, "f1", "f2", "f3", cf5);
268 }
269
270 @Test(timeout = 60000)
271 public void testRollbackAndDoubleExecutionAfterPONR() throws Exception {
272 final TableName tableName = TableName.valueOf("testRollbackAndDoubleExecutionAfterPONR");
273 final String cf5 = "cf5";
274
275 final ProcedureExecutor<MasterProcedureEnv> procExec = getMasterProcedureExecutor();
276
277
278 HRegionInfo[] regions = MasterProcedureTestingUtility.createTable(
279 procExec, tableName, null, "f1", "f2", "f3", cf5);
280 ProcedureTestingUtility.waitNoProcedureRunning(procExec);
281 ProcedureTestingUtility.setKillAndToggleBeforeStoreUpdate(procExec, true);
282
283
284 long procId = procExec.submitProcedure(
285 new DeleteColumnFamilyProcedure(procExec.getEnvironment(), tableName, cf5.getBytes()));
286
287
288
289
290 int numberOfSteps = 4;
291 MasterProcedureTestingUtility.testRollbackAndDoubleExecutionAfterPONR(
292 procExec,
293 procId,
294 numberOfSteps,
295 DeleteColumnFamilyState.values());
296
297 MasterProcedureTestingUtility.validateColumnFamilyDeletion(
298 UTIL.getHBaseCluster().getMaster(), tableName, cf5);
299 }
300
301 private ProcedureExecutor<MasterProcedureEnv> getMasterProcedureExecutor() {
302 return UTIL.getHBaseCluster().getMaster().getMasterProcedureExecutor();
303 }
304 }