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.TableNotDisabledException;
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.EnableTableState;
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 TestEnableTableProcedure {
47 private static final Log LOG = LogFactory.getLog(TestEnableTableProcedure.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 testEnableTable() throws Exception {
92 final TableName tableName = TableName.valueOf("testEnableTable");
93 final ProcedureExecutor<MasterProcedureEnv> procExec = getMasterProcedureExecutor();
94
95 MasterProcedureTestingUtility.createTable(procExec, tableName, null, "f1", "f2");
96 UTIL.getHBaseAdmin().disableTable(tableName);
97
98
99 long procId = procExec.submitProcedure(
100 new EnableTableProcedure(procExec.getEnvironment(), tableName, false), nonceGroup, nonce);
101
102 ProcedureTestingUtility.waitProcedure(procExec, procId);
103 ProcedureTestingUtility.assertProcNotFailed(procExec, procId);
104 MasterProcedureTestingUtility.validateTableIsEnabled(UTIL.getHBaseCluster().getMaster(),
105 tableName);
106 }
107
108 @Test(timeout = 60000)
109 public void testEnableTableTwiceWithSameNonce() throws Exception {
110 final TableName tableName = TableName.valueOf("testEnableTableTwiceWithSameNonce");
111 final ProcedureExecutor<MasterProcedureEnv> procExec = getMasterProcedureExecutor();
112
113 MasterProcedureTestingUtility.createTable(procExec, tableName, null, "f1", "f2");
114 UTIL.getHBaseAdmin().disableTable(tableName);
115
116
117 long procId1 = procExec.submitProcedure(
118 new EnableTableProcedure(procExec.getEnvironment(), tableName, false), nonceGroup, nonce);
119 long procId2 = procExec.submitProcedure(
120 new EnableTableProcedure(procExec.getEnvironment(), tableName, false), nonceGroup, nonce);
121
122
123 ProcedureTestingUtility.waitProcedure(procExec, procId1);
124 ProcedureTestingUtility.assertProcNotFailed(procExec, procId1);
125
126 ProcedureTestingUtility.waitProcedure(procExec, procId2);
127 ProcedureTestingUtility.assertProcNotFailed(procExec, procId2);
128 assertTrue(procId1 == procId2);
129 }
130
131 @Test(timeout=60000, expected=TableNotDisabledException.class)
132 public void testEnableNonDisabledTable() throws Exception {
133 final TableName tableName = TableName.valueOf("testEnableNonExistingTable");
134 final ProcedureExecutor<MasterProcedureEnv> procExec = getMasterProcedureExecutor();
135
136 MasterProcedureTestingUtility.createTable(procExec, tableName, null, "f1", "f2");
137
138
139 long procId1 = procExec.submitProcedure(
140 new EnableTableProcedure(procExec.getEnvironment(), tableName, false), nonceGroup, nonce);
141 ProcedureTestingUtility.waitProcedure(procExec, procId1);
142
143 ProcedureInfo result = procExec.getResult(procId1);
144 assertTrue(result.isFailed());
145 LOG.debug("Enable failed with exception: " + result.getExceptionFullMessage());
146 assertTrue(
147 ProcedureTestingUtility.getExceptionCause(result) instanceof TableNotDisabledException);
148
149
150 long procId2 = procExec.submitProcedure(
151 new EnableTableProcedure(procExec.getEnvironment(), tableName, true),
152 nonceGroup + 1,
153 nonce + 1);
154
155 ProcedureTestingUtility.waitProcedure(procExec, procId2);
156 ProcedureTestingUtility.assertProcNotFailed(procExec, procId2);
157
158
159 final ProcedurePrepareLatch prepareLatch = new ProcedurePrepareLatch.CompatibilityLatch();
160 long procId3 = procExec.submitProcedure(
161 new EnableTableProcedure(procExec.getEnvironment(), tableName, false, prepareLatch),
162 nonceGroup + 2,
163 nonce + 2);
164 prepareLatch.await();
165 Assert.fail("Enable should throw exception through latch.");
166 }
167
168 @Test(timeout = 60000)
169 public void testRecoveryAndDoubleExecution() throws Exception {
170 final TableName tableName = TableName.valueOf("testRecoveryAndDoubleExecution");
171 final ProcedureExecutor<MasterProcedureEnv> procExec = getMasterProcedureExecutor();
172
173 final byte[][] splitKeys = new byte[][] {
174 Bytes.toBytes("a"), Bytes.toBytes("b"), Bytes.toBytes("c")
175 };
176 MasterProcedureTestingUtility.createTable(procExec, tableName, splitKeys, "f1", "f2");
177 UTIL.getHBaseAdmin().disableTable(tableName);
178 ProcedureTestingUtility.waitNoProcedureRunning(procExec);
179 ProcedureTestingUtility.setKillAndToggleBeforeStoreUpdate(procExec, true);
180
181
182 long procId = procExec.submitProcedure(
183 new EnableTableProcedure(procExec.getEnvironment(), tableName, false), nonceGroup, nonce);
184
185
186 int numberOfSteps = EnableTableState.values().length;
187 MasterProcedureTestingUtility.testRecoveryAndDoubleExecution(
188 procExec,
189 procId,
190 numberOfSteps,
191 EnableTableState.values());
192 MasterProcedureTestingUtility.validateTableIsEnabled(UTIL.getHBaseCluster().getMaster(),
193 tableName);
194 }
195
196 @Test(timeout = 60000)
197 public void testRollbackAndDoubleExecution() throws Exception {
198 final TableName tableName = TableName.valueOf("testRollbackAndDoubleExecution");
199 final ProcedureExecutor<MasterProcedureEnv> procExec = getMasterProcedureExecutor();
200
201 final byte[][] splitKeys = new byte[][] {
202 Bytes.toBytes("a"), Bytes.toBytes("b"), Bytes.toBytes("c")
203 };
204 MasterProcedureTestingUtility.createTable(procExec, tableName, splitKeys, "f1", "f2");
205 UTIL.getHBaseAdmin().disableTable(tableName);
206 ProcedureTestingUtility.waitNoProcedureRunning(procExec);
207 ProcedureTestingUtility.setKillAndToggleBeforeStoreUpdate(procExec, true);
208
209
210 long procId = procExec.submitProcedure(
211 new EnableTableProcedure(procExec.getEnvironment(), tableName, false), nonceGroup, nonce);
212
213 int numberOfSteps = EnableTableState.values().length - 2;
214 MasterProcedureTestingUtility.testRollbackAndDoubleExecution(
215 procExec,
216 procId,
217 numberOfSteps,
218 EnableTableState.values());
219 MasterProcedureTestingUtility.validateTableIsDisabled(UTIL.getHBaseCluster().getMaster(),
220 tableName);
221 }
222
223 private ProcedureExecutor<MasterProcedureEnv> getMasterProcedureExecutor() {
224 return UTIL.getHBaseCluster().getMaster().getMasterProcedureExecutor();
225 }
226 }