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.*;
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.HTableDescriptor;
28 import org.apache.hadoop.hbase.NamespaceDescriptor;
29 import org.apache.hadoop.hbase.NamespaceNotFoundException;
30 import org.apache.hadoop.hbase.ProcedureInfo;
31 import org.apache.hadoop.hbase.constraint.ConstraintException;
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.ModifyNamespaceState;
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 TestModifyNamespaceProcedure {
45 private static final Log LOG = LogFactory.getLog(TestModifyNamespaceProcedure.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
83 @Test(timeout = 60000)
84 public void testModifyNamespace() throws Exception {
85 final NamespaceDescriptor nsd = NamespaceDescriptor.create("testModifyNamespace").build();
86 final String nsKey1 = "hbase.namespace.quota.maxregions";
87 final String nsValue1before = "1111";
88 final String nsValue1after = "9999";
89 final String nsKey2 = "hbase.namespace.quota.maxtables";
90 final String nsValue2 = "10";
91 final ProcedureExecutor<MasterProcedureEnv> procExec = getMasterProcedureExecutor();
92
93 nsd.setConfiguration(nsKey1, nsValue1before);
94 createNamespaceForTesting(nsd);
95
96
97 NamespaceDescriptor currentNsDescriptor =
98 UTIL.getHBaseAdmin().getNamespaceDescriptor(nsd.getName());
99 assertEquals(currentNsDescriptor.getConfigurationValue(nsKey1), nsValue1before);
100 assertNull(currentNsDescriptor.getConfigurationValue(nsKey2));
101
102
103 nsd.setConfiguration(nsKey1, nsValue1after);
104 nsd.setConfiguration(nsKey2, nsValue2);
105
106 long procId1 = procExec.submitProcedure(
107 new ModifyNamespaceProcedure(procExec.getEnvironment(), nsd));
108
109 ProcedureTestingUtility.waitProcedure(procExec, procId1);
110 ProcedureTestingUtility.assertProcNotFailed(procExec, procId1);
111
112
113 currentNsDescriptor =
114 UTIL.getHBaseAdmin().getNamespaceDescriptor(nsd.getName());
115 assertEquals(nsd.getConfigurationValue(nsKey1), nsValue1after);
116 assertEquals(currentNsDescriptor.getConfigurationValue(nsKey2), nsValue2);
117 }
118
119 @Test(timeout=60000)
120 public void testModifyNonExistNamespace() throws Exception {
121 final String namespaceName = "testModifyNonExistNamespace";
122 final ProcedureExecutor<MasterProcedureEnv> procExec = getMasterProcedureExecutor();
123
124 try {
125 NamespaceDescriptor nsDescriptor = UTIL.getHBaseAdmin().getNamespaceDescriptor(namespaceName);
126 assertNull(nsDescriptor);
127 } catch (NamespaceNotFoundException nsnfe) {
128
129 LOG.debug("The namespace " + namespaceName + " does not exist. This is expected.");
130 }
131
132 final NamespaceDescriptor nsd = NamespaceDescriptor.create(namespaceName).build();
133
134 long procId = procExec.submitProcedure(
135 new ModifyNamespaceProcedure(procExec.getEnvironment(), nsd));
136
137 ProcedureTestingUtility.waitProcedure(procExec, procId);
138
139
140 ProcedureInfo result = procExec.getResult(procId);
141 assertTrue(result.isFailed());
142 LOG.debug("modify namespace failed with exception: " + result.getExceptionFullMessage());
143 assertTrue(
144 ProcedureTestingUtility.getExceptionCause(result) instanceof NamespaceNotFoundException);
145 }
146
147 @Test(timeout=60000)
148 public void testModifyNamespaceWithInvalidRegionCount() throws Exception {
149 final NamespaceDescriptor nsd =
150 NamespaceDescriptor.create("testModifyNamespaceWithInvalidRegionCount").build();
151 final String nsKey = "hbase.namespace.quota.maxregions";
152 final String nsValue = "-1";
153 final ProcedureExecutor<MasterProcedureEnv> procExec = getMasterProcedureExecutor();
154
155 createNamespaceForTesting(nsd);
156
157
158 nsd.setConfiguration(nsKey, nsValue);
159
160 long procId = procExec.submitProcedure(
161 new ModifyNamespaceProcedure(procExec.getEnvironment(), nsd));
162
163 ProcedureTestingUtility.waitProcedure(procExec, procId);
164 ProcedureInfo result = procExec.getResult(procId);
165 assertTrue(result.isFailed());
166 LOG.debug("Modify namespace failed with exception: " + result.getExceptionFullMessage());
167 assertTrue(ProcedureTestingUtility.getExceptionCause(result) instanceof ConstraintException);
168 }
169
170 @Test(timeout=60000)
171 public void testModifyNamespaceWithInvalidTableCount() throws Exception {
172 final NamespaceDescriptor nsd =
173 NamespaceDescriptor.create("testModifyNamespaceWithInvalidTableCount").build();
174 final String nsKey = "hbase.namespace.quota.maxtables";
175 final String nsValue = "-1";
176 final ProcedureExecutor<MasterProcedureEnv> procExec = getMasterProcedureExecutor();
177
178 createNamespaceForTesting(nsd);
179
180
181 nsd.setConfiguration(nsKey, nsValue);
182
183 long procId = procExec.submitProcedure(
184 new ModifyNamespaceProcedure(procExec.getEnvironment(), nsd));
185
186 ProcedureTestingUtility.waitProcedure(procExec, procId);
187 ProcedureInfo result = procExec.getResult(procId);
188 assertTrue(result.isFailed());
189 LOG.debug("Modify namespace failed with exception: " + result.getExceptionFullMessage());
190 assertTrue(ProcedureTestingUtility.getExceptionCause(result) instanceof ConstraintException);
191 }
192
193 @Test(timeout = 60000)
194 public void testRecoveryAndDoubleExecution() throws Exception {
195 final NamespaceDescriptor nsd =
196 NamespaceDescriptor.create("testRecoveryAndDoubleExecution").build();
197 final String nsKey = "foo";
198 final String nsValue = "bar";
199 final ProcedureExecutor<MasterProcedureEnv> procExec = getMasterProcedureExecutor();
200
201 createNamespaceForTesting(nsd);
202 ProcedureTestingUtility.waitNoProcedureRunning(procExec);
203 ProcedureTestingUtility.setKillAndToggleBeforeStoreUpdate(procExec, true);
204
205
206 nsd.setConfiguration(nsKey, nsValue);
207
208
209 long procId = procExec.submitProcedure(
210 new ModifyNamespaceProcedure(procExec.getEnvironment(), nsd));
211
212
213 int numberOfSteps = ModifyNamespaceState.values().length;
214 MasterProcedureTestingUtility.testRecoveryAndDoubleExecution(
215 procExec,
216 procId,
217 numberOfSteps,
218 ModifyNamespaceState.values());
219
220 ProcedureTestingUtility.assertProcNotFailed(procExec, procId);
221
222 NamespaceDescriptor currentNsDescriptor =
223 UTIL.getHBaseAdmin().getNamespaceDescriptor(nsd.getName());
224 assertEquals(currentNsDescriptor.getConfigurationValue(nsKey), nsValue);
225 }
226
227 @Test(timeout = 60000)
228 public void testRollbackAndDoubleExecution() throws Exception {
229 final NamespaceDescriptor nsd =
230 NamespaceDescriptor.create("testRollbackAndDoubleExecution").build();
231 final String nsKey = "foo";
232 final String nsValue = "bar";
233 final ProcedureExecutor<MasterProcedureEnv> procExec = getMasterProcedureExecutor();
234
235 createNamespaceForTesting(nsd);
236 ProcedureTestingUtility.waitNoProcedureRunning(procExec);
237 ProcedureTestingUtility.setKillAndToggleBeforeStoreUpdate(procExec, true);
238
239
240 nsd.setConfiguration(nsKey, nsValue);
241
242
243 long procId = procExec.submitProcedure(
244 new ModifyNamespaceProcedure(procExec.getEnvironment(), nsd));
245
246
247 int numberOfSteps = ModifyNamespaceState.values().length - 2;
248 MasterProcedureTestingUtility.testRollbackAndDoubleExecution(
249 procExec,
250 procId,
251 numberOfSteps,
252 ModifyNamespaceState.values());
253
254
255 NamespaceDescriptor currentNsDescriptor =
256 UTIL.getHBaseAdmin().getNamespaceDescriptor(nsd.getName());
257 assertNull(currentNsDescriptor.getConfigurationValue(nsKey));
258 }
259
260 private ProcedureExecutor<MasterProcedureEnv> getMasterProcedureExecutor() {
261 return UTIL.getHBaseCluster().getMaster().getMasterProcedureExecutor();
262 }
263
264 private void createNamespaceForTesting(NamespaceDescriptor nsDescriptor) throws Exception {
265 final ProcedureExecutor<MasterProcedureEnv> procExec = getMasterProcedureExecutor();
266
267 long procId = procExec.submitProcedure(
268 new CreateNamespaceProcedure(procExec.getEnvironment(), nsDescriptor));
269
270 ProcedureTestingUtility.waitProcedure(procExec, procId);
271 ProcedureTestingUtility.assertProcNotFailed(procExec, procId);
272 }
273 }