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.HConstants;
28 import org.apache.hadoop.hbase.HTableDescriptor;
29 import org.apache.hadoop.hbase.ProcedureInfo;
30 import org.apache.hadoop.hbase.TableName;
31 import org.apache.hadoop.hbase.TableNotEnabledException;
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.DisableTableState;
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.Assert;
40 import org.junit.Before;
41 import org.junit.BeforeClass;
42 import org.junit.Test;
43 import org.junit.experimental.categories.Category;
44
45 @Category(MediumTests.class)
46 public class TestDisableTableProcedure {
47 private static final Log LOG = LogFactory.getLog(TestDisableTableProcedure.class);
48
49 protected static final HBaseTestingUtility UTIL = new HBaseTestingUtility();
50
51 private static long nonceGroup = HConstants.NO_NONCE;
52 private static long nonce = HConstants.NO_NONCE;
53
54 private static void setupConf(Configuration conf) {
55 conf.setInt(MasterProcedureConstants.MASTER_PROCEDURE_THREADS, 1);
56 }
57
58 @BeforeClass
59 public static void setupCluster() throws Exception {
60 setupConf(UTIL.getConfiguration());
61 UTIL.startMiniCluster(1);
62 }
63
64 @AfterClass
65 public static void cleanupTest() throws Exception {
66 try {
67 UTIL.shutdownMiniCluster();
68 } catch (Exception e) {
69 LOG.warn("failure shutting down cluster", e);
70 }
71 }
72
73 @Before
74 public void setup() throws Exception {
75 ProcedureTestingUtility.setKillAndToggleBeforeStoreUpdate(getMasterProcedureExecutor(), false);
76 nonceGroup =
77 MasterProcedureTestingUtility.generateNonceGroup(UTIL.getHBaseCluster().getMaster());
78 nonce = MasterProcedureTestingUtility.generateNonce(UTIL.getHBaseCluster().getMaster());
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)
91 public void testDisableTable() throws Exception {
92 final TableName tableName = TableName.valueOf("testDisableTable");
93 final ProcedureExecutor<MasterProcedureEnv> procExec = getMasterProcedureExecutor();
94
95 MasterProcedureTestingUtility.createTable(procExec, tableName, null, "f1", "f2");
96
97
98 long procId = procExec.submitProcedure(
99 new DisableTableProcedure(procExec.getEnvironment(), tableName, false), nonceGroup, nonce);
100
101 ProcedureTestingUtility.waitProcedure(procExec, procId);
102 ProcedureTestingUtility.assertProcNotFailed(procExec, procId);
103 MasterProcedureTestingUtility.validateTableIsDisabled(UTIL.getHBaseCluster().getMaster(),
104 tableName);
105 }
106
107 @Test(timeout = 60000)
108 public void testDisableTableMultipleTimes() throws Exception {
109 final TableName tableName = TableName.valueOf("testDisableTableMultipleTimes");
110 final ProcedureExecutor<MasterProcedureEnv> procExec = getMasterProcedureExecutor();
111
112 MasterProcedureTestingUtility.createTable(procExec, tableName, null, "f1", "f2");
113
114
115 long procId1 = procExec.submitProcedure(new DisableTableProcedure(
116 procExec.getEnvironment(), tableName, false), nonceGroup, nonce);
117
118 ProcedureTestingUtility.waitProcedure(procExec, procId1);
119 ProcedureTestingUtility.assertProcNotFailed(procExec, procId1);
120 MasterProcedureTestingUtility.validateTableIsDisabled(UTIL.getHBaseCluster().getMaster(),
121 tableName);
122
123
124 long procId2 = procExec.submitProcedure(new DisableTableProcedure(
125 procExec.getEnvironment(), tableName, false), nonceGroup + 1, nonce + 1);
126
127 ProcedureTestingUtility.waitProcedure(procExec, procId2);
128 ProcedureInfo result = procExec.getResult(procId2);
129 assertTrue(result.isFailed());
130 LOG.debug("Disable failed with exception: " + result.getExceptionFullMessage());
131 assertTrue(
132 ProcedureTestingUtility.getExceptionCause(result) instanceof TableNotEnabledException);
133
134
135 try {
136 final ProcedurePrepareLatch prepareLatch = new ProcedurePrepareLatch.CompatibilityLatch();
137
138 long procId3 = procExec.submitProcedure(new DisableTableProcedure(
139 procExec.getEnvironment(), tableName, false, prepareLatch), nonceGroup + 2, nonce + 2);
140 prepareLatch.await();
141 Assert.fail("Disable should throw exception through latch.");
142 } catch (TableNotEnabledException tnee) {
143
144 LOG.debug("Disable failed with expected exception.");
145 }
146
147
148 long procId4 = procExec.submitProcedure(new DisableTableProcedure(
149 procExec.getEnvironment(), tableName, true));
150
151 ProcedureTestingUtility.waitProcedure(procExec, procId4);
152 ProcedureTestingUtility.assertProcNotFailed(procExec, procId4);
153 MasterProcedureTestingUtility.validateTableIsDisabled(UTIL.getHBaseCluster().getMaster(),
154 tableName);
155 }
156
157 @Test(timeout = 60000)
158 public void testDisableTableTwiceWithSameNonce() throws Exception {
159 final TableName tableName = TableName.valueOf("testDisableTableTwiceWithSameNonce");
160 final ProcedureExecutor<MasterProcedureEnv> procExec = getMasterProcedureExecutor();
161
162 MasterProcedureTestingUtility.createTable(procExec, tableName, null, "f1", "f2");
163
164
165 long procId1 = procExec.submitProcedure(new DisableTableProcedure(
166 procExec.getEnvironment(), tableName, false), nonceGroup, nonce);
167 long procId2 = procExec.submitProcedure(new DisableTableProcedure(
168 procExec.getEnvironment(), tableName, false), nonceGroup, nonce);
169
170 ProcedureTestingUtility.waitProcedure(procExec, procId1);
171 ProcedureTestingUtility.assertProcNotFailed(procExec, procId1);
172 MasterProcedureTestingUtility.validateTableIsDisabled(UTIL.getHBaseCluster().getMaster(),
173 tableName);
174
175 ProcedureTestingUtility.waitProcedure(procExec, procId2);
176 ProcedureTestingUtility.assertProcNotFailed(procExec, procId2);
177 assertTrue(procId1 == procId2);
178 }
179
180 @Test(timeout=60000)
181 public void testRecoveryAndDoubleExecution() throws Exception {
182 final TableName tableName = TableName.valueOf("testRecoveryAndDoubleExecution");
183 final ProcedureExecutor<MasterProcedureEnv> procExec = getMasterProcedureExecutor();
184
185 final byte[][] splitKeys = new byte[][] {
186 Bytes.toBytes("a"), Bytes.toBytes("b"), Bytes.toBytes("c")
187 };
188 MasterProcedureTestingUtility.createTable(procExec, tableName, splitKeys, "f1", "f2");
189
190 ProcedureTestingUtility.setKillAndToggleBeforeStoreUpdate(procExec, true);
191
192
193 long procId = procExec.submitProcedure(
194 new DisableTableProcedure(procExec.getEnvironment(), tableName, false), nonceGroup, nonce);
195
196
197 int numberOfSteps = DisableTableState.values().length;
198 MasterProcedureTestingUtility.testRecoveryAndDoubleExecution(
199 procExec,
200 procId,
201 numberOfSteps,
202 DisableTableState.values());
203 MasterProcedureTestingUtility.validateTableIsDisabled(UTIL.getHBaseCluster().getMaster(),
204 tableName);
205 }
206
207 private ProcedureExecutor<MasterProcedureEnv> getMasterProcedureExecutor() {
208 return UTIL.getHBaseCluster().getMaster().getMasterProcedureExecutor();
209 }
210 }