/**
* Licensed to JumpMind Inc under one or more contributor
* license agreements. See the NOTICE file distributed
* with this work for additional information regarding
* copyright ownership. JumpMind Inc licenses this file
* to you under the GNU General Public License, version 3.0 (GPLv3)
* (the "License"); you may not use this file except in compliance
* with the License.
*
* You should have received a copy of the GNU General Public License,
* version 3.0 (GPLv3) along with this library; if not, see
* <http://www.gnu.org/licenses/>.
*
* 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.jumpmind.symmetric.service.impl;
import junit.framework.Assert;
import org.jumpmind.symmetric.common.ParameterConstants;
import org.jumpmind.symmetric.model.Lock;
import org.jumpmind.symmetric.service.ClusterConstants;
import org.junit.Before;
import org.junit.Test;
public abstract class AbstractClusterServiceTest extends AbstractServiceTest {
@Before
public void setupForTest() {
getClusterService().init();
getParameterService().saveParameter(ParameterConstants.LOCK_WAIT_RETRY_MILLIS, "1", "test");
}
@Test
public void testLockCluster() {
lock(ClusterConstants.PULL, ClusterConstants.TYPE_CLUSTER, 0);
// Should allow multiple cluster locks when on same server
lock(ClusterConstants.PULL, ClusterConstants.TYPE_CLUSTER, 0);
unlock(ClusterConstants.PULL, ClusterConstants.TYPE_CLUSTER, 0);
}
@Test
public void testLockShare() {
lock(ClusterConstants.FILE_SYNC_SHARED, ClusterConstants.TYPE_SHARED, 1);
// Should allow multiple shared locks and increase shared count
lock(ClusterConstants.FILE_SYNC_SHARED, ClusterConstants.TYPE_SHARED, 2);
// Should prevent an exclusive lock
Assert.assertFalse(getClusterService().lock(ClusterConstants.FILE_SYNC_SHARED, ClusterConstants.TYPE_EXCLUSIVE));
// Releasing shared lock should decrease shared count
unlock(ClusterConstants.FILE_SYNC_SHARED, ClusterConstants.TYPE_SHARED, 1);
// Releasing final shared lock
unlock(ClusterConstants.FILE_SYNC_SHARED, ClusterConstants.TYPE_SHARED, 0);
}
@Test
public void testLockShareAfterExclusive() {
lock(ClusterConstants.FILE_SYNC_SHARED, ClusterConstants.TYPE_EXCLUSIVE, 0);
unlock(ClusterConstants.FILE_SYNC_SHARED, ClusterConstants.TYPE_EXCLUSIVE, 0);
lock(ClusterConstants.FILE_SYNC_SHARED, ClusterConstants.TYPE_SHARED, 1);
unlock(ClusterConstants.FILE_SYNC_SHARED, ClusterConstants.TYPE_SHARED, 0);
}
@Test
public void testLockShareAbandoned() {
lock(ClusterConstants.FILE_SYNC_SHARED, ClusterConstants.TYPE_SHARED, 1);
getClusterService().init();
checkUnlock(ClusterConstants.FILE_SYNC_SHARED, ClusterConstants.TYPE_SHARED, 0, false);
}
@Test
public void testLockExclusive() {
lock(ClusterConstants.FILE_SYNC_SHARED, ClusterConstants.TYPE_EXCLUSIVE, 0);
// Should prevent a second exclusive lock
Assert.assertFalse(getClusterService().lock(ClusterConstants.FILE_SYNC_SHARED, ClusterConstants.TYPE_EXCLUSIVE));
// Should prevent a shared lock
Assert.assertFalse(getClusterService().lock(ClusterConstants.FILE_SYNC_SHARED, ClusterConstants.TYPE_SHARED));
unlock(ClusterConstants.FILE_SYNC_SHARED, ClusterConstants.TYPE_EXCLUSIVE, 0);
getClusterService().unlock(ClusterConstants.FILE_SYNC_SHARED, ClusterConstants.TYPE_EXCLUSIVE);
}
@Test
public void testLockExclusiveAfterShare() {
lock(ClusterConstants.FILE_SYNC_SHARED, ClusterConstants.TYPE_SHARED, 1);
unlock(ClusterConstants.FILE_SYNC_SHARED, ClusterConstants.TYPE_SHARED, 0);
lock(ClusterConstants.FILE_SYNC_SHARED, ClusterConstants.TYPE_EXCLUSIVE, 0);
unlock(ClusterConstants.FILE_SYNC_SHARED, ClusterConstants.TYPE_EXCLUSIVE, 0);
}
@Test
public void testLockExclusiveAbandoned() {
lock(ClusterConstants.FILE_SYNC_SHARED, ClusterConstants.TYPE_EXCLUSIVE, 0);
getClusterService().init();
checkUnlock(ClusterConstants.FILE_SYNC_SHARED, ClusterConstants.TYPE_EXCLUSIVE, 0, false);
}
@Test
public void testLockExclusiveWait() {
lock(ClusterConstants.FILE_SYNC_SHARED, ClusterConstants.TYPE_SHARED, 1);
Assert.assertFalse(getClusterService().lock(ClusterConstants.FILE_SYNC_SHARED, ClusterConstants.TYPE_EXCLUSIVE, 1));
checkLock(ClusterConstants.FILE_SYNC_SHARED, ClusterConstants.TYPE_SHARED, 1, false);
Assert.assertFalse(getClusterService().lock(ClusterConstants.FILE_SYNC_SHARED, ClusterConstants.TYPE_SHARED));
unlock(ClusterConstants.FILE_SYNC_SHARED, ClusterConstants.TYPE_SHARED, 0);
Assert.assertTrue(getClusterService().lock(ClusterConstants.FILE_SYNC_SHARED, ClusterConstants.TYPE_EXCLUSIVE, 1));
unlock(ClusterConstants.FILE_SYNC_SHARED, ClusterConstants.TYPE_EXCLUSIVE, 0);
}
@Test
public void testLockSharedWait() {
lock(ClusterConstants.FILE_SYNC_SHARED, ClusterConstants.TYPE_EXCLUSIVE, 0);
Assert.assertFalse(getClusterService().lock(ClusterConstants.FILE_SYNC_SHARED, ClusterConstants.TYPE_SHARED, 1));
checkLock(ClusterConstants.FILE_SYNC_SHARED, ClusterConstants.TYPE_EXCLUSIVE, 0, false);
unlock(ClusterConstants.FILE_SYNC_SHARED, ClusterConstants.TYPE_EXCLUSIVE, 0);
lock(ClusterConstants.FILE_SYNC_SHARED, ClusterConstants.TYPE_SHARED, 1);
unlock(ClusterConstants.FILE_SYNC_SHARED, ClusterConstants.TYPE_SHARED, 0);
}
private void lock(String action, String lockType, int expectedSharedCount) {
Assert.assertTrue("Expected to obtain lock", getClusterService().lock(action, lockType));
checkLock(action, lockType, expectedSharedCount, expectedSharedCount > 0);
}
private void unlock(String action, String lockType, int expectedSharedCount) {
getClusterService().unlock(action, lockType);
checkUnlock(action, lockType, expectedSharedCount, expectedSharedCount > 0);
}
private Lock checkLock(String action, String lockType, int expectedSharedCount, boolean expectedSharedEnable) {
Lock lock = getClusterService().findLocks().get(action);
Assert.assertEquals(lockType, lock.getLockType());
Assert.assertNotNull(lock.getLockingServerId());
Assert.assertNotNull(lock.getLockTime());
Assert.assertEquals(expectedSharedCount, lock.getSharedCount());
if (expectedSharedCount > 0) {
Assert.assertEquals(expectedSharedEnable, lock.isSharedEnable());
}
return lock;
}
private void checkUnlock(String action, String lockType, int expectedSharedCount, boolean expectedSharedEnable) {
Lock lock = getClusterService().findLocks().get(action);
Assert.assertEquals(lockType, lock.getLockType());
Assert.assertNotNull(lock.getLastLockingServerId());
Assert.assertNotNull(lock.getLastLockTime());
if (lockType != ClusterConstants.TYPE_SHARED || lock.getSharedCount() == 0) {
Assert.assertNull(lock.getLockingServerId());
Assert.assertNull(lock.getLockTime());
Assert.assertFalse(lock.isSharedEnable());
}
Assert.assertEquals(expectedSharedCount, lock.getSharedCount());
}
}