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.DeleteTableState;
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 TestDeleteTableProcedure {
51 private static final Log LOG = LogFactory.getLog(TestDeleteTableProcedure.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, expected=TableNotFoundException.class)
91 public void testDeleteNotExistentTable() throws Exception {
92 final TableName tableName = TableName.valueOf("testDeleteNotExistentTable");
93
94 final ProcedureExecutor<MasterProcedureEnv> procExec = getMasterProcedureExecutor();
95 ProcedurePrepareLatch latch = new ProcedurePrepareLatch.CompatibilityLatch();
96 long procId = ProcedureTestingUtility.submitAndWait(procExec,
97 new DeleteTableProcedure(procExec.getEnvironment(), tableName, latch));
98 latch.await();
99 }
100
101 @Test(timeout=60000, expected=TableNotDisabledException.class)
102 public void testDeleteNotDisabledTable() throws Exception {
103 final TableName tableName = TableName.valueOf("testDeleteNotDisabledTable");
104
105 final ProcedureExecutor<MasterProcedureEnv> procExec = getMasterProcedureExecutor();
106 MasterProcedureTestingUtility.createTable(procExec, tableName, null, "f");
107
108 ProcedurePrepareLatch latch = new ProcedurePrepareLatch.CompatibilityLatch();
109 long procId = ProcedureTestingUtility.submitAndWait(procExec,
110 new DeleteTableProcedure(procExec.getEnvironment(), tableName, latch));
111 latch.await();
112 }
113
114 @Test(timeout=60000)
115 public void testDeleteDeletedTable() throws Exception {
116 final TableName tableName = TableName.valueOf("testDeleteDeletedTable");
117 final ProcedureExecutor<MasterProcedureEnv> procExec = getMasterProcedureExecutor();
118
119 HRegionInfo[] regions = MasterProcedureTestingUtility.createTable(
120 procExec, tableName, null, "f");
121 UTIL.getHBaseAdmin().disableTable(tableName);
122
123
124 long procId1 = procExec.submitProcedure(
125 new DeleteTableProcedure(procExec.getEnvironment(), tableName));
126
127 long procId2 = procExec.submitProcedure(
128 new DeleteTableProcedure(procExec.getEnvironment(), tableName));
129
130
131 ProcedureTestingUtility.waitProcedure(procExec, procId1);
132 ProcedureTestingUtility.waitProcedure(procExec, procId2);
133
134
135 ProcedureTestingUtility.assertProcNotFailed(procExec, procId1);
136 MasterProcedureTestingUtility.validateTableDeletion(
137 UTIL.getHBaseCluster().getMaster(), tableName, regions, "f");
138
139
140 ProcedureInfo result = procExec.getResult(procId2);
141 assertTrue(result.isFailed());
142 LOG.debug("Delete failed with exception: " + result.getExceptionFullMessage());
143 assertTrue(ProcedureTestingUtility.getExceptionCause(result) instanceof TableNotFoundException);
144 }
145
146 @Test(timeout=60000)
147 public void testSimpleDelete() throws Exception {
148 final TableName tableName = TableName.valueOf("testSimpleDelete");
149 final byte[][] splitKeys = null;
150 testSimpleDelete(tableName, splitKeys);
151 }
152
153 @Test(timeout=60000)
154 public void testSimpleDeleteWithSplits() throws Exception {
155 final TableName tableName = TableName.valueOf("testSimpleDeleteWithSplits");
156 final byte[][] splitKeys = new byte[][] {
157 Bytes.toBytes("a"), Bytes.toBytes("b"), Bytes.toBytes("c")
158 };
159 testSimpleDelete(tableName, splitKeys);
160 }
161
162 private void testSimpleDelete(final TableName tableName, byte[][] splitKeys) throws Exception {
163 HRegionInfo[] regions = MasterProcedureTestingUtility.createTable(
164 getMasterProcedureExecutor(), tableName, splitKeys, "f1", "f2");
165 UTIL.getHBaseAdmin().disableTable(tableName);
166
167
168 final ProcedureExecutor<MasterProcedureEnv> procExec = getMasterProcedureExecutor();
169 long procId = ProcedureTestingUtility.submitAndWait(procExec,
170 new DeleteTableProcedure(procExec.getEnvironment(), tableName));
171 ProcedureTestingUtility.assertProcNotFailed(procExec, procId);
172 MasterProcedureTestingUtility.validateTableDeletion(
173 UTIL.getHBaseCluster().getMaster(), tableName, regions, "f1", "f2");
174 }
175
176 @Test(timeout=60000)
177 public void testRecoveryAndDoubleExecution() throws Exception {
178 final TableName tableName = TableName.valueOf("testRecoveryAndDoubleExecution");
179
180
181 byte[][] splitKeys = null;
182 HRegionInfo[] regions = MasterProcedureTestingUtility.createTable(
183 getMasterProcedureExecutor(), tableName, splitKeys, "f1", "f2");
184 UTIL.getHBaseAdmin().disableTable(tableName);
185
186 final ProcedureExecutor<MasterProcedureEnv> procExec = getMasterProcedureExecutor();
187 ProcedureTestingUtility.waitNoProcedureRunning(procExec);
188 ProcedureTestingUtility.setKillAndToggleBeforeStoreUpdate(procExec, true);
189
190
191 long procId = procExec.submitProcedure(
192 new DeleteTableProcedure(procExec.getEnvironment(), tableName));
193
194
195
196
197 MasterProcedureTestingUtility.testRecoveryAndDoubleExecution(
198 procExec, procId, 6, DeleteTableState.values());
199
200 MasterProcedureTestingUtility.validateTableDeletion(
201 UTIL.getHBaseCluster().getMaster(), tableName, regions, "f1", "f2");
202 }
203
204 private ProcedureExecutor<MasterProcedureEnv> getMasterProcedureExecutor() {
205 return UTIL.getHBaseCluster().getMaster().getMasterProcedureExecutor();
206 }
207 }