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.locking; 019 020import static org.junit.Assert.assertEquals; 021import static org.junit.Assert.assertFalse; 022import static org.junit.Assert.assertTrue; 023 024import java.util.List; 025import org.apache.hadoop.conf.Configuration; 026import org.apache.hadoop.hbase.HBaseClassTestRule; 027import org.apache.hadoop.hbase.HBaseTestingUtil; 028import org.apache.hadoop.hbase.NamespaceDescriptor; 029import org.apache.hadoop.hbase.TableName; 030import org.apache.hadoop.hbase.client.RegionInfo; 031import org.apache.hadoop.hbase.master.MasterServices; 032import org.apache.hadoop.hbase.master.procedure.MasterProcedureConstants; 033import org.apache.hadoop.hbase.master.procedure.MasterProcedureEnv; 034import org.apache.hadoop.hbase.procedure2.LockType; 035import org.apache.hadoop.hbase.procedure2.Procedure; 036import org.apache.hadoop.hbase.procedure2.ProcedureExecutor; 037import org.apache.hadoop.hbase.procedure2.ProcedureTestingUtility; 038import org.apache.hadoop.hbase.testclassification.MasterTests; 039import org.apache.hadoop.hbase.testclassification.MediumTests; 040import org.apache.hadoop.hbase.util.Bytes; 041import org.junit.After; 042import org.junit.AfterClass; 043import org.junit.BeforeClass; 044import org.junit.ClassRule; 045import org.junit.Rule; 046import org.junit.Test; 047import org.junit.experimental.categories.Category; 048import org.junit.rules.TestName; 049import org.slf4j.Logger; 050import org.slf4j.LoggerFactory; 051 052@Category({ MasterTests.class, MediumTests.class }) 053public class TestLockManager { 054 055 @ClassRule 056 public static final HBaseClassTestRule CLASS_RULE = 057 HBaseClassTestRule.forClass(TestLockManager.class); 058 059 @Rule 060 public TestName testName = new TestName(); 061 // crank this up if this test turns out to be flaky. 062 private static final int LOCAL_LOCKS_TIMEOUT = 1000; 063 064 private static final Logger LOG = LoggerFactory.getLogger(TestLockManager.class); 065 protected static final HBaseTestingUtil UTIL = new HBaseTestingUtil(); 066 private static MasterServices masterServices; 067 068 private static String namespace = "namespace"; 069 private static TableName tableName = TableName.valueOf(namespace, "table"); 070 private static RegionInfo[] tableRegions; 071 072 private static void setupConf(Configuration conf) { 073 conf.setInt(MasterProcedureConstants.MASTER_PROCEDURE_THREADS, 1); 074 conf.setBoolean("hbase.procedure.check.owner.set", false); // since rpc user will be null 075 conf.setInt(LockProcedure.LOCAL_MASTER_LOCKS_TIMEOUT_MS_CONF, LOCAL_LOCKS_TIMEOUT); 076 } 077 078 @BeforeClass 079 public static void setupCluster() throws Exception { 080 setupConf(UTIL.getConfiguration()); 081 UTIL.startMiniCluster(1); 082 masterServices = UTIL.getMiniHBaseCluster().getMaster(); 083 UTIL.getAdmin().createNamespace(NamespaceDescriptor.create(namespace).build()); 084 UTIL.createTable(tableName, new byte[][] { Bytes.toBytes("fam") }, 085 new byte[][] { Bytes.toBytes("1") }); 086 List<RegionInfo> regions = UTIL.getAdmin().getRegions(tableName); 087 assert regions.size() > 0; 088 tableRegions = new RegionInfo[regions.size()]; 089 regions.toArray(tableRegions); 090 } 091 092 @AfterClass 093 public static void cleanupTest() throws Exception { 094 try { 095 UTIL.shutdownMiniCluster(); 096 } catch (Exception e) { 097 LOG.warn("failure shutting down cluster", e); 098 } 099 } 100 101 @After 102 public void tearDown() throws Exception { 103 for (Procedure<?> proc : getMasterProcedureExecutor().getProcedures()) { 104 if (proc instanceof LockProcedure) { 105 ((LockProcedure) proc).unlock(getMasterProcedureExecutor().getEnvironment()); 106 ProcedureTestingUtility.waitProcedure(getMasterProcedureExecutor(), proc); 107 } 108 } 109 assertEquals(0, getMasterProcedureExecutor().getEnvironment().getProcedureScheduler().size()); 110 } 111 112 private ProcedureExecutor<MasterProcedureEnv> getMasterProcedureExecutor() { 113 return UTIL.getHBaseCluster().getMaster().getMasterProcedureExecutor(); 114 } 115 116 /** 117 * Tests that basic lock functionality works. 118 */ 119 @Test 120 public void testMasterLockAcquire() throws Exception { 121 LockManager.MasterLock lock = 122 masterServices.getLockManager().createMasterLock(namespace, LockType.EXCLUSIVE, "desc"); 123 assertTrue(lock.tryAcquire(2000)); 124 assertTrue(lock.getProc().isLocked()); 125 lock.release(); 126 assertEquals(null, lock.getProc()); 127 } 128 129 /** 130 * Two locks try to acquire lock on same table, assert that later one times out. 131 */ 132 @Test 133 public void testMasterLockAcquireTimeout() throws Exception { 134 LockManager.MasterLock lock = 135 masterServices.getLockManager().createMasterLock(tableName, LockType.EXCLUSIVE, "desc"); 136 LockManager.MasterLock lock2 = 137 masterServices.getLockManager().createMasterLock(tableName, LockType.EXCLUSIVE, "desc"); 138 assertTrue(lock.tryAcquire(2000)); 139 assertFalse(lock2.tryAcquire(LOCAL_LOCKS_TIMEOUT / 2)); // wait less than other lock's timeout 140 assertEquals(null, lock2.getProc()); 141 lock.release(); 142 assertTrue(lock2.tryAcquire(2000)); 143 assertTrue(lock2.getProc().isLocked()); 144 lock2.release(); 145 } 146 147 /** 148 * Take region lock, they try table exclusive lock, later one should time out. 149 */ 150 @Test 151 public void testMasterLockAcquireTimeoutRegionVsTableExclusive() throws Exception { 152 LockManager.MasterLock lock = 153 masterServices.getLockManager().createMasterLock(tableRegions, "desc"); 154 LockManager.MasterLock lock2 = 155 masterServices.getLockManager().createMasterLock(tableName, LockType.EXCLUSIVE, "desc"); 156 assertTrue(lock.tryAcquire(2000)); 157 assertFalse(lock2.tryAcquire(LOCAL_LOCKS_TIMEOUT / 2)); // wait less than other lock's timeout 158 assertEquals(null, lock2.getProc()); 159 lock.release(); 160 assertTrue(lock2.tryAcquire(2000)); 161 assertTrue(lock2.getProc().isLocked()); 162 lock2.release(); 163 } 164}