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 = procExec.submitProcedure(
93 new DeleteColumnFamilyProcedure(procExec.getEnvironment(), tableName, cf1.getBytes()));
94
95 ProcedureTestingUtility.waitProcedure(procExec, procId1);
96 ProcedureTestingUtility.assertProcNotFailed(procExec, procId1);
97
98 MasterProcedureTestingUtility.validateColumnFamilyDeletion(UTIL.getHBaseCluster().getMaster(),
99 tableName, cf1);
100
101
102 UTIL.getHBaseAdmin().disableTable(tableName);
103 long procId2 = procExec.submitProcedure(
104 new DeleteColumnFamilyProcedure(procExec.getEnvironment(), tableName, cf2.getBytes()));
105
106 ProcedureTestingUtility.waitProcedure(procExec, procId2);
107 ProcedureTestingUtility.assertProcNotFailed(procExec, procId2);
108 }
109
110 @Test(timeout=60000)
111 public void testDeleteColumnFamilyTwice() throws Exception {
112 final TableName tableName = TableName.valueOf("testDeleteColumnFamilyTwice");
113 final ProcedureExecutor<MasterProcedureEnv> procExec = getMasterProcedureExecutor();
114
115 final String cf2 = "cf2";
116
117 MasterProcedureTestingUtility.createTable(procExec, tableName, null, "f1", cf2);
118
119
120 long procId1 = procExec.submitProcedure(
121 new DeleteColumnFamilyProcedure(procExec.getEnvironment(), tableName, cf2.getBytes()));
122
123 ProcedureTestingUtility.waitProcedure(procExec, procId1);
124
125 ProcedureTestingUtility.assertProcNotFailed(procExec, procId1);
126
127 MasterProcedureTestingUtility.validateColumnFamilyDeletion(UTIL.getHBaseCluster().getMaster(),
128 tableName, cf2);
129
130
131 long procId2 = procExec.submitProcedure(
132 new DeleteColumnFamilyProcedure(procExec.getEnvironment(), tableName, cf2.getBytes()));
133
134
135 ProcedureTestingUtility.waitProcedure(procExec, procId2);
136
137
138 ProcedureInfo result = procExec.getResult(procId2);
139 assertTrue(result.isFailed());
140 LOG.debug("Delete online failed with exception: " + result.getExceptionFullMessage());
141 assertTrue(
142 ProcedureTestingUtility.getExceptionCause(result) instanceof InvalidFamilyOperationException);
143
144
145 UTIL.getHBaseAdmin().disableTable(tableName);
146 long procId3 = procExec.submitProcedure(
147 new DeleteColumnFamilyProcedure(procExec.getEnvironment(), tableName, cf2.getBytes()));
148
149 ProcedureTestingUtility.waitProcedure(procExec, procId3);
150
151 result = procExec.getResult(procId2);
152 assertTrue(result.isFailed());
153 LOG.debug("Delete offline failed with exception: " + result.getExceptionFullMessage());
154 assertTrue(
155 ProcedureTestingUtility.getExceptionCause(result) instanceof InvalidFamilyOperationException);
156 }
157
158 @Test(timeout=60000)
159 public void testDeleteNonExistingColumnFamily() throws Exception {
160 final TableName tableName = TableName.valueOf("testDeleteNonExistingColumnFamily");
161 final ProcedureExecutor<MasterProcedureEnv> procExec = getMasterProcedureExecutor();
162
163 final String cf3 = "cf3";
164
165 MasterProcedureTestingUtility.createTable(procExec, tableName, null, "f1", "f2");
166
167
168 long procId1 = procExec.submitProcedure(
169 new DeleteColumnFamilyProcedure(procExec.getEnvironment(), tableName, cf3.getBytes()));
170
171 ProcedureTestingUtility.waitProcedure(procExec, procId1);
172
173 ProcedureInfo result = procExec.getResult(procId1);
174 assertTrue(result.isFailed());
175 LOG.debug("Delete failed with exception: " + result.getExceptionFullMessage());
176 assertTrue(
177 ProcedureTestingUtility.getExceptionCause(result) instanceof InvalidFamilyOperationException);
178 }
179
180 @Test(timeout=60000)
181 public void testRecoveryAndDoubleExecutionOffline() throws Exception {
182 final TableName tableName = TableName.valueOf("testRecoveryAndDoubleExecutionOffline");
183 final String cf4 = "cf4";
184
185 final ProcedureExecutor<MasterProcedureEnv> procExec = getMasterProcedureExecutor();
186
187
188 MasterProcedureTestingUtility.createTable(procExec, tableName, null, "f1", "f2", "f3", cf4);
189 UTIL.getHBaseAdmin().disableTable(tableName);
190 ProcedureTestingUtility.waitNoProcedureRunning(procExec);
191 ProcedureTestingUtility.setKillAndToggleBeforeStoreUpdate(procExec, true);
192
193
194 long procId = procExec.submitProcedure(
195 new DeleteColumnFamilyProcedure(procExec.getEnvironment(), tableName, cf4.getBytes()));
196
197
198 int numberOfSteps = DeleteColumnFamilyState.values().length;
199 MasterProcedureTestingUtility.testRecoveryAndDoubleExecution(procExec, procId, numberOfSteps,
200 DeleteColumnFamilyState.values());
201
202 MasterProcedureTestingUtility.validateColumnFamilyDeletion(UTIL.getHBaseCluster().getMaster(),
203 tableName, cf4);
204 }
205
206 @Test(timeout = 60000)
207 public void testRecoveryAndDoubleExecutionOnline() throws Exception {
208 final TableName tableName = TableName.valueOf("testRecoveryAndDoubleExecutionOnline");
209 final String cf5 = "cf5";
210
211 final ProcedureExecutor<MasterProcedureEnv> procExec = getMasterProcedureExecutor();
212
213
214 MasterProcedureTestingUtility.createTable(procExec, tableName, null, "f1", "f2", "f3", cf5);
215 ProcedureTestingUtility.waitNoProcedureRunning(procExec);
216 ProcedureTestingUtility.setKillAndToggleBeforeStoreUpdate(procExec, true);
217
218
219 long procId = procExec.submitProcedure(
220 new DeleteColumnFamilyProcedure(procExec.getEnvironment(), tableName, cf5.getBytes()));
221
222
223 int numberOfSteps = DeleteColumnFamilyState.values().length;
224 MasterProcedureTestingUtility.testRecoveryAndDoubleExecution(procExec, procId, numberOfSteps,
225 DeleteColumnFamilyState.values());
226
227 MasterProcedureTestingUtility.validateColumnFamilyDeletion(UTIL.getHBaseCluster().getMaster(),
228 tableName, cf5);
229 }
230
231 @Test(timeout = 60000)
232 public void testRollbackAndDoubleExecution() throws Exception {
233 final TableName tableName = TableName.valueOf("testRollbackAndDoubleExecution");
234 final String cf5 = "cf5";
235
236 final ProcedureExecutor<MasterProcedureEnv> procExec = getMasterProcedureExecutor();
237
238
239 HRegionInfo[] regions = MasterProcedureTestingUtility.createTable(
240 procExec, tableName, null, "f1", "f2", "f3", cf5);
241 ProcedureTestingUtility.waitNoProcedureRunning(procExec);
242 ProcedureTestingUtility.setKillAndToggleBeforeStoreUpdate(procExec, true);
243
244
245 long procId = procExec.submitProcedure(
246 new DeleteColumnFamilyProcedure(procExec.getEnvironment(), tableName, cf5.getBytes()));
247
248
249
250
251 int numberOfSteps = 1;
252 MasterProcedureTestingUtility.testRollbackAndDoubleExecution(
253 procExec,
254 procId,
255 numberOfSteps,
256 DeleteColumnFamilyState.values());
257
258 MasterProcedureTestingUtility.validateTableCreation(
259 UTIL.getHBaseCluster().getMaster(), tableName, regions, "f1", "f2", "f3", cf5);
260 }
261
262 @Test(timeout = 60000)
263 public void testRollbackAndDoubleExecutionAfterPONR() throws Exception {
264 final TableName tableName = TableName.valueOf("testRollbackAndDoubleExecutionAfterPONR");
265 final String cf5 = "cf5";
266
267 final ProcedureExecutor<MasterProcedureEnv> procExec = getMasterProcedureExecutor();
268
269
270 HRegionInfo[] regions = MasterProcedureTestingUtility.createTable(
271 procExec, tableName, null, "f1", "f2", "f3", cf5);
272 ProcedureTestingUtility.waitNoProcedureRunning(procExec);
273 ProcedureTestingUtility.setKillAndToggleBeforeStoreUpdate(procExec, true);
274
275
276 long procId = procExec.submitProcedure(
277 new DeleteColumnFamilyProcedure(procExec.getEnvironment(), tableName, cf5.getBytes()));
278
279
280
281
282 int numberOfSteps = 4;
283 MasterProcedureTestingUtility.testRollbackAndDoubleExecutionAfterPONR(
284 procExec,
285 procId,
286 numberOfSteps,
287 DeleteColumnFamilyState.values());
288
289 MasterProcedureTestingUtility.validateColumnFamilyDeletion(
290 UTIL.getHBaseCluster().getMaster(), tableName, cf5);
291 }
292
293 private ProcedureExecutor<MasterProcedureEnv> getMasterProcedureExecutor() {
294 return UTIL.getHBaseCluster().getMaster().getMasterProcedureExecutor();
295 }
296 }