001/** 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.apache.hadoop.hbase.master.procedure; 019 020import static org.junit.Assert.assertNotNull; 021import static org.junit.Assert.assertNull; 022import static org.junit.Assert.assertTrue; 023 024import java.io.IOException; 025import org.apache.hadoop.conf.Configuration; 026import org.apache.hadoop.hbase.HBaseClassTestRule; 027import org.apache.hadoop.hbase.HBaseTestingUtility; 028import org.apache.hadoop.hbase.NamespaceDescriptor; 029import org.apache.hadoop.hbase.NamespaceExistException; 030import org.apache.hadoop.hbase.NamespaceNotFoundException; 031import org.apache.hadoop.hbase.constraint.ConstraintException; 032import org.apache.hadoop.hbase.procedure2.Procedure; 033import org.apache.hadoop.hbase.procedure2.ProcedureExecutor; 034import org.apache.hadoop.hbase.procedure2.ProcedureTestingUtility; 035import org.apache.hadoop.hbase.testclassification.MasterTests; 036import org.apache.hadoop.hbase.testclassification.MediumTests; 037import org.junit.After; 038import org.junit.AfterClass; 039import org.junit.Before; 040import org.junit.BeforeClass; 041import org.junit.ClassRule; 042import org.junit.Test; 043import org.junit.experimental.categories.Category; 044import org.slf4j.Logger; 045import org.slf4j.LoggerFactory; 046 047@Category({MasterTests.class, MediumTests.class}) 048public class TestCreateNamespaceProcedure { 049 050 @ClassRule 051 public static final HBaseClassTestRule CLASS_RULE = 052 HBaseClassTestRule.forClass(TestCreateNamespaceProcedure.class); 053 054 private static final Logger LOG = LoggerFactory.getLogger(TestCreateNamespaceProcedure.class); 055 056 protected static final HBaseTestingUtility UTIL = new HBaseTestingUtility(); 057 058 private static void setupConf(Configuration conf) { 059 conf.setInt(MasterProcedureConstants.MASTER_PROCEDURE_THREADS, 1); 060 conf.setInt(MasterProcedureConstants.MASTER_URGENT_PROCEDURE_THREADS, 0); 061 } 062 063 @BeforeClass 064 public static void setupCluster() throws Exception { 065 setupConf(UTIL.getConfiguration()); 066 UTIL.startMiniCluster(1); 067 } 068 069 @AfterClass 070 public static void cleanupTest() throws Exception { 071 try { 072 UTIL.shutdownMiniCluster(); 073 } catch (Exception e) { 074 LOG.warn("failure shutting down cluster", e); 075 } 076 } 077 078 @Before 079 public void setup() throws Exception { 080 ProcedureTestingUtility.setKillAndToggleBeforeStoreUpdate(getMasterProcedureExecutor(), false); 081 } 082 083 @After 084 public void tearDown() throws Exception { 085 ProcedureTestingUtility.setKillAndToggleBeforeStoreUpdate(getMasterProcedureExecutor(), false); 086 } 087 088 @Test 089 public void testCreateNamespace() throws Exception { 090 final NamespaceDescriptor nsd = NamespaceDescriptor.create("testCreateNamespace").build(); 091 final ProcedureExecutor<MasterProcedureEnv> procExec = getMasterProcedureExecutor(); 092 093 long procId = procExec.submitProcedure( 094 new CreateNamespaceProcedure(procExec.getEnvironment(), nsd)); 095 // Wait the completion 096 ProcedureTestingUtility.waitProcedure(procExec, procId); 097 ProcedureTestingUtility.assertProcNotFailed(procExec, procId); 098 099 validateNamespaceCreated(nsd); 100 } 101 102 @Test 103 public void testCreateSameNamespaceTwice() throws Exception { 104 final NamespaceDescriptor nsd = 105 NamespaceDescriptor.create("testCreateSameNamespaceTwice").build(); 106 final ProcedureExecutor<MasterProcedureEnv> procExec = getMasterProcedureExecutor(); 107 108 long procId1 = procExec.submitProcedure( 109 new CreateNamespaceProcedure(procExec.getEnvironment(), nsd)); 110 // Wait the completion 111 ProcedureTestingUtility.waitProcedure(procExec, procId1); 112 ProcedureTestingUtility.assertProcNotFailed(procExec, procId1); 113 114 // Create the namespace that exists 115 long procId2 = procExec.submitProcedure( 116 new CreateNamespaceProcedure(procExec.getEnvironment(), nsd)); 117 // Wait the completion 118 ProcedureTestingUtility.waitProcedure(procExec, procId2); 119 120 // Second create should fail with NamespaceExistException 121 Procedure<?> result = procExec.getResult(procId2); 122 assertTrue(result.isFailed()); 123 LOG.debug("Create namespace failed with exception: " + result.getException()); 124 assertTrue( 125 ProcedureTestingUtility.getExceptionCause(result) instanceof NamespaceExistException); 126 } 127 128 @Test 129 public void testCreateSystemNamespace() throws Exception { 130 final NamespaceDescriptor nsd = 131 UTIL.getAdmin().getNamespaceDescriptor(NamespaceDescriptor.SYSTEM_NAMESPACE.getName()); 132 final ProcedureExecutor<MasterProcedureEnv> procExec = getMasterProcedureExecutor(); 133 134 long procId = procExec.submitProcedure( 135 new CreateNamespaceProcedure(procExec.getEnvironment(), nsd)); 136 // Wait the completion 137 ProcedureTestingUtility.waitProcedure(procExec, procId); 138 Procedure<?> result = procExec.getResult(procId); 139 assertTrue(result.isFailed()); 140 LOG.debug("Create namespace failed with exception: " + result.getException()); 141 assertTrue( 142 ProcedureTestingUtility.getExceptionCause(result) instanceof NamespaceExistException); 143 } 144 145 @Test 146 public void testCreateNamespaceWithInvalidRegionCount() throws Exception { 147 final NamespaceDescriptor nsd = 148 NamespaceDescriptor.create("testCreateNamespaceWithInvalidRegionCount").build(); 149 final String nsKey = "hbase.namespace.quota.maxregions"; 150 final String nsValue = "-1"; 151 final ProcedureExecutor<MasterProcedureEnv> procExec = getMasterProcedureExecutor(); 152 153 nsd.setConfiguration(nsKey, nsValue); 154 155 long procId = procExec.submitProcedure( 156 new CreateNamespaceProcedure(procExec.getEnvironment(), nsd)); 157 // Wait the completion 158 ProcedureTestingUtility.waitProcedure(procExec, procId); 159 Procedure<?> result = procExec.getResult(procId); 160 assertTrue(result.isFailed()); 161 LOG.debug("Create namespace failed with exception: " + result.getException()); 162 assertTrue(ProcedureTestingUtility.getExceptionCause(result) instanceof ConstraintException); 163 } 164 165 @Test 166 public void testCreateNamespaceWithInvalidTableCount() throws Exception { 167 final NamespaceDescriptor nsd = 168 NamespaceDescriptor.create("testCreateNamespaceWithInvalidTableCount").build(); 169 final String nsKey = "hbase.namespace.quota.maxtables"; 170 final String nsValue = "-1"; 171 final ProcedureExecutor<MasterProcedureEnv> procExec = getMasterProcedureExecutor(); 172 173 nsd.setConfiguration(nsKey, nsValue); 174 175 long procId = procExec.submitProcedure( 176 new CreateNamespaceProcedure(procExec.getEnvironment(), nsd)); 177 // Wait the completion 178 ProcedureTestingUtility.waitProcedure(procExec, procId); 179 Procedure<?> result = procExec.getResult(procId); 180 assertTrue(result.isFailed()); 181 LOG.debug("Create namespace failed with exception: " + result.getException()); 182 assertTrue(ProcedureTestingUtility.getExceptionCause(result) instanceof ConstraintException); 183 } 184 185 @Test 186 public void testRecoveryAndDoubleExecution() throws Exception { 187 final NamespaceDescriptor nsd = 188 NamespaceDescriptor.create("testRecoveryAndDoubleExecution").build(); 189 final ProcedureExecutor<MasterProcedureEnv> procExec = getMasterProcedureExecutor(); 190 191 ProcedureTestingUtility.waitNoProcedureRunning(procExec); 192 ProcedureTestingUtility.setKillAndToggleBeforeStoreUpdate(procExec, true); 193 194 // Start the CreateNamespace procedure && kill the executor 195 long procId = procExec.submitProcedure( 196 new CreateNamespaceProcedure(procExec.getEnvironment(), nsd)); 197 198 // Restart the executor and execute the step twice 199 MasterProcedureTestingUtility.testRecoveryAndDoubleExecution(procExec, procId); 200 201 // Validate the creation of namespace 202 ProcedureTestingUtility.assertProcNotFailed(procExec, procId); 203 validateNamespaceCreated(nsd); 204 } 205 206 @Test 207 public void testRollbackAndDoubleExecution() throws Exception { 208 final NamespaceDescriptor nsd = 209 NamespaceDescriptor.create("testRollbackAndDoubleExecution").build(); 210 final ProcedureExecutor<MasterProcedureEnv> procExec = getMasterProcedureExecutor(); 211 212 ProcedureTestingUtility.waitNoProcedureRunning(procExec); 213 ProcedureTestingUtility.setKillAndToggleBeforeStoreUpdate(procExec, true); 214 215 // Start the CreateNamespace procedure && kill the executor 216 long procId = procExec.submitProcedure( 217 new CreateNamespaceProcedure(procExec.getEnvironment(), nsd)); 218 219 int lastStep = 2; // failing before CREATE_NAMESPACE_CREATE_DIRECTORY 220 MasterProcedureTestingUtility.testRollbackAndDoubleExecution(procExec, procId, lastStep); 221 222 // Validate the non-existence of namespace 223 try { 224 NamespaceDescriptor nsDescriptor = UTIL.getAdmin().getNamespaceDescriptor(nsd.getName()); 225 assertNull(nsDescriptor); 226 } catch (NamespaceNotFoundException nsnfe) { 227 // Expected 228 LOG.info("The namespace " + nsd.getName() + " is not created."); 229 } 230 } 231 232 private ProcedureExecutor<MasterProcedureEnv> getMasterProcedureExecutor() { 233 return UTIL.getHBaseCluster().getMaster().getMasterProcedureExecutor(); 234 } 235 236 private void validateNamespaceCreated(NamespaceDescriptor nsd) throws IOException { 237 NamespaceDescriptor createdNsDescriptor = 238 UTIL.getAdmin().getNamespaceDescriptor(nsd.getName()); 239 assertNotNull(createdNsDescriptor); 240 } 241}