/*
* Licensed to the Apache Software Foundation (ASF) under one or more contributor license
* agreements. See the NOTICE file distributed with this work for additional information regarding
* copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License. You may obtain a
* copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/
package org.apache.geode.management;
import org.junit.experimental.categories.Category;
import org.junit.Test;
import static org.junit.Assert.*;
import org.apache.geode.test.dunit.cache.internal.JUnit4CacheTestCase;
import org.apache.geode.test.dunit.internal.JUnit4DistributedTestCase;
import org.apache.geode.test.junit.categories.DistributedTest;
import java.util.Map;
import java.util.Set;
import javax.management.ObjectName;
import org.junit.experimental.categories.Category;
import org.apache.geode.distributed.DistributedLockService;
import org.apache.geode.distributed.DistributedMember;
import org.apache.geode.distributed.internal.InternalDistributedSystem;
import org.apache.geode.distributed.internal.locks.DLockService;
import org.apache.geode.distributed.internal.membership.InternalDistributedMember;
import org.apache.geode.internal.cache.GemFireCacheImpl;
import org.apache.geode.management.internal.MBeanJMXAdapter;
import org.apache.geode.management.internal.SystemManagementService;
import org.apache.geode.test.dunit.Assert;
import org.apache.geode.test.dunit.LogWriterUtils;
import org.apache.geode.test.dunit.SerializableRunnable;
import org.apache.geode.test.dunit.VM;
import org.apache.geode.test.dunit.Wait;
import org.apache.geode.test.dunit.WaitCriterion;
import org.apache.geode.test.junit.categories.FlakyTest;
@Category(DistributedTest.class)
public class DLockManagementDUnitTest extends ManagementTestBase {
private static final long serialVersionUID = 1L;
private static final String LOCK_SERVICE_NAME = "testLockService";
// This must be bigger than the dunit ack-wait-threshold for the revoke
// tests. The command line is setting the ack-wait-threshold to be
// 60 seconds.
private static final int MAX_WAIT = 70 * 1000;
public DLockManagementDUnitTest() {
super();
}
/**
* Distributed Lock Service test
*
* @throws Exception
*/
@Category(FlakyTest.class) // GEODE-173: eats exceptions, HeadlessGFSH, time sensitive,
// waitForCriterions
@Test
public void testDLockMBean() throws Throwable {
initManagement(false);
VM[] managedNodes = new VM[getManagedNodeList().size()];
VM managingNode = getManagingNode();
getManagedNodeList().toArray(managedNodes);
createGrantorLockService(managedNodes[0]);
createLockService(managedNodes[1]);
createLockService(managedNodes[2]);
for (VM vm : getManagedNodeList()) {
verifyLockData(vm);
}
verifyLockDataRemote(managingNode);
for (VM vm : getManagedNodeList()) {
closeLockService(vm);
}
}
/**
* Distributed Lock Service test
*
* @throws Exception
*/
@Category(FlakyTest.class) // GEODE-553: waitForCriterion, eats exceptions, HeadlessGFSH
@Test
public void testDLockAggregate() throws Throwable {
initManagement(false);
VM[] managedNodes = new VM[getManagedNodeList().size()];
VM managingNode = getManagingNode();
getManagedNodeList().toArray(managedNodes);
createGrantorLockService(managedNodes[0]);
createLockService(managedNodes[1]);
createLockService(managedNodes[2]);
checkAggregate(managingNode, 3);
DistributedMember member = getMember(managedNodes[2]);
checkNavigation(managingNode, member);
createLockService(managingNode);
checkAggregate(managingNode, 4);
for (VM vm : getManagedNodeList()) {
closeLockService(vm);
}
ensureProxyCleanup(managingNode);
checkAggregate(managingNode, 1);
closeLockService(managingNode);
checkAggregate(managingNode, 0);
}
public void ensureProxyCleanup(final VM vm) {
SerializableRunnable ensureProxyCleanup = new SerializableRunnable("Ensure Proxy cleanup") {
public void run() {
GemFireCacheImpl cache = GemFireCacheImpl.getInstance();
Set<DistributedMember> otherMemberSet =
cache.getDistributionManager().getOtherNormalDistributionManagerIds();
final SystemManagementService service = (SystemManagementService) getManagementService();
for (final DistributedMember member : otherMemberSet) {
RegionMXBean bean = null;
try {
Wait.waitForCriterion(new WaitCriterion() {
LockServiceMXBean bean = null;
public String description() {
return "Waiting for the proxy to get deleted at managing node";
}
public boolean done() {
ObjectName objectName = service.getRegionMBeanName(member, LOCK_SERVICE_NAME);
bean = service.getMBeanProxy(objectName, LockServiceMXBean.class);
boolean done = (bean == null);
return done;
}
}, MAX_WAIT, 500, true);
} catch (Exception e) {
throw new AssertionError("could not remove proxies in required time", e);
}
assertNull(bean);
}
}
};
vm.invoke(ensureProxyCleanup);
}
/**
* Creates a grantor lock service
*
* @param vm
*/
@SuppressWarnings("serial")
protected void createGrantorLockService(final VM vm) {
SerializableRunnable createGrantorLockService =
new SerializableRunnable("Create Grantor LockService") {
public void run() {
GemFireCacheImpl cache = GemFireCacheImpl.getInstance();
assertNull(DistributedLockService.getServiceNamed(LOCK_SERVICE_NAME));
DLockService service = (DLockService) DistributedLockService.create(LOCK_SERVICE_NAME,
cache.getDistributedSystem());
assertSame(service, DistributedLockService.getServiceNamed(LOCK_SERVICE_NAME));
InternalDistributedMember grantor = service.getLockGrantorId().getLockGrantorMember();
assertNotNull(grantor);
LogWriterUtils.getLogWriter().info("In identifyLockGrantor - grantor is " + grantor);
ManagementService mgmtService = getManagementService();
LockServiceMXBean bean = mgmtService.getLocalLockServiceMBean(LOCK_SERVICE_NAME);
assertNotNull(bean);
assertTrue(bean.isDistributed());
assertEquals(bean.getName(), LOCK_SERVICE_NAME);
assertTrue(bean.isLockGrantor());
assertEquals(cache.getDistributedSystem().getMemberId(), bean.fetchGrantorMember());
}
};
vm.invoke(createGrantorLockService);
}
/**
* Creates a named lock service
*
* @param vm
*/
@SuppressWarnings("serial")
protected void createLockService(final VM vm) {
SerializableRunnable createLockService = new SerializableRunnable("Create LockService") {
public void run() {
assertNull(DistributedLockService.getServiceNamed(LOCK_SERVICE_NAME));
GemFireCacheImpl cache = GemFireCacheImpl.getInstance();
DistributedLockService service =
DistributedLockService.create(LOCK_SERVICE_NAME, cache.getDistributedSystem());
assertSame(service, DistributedLockService.getServiceNamed(LOCK_SERVICE_NAME));
ManagementService mgmtService = getManagementService();
LockServiceMXBean bean = mgmtService.getLocalLockServiceMBean(LOCK_SERVICE_NAME);
assertNotNull(bean);
assertTrue(bean.isDistributed());
assertFalse(bean.isLockGrantor());
}
};
vm.invoke(createLockService);
}
/**
* Closes a named lock service
*
* @param vm
*/
@SuppressWarnings("serial")
protected void closeLockService(final VM vm) {
SerializableRunnable closeLockService = new SerializableRunnable("Close LockService") {
public void run() {
DistributedLockService service = DistributedLockService.getServiceNamed(LOCK_SERVICE_NAME);
DistributedLockService.destroy(LOCK_SERVICE_NAME);
ManagementService mgmtService = getManagementService();
LockServiceMXBean bean = null;
try {
bean = mgmtService.getLocalLockServiceMBean(LOCK_SERVICE_NAME);
} catch (ManagementException mgs) {
}
assertNull(bean);
}
};
vm.invoke(closeLockService);
}
/**
* Lock data related verifications
*
* @param vm
*/
@SuppressWarnings("serial")
protected void verifyLockData(final VM vm) {
SerializableRunnable verifyLockData = new SerializableRunnable("Verify LockService") {
public void run() {
DistributedLockService service = DistributedLockService.getServiceNamed(LOCK_SERVICE_NAME);
final String LOCK_OBJECT = "lockObject_" + vm.getPid();
Wait.waitForCriterion(new WaitCriterion() {
DistributedLockService service = null;
public String description() {
return "Waiting for the lock service to be initialised";
}
public boolean done() {
DistributedLockService service =
DistributedLockService.getServiceNamed(LOCK_SERVICE_NAME);
boolean done = service != null;
return done;
}
}, MAX_WAIT, 500, true);
service.lock(LOCK_OBJECT, 1000, -1);
ManagementService mgmtService = getManagementService();
LockServiceMXBean bean = null;
try {
bean = mgmtService.getLocalLockServiceMBean(LOCK_SERVICE_NAME);
} catch (ManagementException mgs) {
}
assertNotNull(bean);
String[] listHeldLock = bean.listHeldLocks();
assertEquals(listHeldLock.length, 1);
LogWriterUtils.getLogWriter().info("List Of Lock Object is " + listHeldLock[0]);
Map<String, String> lockThreadMap = bean.listThreadsHoldingLock();
assertEquals(lockThreadMap.size(), 1);
LogWriterUtils.getLogWriter().info("List Of Lock Thread is " + lockThreadMap.toString());
}
};
vm.invoke(verifyLockData);
}
/**
* Verify lock data from remote Managing node
*
* @param vm
*/
@SuppressWarnings("serial")
protected void verifyLockDataRemote(final VM vm) {
SerializableRunnable verifyLockDataRemote =
new SerializableRunnable("Verify LockService Remote") {
public void run() {
GemFireCacheImpl cache = GemFireCacheImpl.getInstance();
Set<DistributedMember> otherMemberSet =
cache.getDistributionManager().getOtherNormalDistributionManagerIds();
for (DistributedMember member : otherMemberSet) {
LockServiceMXBean bean = null;
try {
bean = MBeanUtil.getLockServiceMbeanProxy(member, LOCK_SERVICE_NAME);
} catch (Exception e) {
InternalDistributedSystem.getLoggerI18n()
.fine("Undesired Result , LockServiceMBean Should not be null", e);
}
assertNotNull(bean);
String[] listHeldLock = bean.listHeldLocks();
assertEquals(listHeldLock.length, 1);
LogWriterUtils.getLogWriter().info("List Of Lock Object is " + listHeldLock[0]);
Map<String, String> lockThreadMap = bean.listThreadsHoldingLock();
assertEquals(lockThreadMap.size(), 1);
LogWriterUtils.getLogWriter()
.info("List Of Lock Thread is " + lockThreadMap.toString());
}
}
};
vm.invoke(verifyLockDataRemote);
}
protected void checkNavigation(final VM vm, final DistributedMember lockServiceMember) {
SerializableRunnable checkNavigation = new SerializableRunnable("Check Navigation") {
public void run() {
final ManagementService service = getManagementService();
DistributedSystemMXBean disMBean = service.getDistributedSystemMXBean();
try {
ObjectName expected = MBeanJMXAdapter.getDistributedLockServiceName(LOCK_SERVICE_NAME);
ObjectName actual = disMBean.fetchDistributedLockServiceObjectName(LOCK_SERVICE_NAME);
assertEquals(expected, actual);
} catch (Exception e) {
throw new AssertionError("Lock Service Navigation Failed ", e);
}
try {
ObjectName expected =
MBeanJMXAdapter.getLockServiceMBeanName(lockServiceMember.getId(), LOCK_SERVICE_NAME);
ObjectName actual =
disMBean.fetchLockServiceObjectName(lockServiceMember.getId(), LOCK_SERVICE_NAME);
assertEquals(expected, actual);
} catch (Exception e) {
throw new AssertionError("Lock Service Navigation Failed ", e);
}
}
};
vm.invoke(checkNavigation);
}
/**
* Verify Aggregate MBean
*
* @param vm
*/
@SuppressWarnings("serial")
protected void checkAggregate(final VM vm, final int expectedMembers) {
SerializableRunnable checkAggregate = new SerializableRunnable("Verify Aggregate MBean") {
public void run() {
final ManagementService service = getManagementService();
if (expectedMembers == 0) {
try {
Wait.waitForCriterion(new WaitCriterion() {
DistributedLockServiceMXBean bean = null;
public String description() {
return "Waiting for the proxy to get deleted at managing node";
}
public boolean done() {
bean = service.getDistributedLockServiceMXBean(LOCK_SERVICE_NAME);
boolean done = (bean == null);
return done;
}
}, MAX_WAIT, 500, true);
} catch (Exception e) {
throw new AssertionError("could not remove Aggregate Bean in required time", e);
}
return;
}
DistributedLockServiceMXBean bean = null;
try {
bean = MBeanUtil.getDistributedLockMbean(LOCK_SERVICE_NAME, expectedMembers);
} catch (Exception e) {
InternalDistributedSystem.getLoggerI18n()
.fine("Undesired Result , LockServiceMBean Should not be null", e);
}
assertNotNull(bean);
assertEquals(bean.getName(), LOCK_SERVICE_NAME);
}
};
vm.invoke(checkAggregate);
}
}