blob: 77c3cff5c868d332ea7f248873adcc689b4ab86c [file] [log] [blame]
/*
* Copyright (c) 2021 Eike Stepper (Loehne, Germany) and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Eike Stepper - initial API and implementation
*/
package org.eclipse.emf.cdo.tests;
import org.eclipse.emf.cdo.common.branch.CDOBranch;
import org.eclipse.emf.cdo.common.branch.CDOBranchPoint;
import org.eclipse.emf.cdo.common.id.CDOID;
import org.eclipse.emf.cdo.common.lock.CDOLockOwner;
import org.eclipse.emf.cdo.session.CDOSession;
import org.eclipse.emf.cdo.spi.common.lock.InternalCDOLockState;
import org.eclipse.emf.cdo.tests.config.IRepositoryConfig;
import org.eclipse.emf.cdo.view.CDOView;
import org.eclipse.emf.internal.cdo.session.CDOLockStateCacheImpl;
import org.eclipse.net4j.util.concurrent.IRWLockManager.LockType;
import org.eclipse.net4j.util.io.IOUtil;
import org.eclipse.emf.spi.cdo.CDOLockStateCache;
import java.util.Set;
/**
* @author Eike Stepper
*/
public class LockStateCacheTest extends AbstractCDOTest
{
public void testLockStateCache() throws Exception
{
CDOSession session = openSession();
CDOLockStateCache cache = new CDOLockStateCacheImpl(session);
CDOBranchPoint head = getTestBranch(session).getHead();
CDOView view1 = session.openView(head);
CDOView view2 = session.openView(head);
CDOView view3 = session.openView(head);
CDOView view4 = session.openView(head);
CDOLockOwner owner1 = view1.getLockOwner();
CDOLockOwner owner2 = view2.getLockOwner();
CDOLockOwner owner3 = view3.getLockOwner();
CDOLockOwner owner4 = view4.getLockOwner();
InternalCDOLockState lockState1 = getLockState(cache, view1);
InternalCDOLockState lockState2 = getLockState(cache, view2);
InternalCDOLockState lockState3 = getLockState(cache, view3);
InternalCDOLockState lockState4 = getLockState(cache, view4);
// Write lock.
lockState1.addOwner(owner1, LockType.WRITE);
assertEquals(owner1, lockState1.getWriteLockOwner());
assertEquals(owner1, lockState2.getWriteLockOwner());
assertEquals(owner1, lockState3.getWriteLockOwner());
assertEquals(owner1, lockState4.getWriteLockOwner());
// Another write lock is not possible.
assertException(IllegalStateException.class, () -> lockState2.addOwner(owner2, LockType.WRITE));
// A read lock is not possible.
assertException(IllegalStateException.class, () -> lockState3.addOwner(owner3, LockType.READ));
// A write option is not possible.
assertException(IllegalStateException.class, () -> lockState4.addOwner(owner4, LockType.OPTION));
// Release write lock.
lockState1.removeOwner(owner1, LockType.WRITE);
assertEquals(null, lockState1.getWriteLockOwner());
// Read lock first time.
lockState1.addOwner(owner1, LockType.READ);
assertEquals(1, lockState1.getReadLockOwners().size());
assertTrue(lockState1.getReadLockOwners().contains(owner1));
// A write lock is not possible.
assertException(IllegalStateException.class, () -> lockState4.addOwner(owner4, LockType.WRITE));
// Read lock second time.
lockState1.addOwner(owner2, LockType.READ);
assertEquals(2, lockState1.getReadLockOwners().size());
assertTrue(lockState1.getReadLockOwners().contains(owner1));
assertTrue(lockState1.getReadLockOwners().contains(owner2));
// A write lock is not possible.
assertException(IllegalStateException.class, () -> lockState4.addOwner(owner4, LockType.WRITE));
// Read lock third time.
lockState1.addOwner(owner3, LockType.READ);
assertEquals(3, lockState1.getReadLockOwners().size());
assertTrue(lockState1.getReadLockOwners().contains(owner1));
assertTrue(lockState1.getReadLockOwners().contains(owner2));
assertTrue(lockState1.getReadLockOwners().contains(owner3));
// A write lock is not possible.
assertException(IllegalStateException.class, () -> lockState4.addOwner(owner4, LockType.WRITE));
// Write option.
lockState1.addOwner(owner1, LockType.OPTION);
assertEquals(3, lockState1.getReadLockOwners().size());
assertTrue(lockState1.getReadLockOwners().contains(owner1));
assertTrue(lockState1.getReadLockOwners().contains(owner2));
assertTrue(lockState1.getReadLockOwners().contains(owner3));
assertEquals(owner1, lockState1.getWriteOptionOwner());
}
public void testSetWriteLockOwner() throws Exception
{
// Unlocked.
initial() //
.modify(1, 0) //
.verify(1, 0);
// Write locked by same owner.
initial(1, 0) //
.modify(1, 0) //
.verify(1, 0);
// Write locked by different owner.
initial(2, 0) //
.modify(1, 0) //
.verify(IllegalStateException.class);
// Write optioned by same owner.
initial(0, 1) //
.modify(1, 0) //
.verify(1, 0);
// Write optioned by different owner.
initial(0, 2) //
.modify(1, 0) //
.verify(IllegalStateException.class);
// Read locked by same owner.
initial(0, 0, 1) //
.modify(1, 0) // Lock upgrade.
.verify(1, 0, 1);
// Read locked by different owner.
initial(0, 0, 2) //
.modify(1, 0) //
.verify(IllegalStateException.class);
// Read locked by same and different owner.
initial(0, 0, 1, 2) //
.modify(1, 0) //
.verify(IllegalStateException.class);
// Read locked by same and two different owners.
initial(0, 0, 1, 2, 3) //
.modify(1, 0) //
.verify(IllegalStateException.class);
// Read locked by two different owners.
initial(0, 0, 2, 3) //
.modify(1, 0) //
.verify(IllegalStateException.class);
// Read locked by three different owners.
initial(0, 0, 2, 3, 4) //
.modify(1, 0) //
.verify(IllegalStateException.class);
// Read locked by same owner + write locked by same owner.
initial(1, 0, 1) //
.modify(1, 0) //
.verifyUnmodified();
// Read locked by different owner + write different by same owner.
initial(2, 0, 2) //
.modify(1, 0) //
.verify(IllegalStateException.class);
// Read locked by same owner + write optioned by different owner.
initial(0, 2, 1) //
.modify(1, 0) //
.verify(IllegalStateException.class);
// Read locked by different owner + write optioned by different owner.
initial(0, 2, 2) //
.modify(1, 0) //
.verify(IllegalStateException.class);
// Read locked by same and different owner + write optioned by different owner.
initial(0, 2, 1, 2) //
.modify(1, 0) //
.verify(IllegalStateException.class);
// Read locked by same and two different owners + write optioned by different owner.
initial(0, 2, 1, 2, 3) //
.modify(1, 0) //
.verify(IllegalStateException.class);
// Read locked by two different owners + write optioned by different owner.
initial(0, 2, 2, 3) //
.modify(1, 0) //
.verify(IllegalStateException.class);
// Read locked by three different owners + write optioned by different owner.
initial(0, 2, 2, 3, 4) //
.modify(1, 0) //
.verify(IllegalStateException.class);
// Read locked by same owner + write optioned by same owner.
initial(0, 1, 1) //
.modify(1, 0) //
.verify(1, 0);
// Read locked by different owner + write optioned by different owner.
initial(0, 1, 2) //
.modify(1, 0) //
.verify(IllegalStateException.class);
// Read locked by same and different owner + write optioned by same owner.
initial(0, 1, 1, 2) //
.modify(1, 0) //
.verify(IllegalStateException.class);
// Read locked by same and two different owners + write optioned by same owner.
initial(0, 1, 1, 2, 3) //
.modify(1, 0) //
.verify(IllegalStateException.class);
// Read locked by two different owners + write optioned by same owner.
initial(0, 1, 2, 3) //
.modify(1, 0) //
.verify(IllegalStateException.class);
// Read locked by three different owners + write optioned by same owner.
initial(0, 1, 2, 3, 4) //
.modify(1, 0) //
.verify(IllegalStateException.class);
}
public void testUnsetWriteLockOwner() throws Exception
{
// Unlocked.
initial() //
.modify(-1, 0) //
.verifyUnmodified();
// Write locked.
initial(1, 0) //
.modify(-1, 0) //
.verifyUnlocked();
// Write optioned.
initial(0, 1) //
.modify(-1, 0) //
.verifyUnmodified();
// Read locked.
initial(0, 0, 1) //
.modify(-1, 0) //
.verifyUnmodified();
// Read locked by two owners.
initial(0, 0, 1, 2) //
.modify(-1, 0) //
.verifyUnmodified();
// Read locked by three owners.
initial(0, 0, 2, 3, 4) //
.modify(-1, 0) //
.verifyUnmodified();
// Read locked and write locked.
initial(1, 0, 1) //
.modify(-1, 0) // Lock downgrade.
.verify(0, 0, 1);
// Read locked and write optioned.
initial(0, 1, 1) //
.modify(-1, 0) //
.verifyUnmodified();
initial(0, 1, 1, 2) //
.modify(-1, 0) //
.verifyUnmodified();
initial(0, 1, 1, 2, 3) //
.modify(-1, 0) //
.verifyUnmodified();
initial(0, 4, 1) //
.modify(-1, 0) //
.verifyUnmodified();
initial(0, 4, 1, 2) //
.modify(-1, 0) //
.verifyUnmodified();
initial(0, 4, 1, 2, 3) //
.modify(-1, 0) //
.verifyUnmodified();
}
public void testSetWriteOptionOwner() throws Exception
{
// Unlocked.
initial() //
.modify(0, 1) //
.verify(0, 1);
// Write optioned by same owner.
initial(0, 1) //
.modify(0, 1) //
.verify(0, 1);
// Write optioned by different owner.
initial(0, 2) //
.modify(0, 1) //
.verify(IllegalStateException.class);
// Write locked by same owner.
initial(1, 0) //
.modify(0, 1) //
.verify(IllegalStateException.class);
// Write locked by different owner.
initial(2, 0) //
.modify(0, 1) //
.verify(IllegalStateException.class);
// Read locked by same owner.
initial(0, 0, 1) //
.modify(0, 1) //
.verify(0, 1, 1);
// Read locked by different owner.
initial(0, 0, 2) //
.modify(0, 1) //
.verify(0, 1, 2);
// Write locked by same owner and read locked by same owner.
initial(1, 0, 1) //
.modify(0, 1) //
.verify(IllegalStateException.class);
// Write optioned by same owner and read locked by same owner.
initial(0, 1, 1) //
.modify(0, 1) //
.verifyUnmodified();
// Write optioned by same owner and read locked by different owner.
initial(0, 1, 2) //
.modify(0, 1) //
.verifyUnmodified();
// Write optioned by different owner and read locked by same owner.
initial(0, 2, 1) //
.modify(0, 1) //
.verify(IllegalStateException.class);
// Write optioned by different owner and read locked by different owners.
initial(0, 2, 2) //
.modify(0, 1) //
.verify(IllegalStateException.class);
initial(0, 2, 3) //
.modify(0, 1) //
.verify(IllegalStateException.class);
initial(0, 2, 2, 3) //
.modify(0, 1) //
.verify(IllegalStateException.class);
initial(0, 2, 2, 3, 4) //
.modify(0, 1) //
.verify(IllegalStateException.class);
}
public void testUnsetWriteOptionOwner() throws Exception
{
// Unlocked.
initial() //
.modify(0, -1) //
.verifyUnmodified();
// Write locked.
initial(1, 0) //
.modify(0, -1) //
.verifyUnmodified();
// Write optioned.
initial(0, 1) //
.modify(0, -1) //
.verifyUnlocked();
// Read locked.
initial(0, 0, 1) //
.modify(0, -1) //
.verifyUnmodified();
// Read locked by two owners.
initial(0, 0, 1, 2) //
.modify(0, -1) //
.verifyUnmodified();
// Read locked by three owners.
initial(0, 0, 2, 3, 4) //
.modify(0, -1) //
.verifyUnmodified();
// Read locked and write locked.
initial(1, 0, 1) //
.modify(0, -1) //
.verifyUnmodified();
// Read locked and write optioned.
initial(0, 1, 1) //
.modify(0, -1) //
.verify(0, 0, 1);
initial(0, 1, 1, 2) //
.modify(0, -1) //
.verify(0, 0, 1, 2);
initial(0, 1, 1, 2, 3) //
.modify(0, -1) //
.verify(0, 0, 1, 2, 3);
}
public void testAddReadLockOwner()
{
// Unlocked.
initial() //
.modify(0, 0, 1) //
.verify(0, 0, 1);
// Read locked by same owner.
initial(0, 0, 1) //
.modify(0, 0, 1) //
.verify(0, 0, 1);
// Read locked by different owner.
initial(0, 0, 2) //
.modify(0, 0, 1) //
.verify(0, 0, 2, 1);
// Read locked by two different owners.
initial(0, 0, 2, 3) //
.modify(0, 0, 1) //
.verify(0, 0, 2, 3, 1);
// Read locked by three different owners.
initial(0, 0, 2, 3, 4) //
.modify(0, 0, 1) //
.verify(0, 0, 2, 3, 4, 1);
// Write locked by same owner.
initial(1, 0) //
.modify(0, 0, 1) //
.verify(1, 0, 1);
// Write locked by same owner and read locked by same owner.
initial(1, 0, 1) //
.modify(0, 0, 1) //
.verifyUnmodified();
// Write locked by different owner.
initial(2, 0) //
.modify(0, 0, 1) //
.verify(IllegalStateException.class);
// Write locked by different owner and read locked by different owner.
initial(2, 0, 2) //
.modify(0, 0, 1) //
.verify(IllegalStateException.class);
// Write optioned by same owner.
initial(0, 1) //
.modify(0, 0, 1) //
.verify(0, 1, 1);
// Write optioned by same owner and read locked by same owner.
initial(0, 1, 1) //
.modify(0, 0, 1) //
.verifyUnmodified();
// Write optioned by same owner and read locked by different owner.
initial(0, 1, 2) //
.modify(0, 0, 1) //
.verify(0, 1, 2, 1);
// Write optioned by same owner and read locked by two different owners.
initial(0, 1, 2, 3) //
.modify(0, 0, 1) //
.verify(0, 1, 2, 3, 1);
// Write optioned by same owner and read locked by three different owners.
initial(0, 1, 2, 3, 4) //
.modify(0, 0, 1) //
.verify(0, 1, 2, 3, 4, 1);
// Write optioned by different owner.
initial(0, 2) //
.modify(0, 0, 1) //
.verify(0, 2, 1);
// Write optioned by different owner and read locked by same owner.
initial(0, 2, 1) //
.modify(0, 0, 1) //
.verifyUnmodified();
// Write optioned by different owner and read locked by different owner.
initial(0, 2, 2) //
.modify(0, 0, 1) //
.verify(0, 2, 2, 1);
// Write optioned by different owner and read locked by two different owners.
initial(0, 2, 2, 3) //
.modify(0, 0, 1) //
.verify(0, 2, 2, 3, 1);
// Write optioned by different owner and read locked by three different owners.
initial(0, 2, 2, 3, 4) //
.modify(0, 0, 1) //
.verify(0, 2, 2, 3, 4, 1);
}
public void testRemoveReadLockOwner()
{
// Unlocked.
initial() //
.modify(0, 0, -1) //
.verifyUnmodified();
// Read locked by same owner.
initial(0, 0, 1) //
.modify(0, 0, -1) //
.verifyUnlocked();
// Read locked by same owner and different owner.
initial(0, 0, 1, 2) //
.modify(0, 0, -1) //
.verify(0, 0, 2);
// Read locked by same owner and two different owners.
initial(0, 0, 1, 2, 3) //
.modify(0, 0, -1) //
.verify(0, 0, 2, 3);
// Read locked by same owner and two different owners.
initial(0, 0, 1, 2, 3, 4) //
.modify(0, 0, -1) //
.verify(0, 0, 2, 3, 4);
// Read locked by different owner.
initial(0, 0, 2) //
.modify(0, 0, -1) //
.verifyUnmodified();
// Read locked by two different owners.
initial(0, 0, 2, 3) //
.modify(0, 0, -1) //
.verifyUnmodified();
// Read locked by three different owners.
initial(0, 0, 2, 3, 4) //
.modify(0, 0, -1) //
.verifyUnmodified();
// Write locked by same owner.
initial(1, 0) //
.modify(0, 0, -1) //
.verifyUnmodified();
// Write locked by same owner and read locked by same owner.
initial(1, 0, 1) //
.modify(0, 0, -1) //
.verify(1, 0);
// Write locked by different owner and read locked by different owner.
initial(2, 0, 2) //
.modify(0, 0, -1) //
.verifyUnmodified();
// Write locked by different owner.
initial(2, 0) //
.modify(0, 0, -1) //
.verifyUnmodified();
// Write optioned by same owner.
initial(0, 1) //
.modify(0, 0, -1) //
.verifyUnmodified();
// Write optioned by same owner and read locked by same owner.
initial(0, 1, 1) //
.modify(0, 0, -1) //
.verify(0, 1);
// Write optioned by same owner and read locked by same owner and different owner.
initial(0, 1, 1, 2) //
.modify(0, 0, -1) //
.verify(0, 1, 2);
initial(0, 1, 1, 2) //
.modify(0, 0, -2) //
.verify(0, 1, 1);
initial(0, 1, 1, 2, 3, 4) //
.modify(0, 0, -2) //
.verify(0, 1, 1, 3, 4);
// Write optioned by same owner and read locked by different owner.
initial(0, 1, 2) //
.modify(0, 0, -1) //
.verifyUnmodified();
// Write optioned by same owner and read locked by two different owners.
initial(0, 1, 2, 3) //
.modify(0, 0, -1) //
.verifyUnmodified();
// Write optioned by same owner and read locked by three different owners.
initial(0, 1, 2, 3, 4) //
.modify(0, 0, -1) //
.verifyUnmodified();
// Write optioned by different owner.
initial(0, 2) //
.modify(0, 0, -1) //
.verifyUnmodified();
// Write optioned by different owner and read locked by same owner.
initial(0, 2, 1) //
.modify(0, 0, -1) //
.verify(0, 2);
// Write optioned by different owner and read locked by different owner.
initial(0, 2, 2) //
.modify(0, 0, -1) //
.verifyUnmodified();
// Write optioned by different owner and read locked by two different owners.
initial(0, 2, 2, 3) //
.modify(0, 0, -1) //
.verifyUnmodified();
// Write optioned by different owner and read locked by three different owners.
initial(0, 2, 2, 3, 4) //
.modify(0, 0, -1) //
.verifyUnmodified();
}
public void testRemoveOwner()
{
// Unlocked.
initial() //
.removeOwner(1) //
.verifyUnmodified();
// Read locked by same owner.
initial(0, 0, 1) //
.removeOwner(1) //
.verifyUnlocked();
// Read locked by same owner and different owner.
initial(0, 0, 1, 2) //
.removeOwner(1) //
.verify(0, 0, 2);
// Read locked by same owner and two different owners.
initial(0, 0, 1, 2, 3) //
.removeOwner(1) //
.verify(0, 0, 2, 3);
// Read locked by same owner and two different owners.
initial(0, 0, 1, 2, 3, 4) //
.removeOwner(1) //
.verify(0, 0, 2, 3, 4);
// Read locked by different owner.
initial(0, 0, 2) //
.removeOwner(1) //
.verifyUnmodified();
// Read locked by two different owners.
initial(0, 0, 2, 3) //
.removeOwner(1) //
.verifyUnmodified();
// Read locked by three different owners.
initial(0, 0, 2, 3, 4) //
.removeOwner(1) //
.verifyUnmodified();
// Write locked by same owner.
initial(1, 0) //
.removeOwner(1) //
.verifyUnlocked();
// Write locked by different owner.
initial(2, 0) //
.removeOwner(1) //
.verifyUnmodified();
// Write optioned by same owner.
initial(0, 1) //
.removeOwner(1) //
.verifyUnlocked();
// Write optioned by same owner and read locked by same owner.
initial(0, 1, 1) //
.removeOwner(1) //
.verifyUnlocked();
// Write optioned by same owner and read locked by same owner and different owner.
initial(0, 1, 1, 2) //
.removeOwner(1) //
.verify(0, 0, 2);
initial(0, 1, 1, 2) //
.modify(0, 0, -2) //
.verify(0, 1, 1);
initial(0, 1, 1, 2, 3, 4) //
.modify(0, 0, -2) //
.verify(0, 1, 1, 3, 4);
// Write optioned by same owner and read locked by different owner.
initial(0, 1, 2) //
.removeOwner(1) //
.verify(0, 0, 2);
// Write optioned by same owner and read locked by two different owners.
initial(0, 1, 2, 3) //
.removeOwner(1) //
.verify(0, 0, 2, 3);
// Write optioned by same owner and read locked by three different owners.
initial(0, 1, 2, 3, 4) //
.removeOwner(1) //
.verify(0, 0, 2, 3, 4);
// Write optioned by different owner.
initial(0, 2) //
.removeOwner(1) //
.verifyUnmodified();
// Write optioned by different owner and read locked by same owner.
initial(0, 2, 1) //
.removeOwner(1) //
.verify(0, 2);
// Write optioned by different owner and read locked by different owner.
initial(0, 2, 2) //
.removeOwner(1) //
.verifyUnmodified();
// Write optioned by different owner and read locked by two different owners.
initial(0, 2, 2, 3) //
.removeOwner(1) //
.verifyUnmodified();
// Write optioned by different owner and read locked by three different owners.
initial(0, 2, 2, 3, 4) //
.removeOwner(1) //
.verifyUnmodified();
}
protected CDOBranch getTestBranch(CDOSession session)
{
return session.getBranchManager().getMainBranch();
}
private TestLockState initial()
{
return initial(0, 0);
}
private TestLockState initial(int writer, int optioner, int... readers)
{
return new TestLockState(writer, optioner, readers);
}
private static InternalCDOLockState getLockState(CDOLockStateCache cache, CDOView view)
{
CDOBranch branch = view.getBranch();
CDOID id = view.getRootResource().cdoID();
return (InternalCDOLockState)cache.getLockState(branch, id);
}
/**
* @author Eike Stepper
*/
public final class TestLockState
{
private int initialWriter;
private int initialOptioner;
private int[] initialReaders;
private CDOLockStateCache cache;
private CDOLockOwner[] lockOwners = new CDOLockOwner[5];
private InternalCDOLockState lockState;
public TestLockState(int writer, int optioner, int... readers)
{
initialWriter = writer;
initialOptioner = optioner;
initialReaders = readers;
CDOSession session = openSession();
cache = new CDOLockStateCacheImpl(session);
CDOBranchPoint head = getTestBranch(session).getHead();
for (int i = 0; i < lockOwners.length; i++)
{
CDOView view = session.openView(head);
if (i == 0)
{
lockState = getLockState(cache, view);
}
else
{
lockOwners[i] = view.getLockOwner();
}
}
update(writer, optioner, readers);
}
private void update(int writer, int optioner, int... readers)
{
for (int i = 0; i < readers.length; i++)
{
int reader = readers[i];
if (reader > 0)
{
lockState.addOwner(lockOwners[reader], LockType.READ);
}
else
{
lockState.removeOwner(lockOwners[-reader], LockType.READ);
}
}
if (writer == -1)
{
lockState.removeOwner(lockState.getWriteLockOwner(), LockType.WRITE);
}
else if (writer > 0)
{
lockState.addOwner(lockOwners[writer], LockType.WRITE);
}
if (optioner == -1)
{
lockState.removeOwner(lockState.getWriteOptionOwner(), LockType.OPTION);
}
else if (optioner > 0)
{
lockState.addOwner(lockOwners[optioner], LockType.OPTION);
}
}
private void update(int ownerToRemove)
{
lockState.clearOwner(lockOwners[ownerToRemove]);
}
public TestExecution modify(int writer, int optioner, int... readers)
{
return new TestExecution(writer, optioner, readers);
}
public TestExecution removeOwner(int owner)
{
return new TestExecution(owner);
}
/**
* @author Eike Stepper
*/
public final class TestExecution
{
private int writer;
private int optioner;
private int[] readers;
private int ownerToRemove;
public TestExecution(int writer, int optioner, int[] readers)
{
this.writer = writer;
this.optioner = optioner;
this.readers = readers;
}
public TestExecution(int ownerToRemove)
{
this.ownerToRemove = ownerToRemove;
}
public void verify(int writer, int optioner, int... readers)
{
try
{
update();
CDOLockOwner writeLockOwner = lockState.getWriteLockOwner();
assertEquals(lockOwners[writer], writeLockOwner);
assertEquals(writeLockOwner != null, lockState.isLocked(LockType.WRITE, writeLockOwner, false));
assertEquals(writeLockOwner != null, lockState.isLocked(null, writeLockOwner, false));
CDOLockOwner writeOptionOwner = lockState.getWriteOptionOwner();
assertEquals(lockOwners[optioner], writeOptionOwner);
assertEquals(writeOptionOwner != null, lockState.isLocked(LockType.OPTION, writeOptionOwner, false));
assertEquals(writeOptionOwner != null, lockState.isLocked(null, writeOptionOwner, false));
Set<CDOLockOwner> readLockOwners = lockState.getReadLockOwners();
assertEquals(readers.length, readLockOwners.size());
for (int i = 0; i < readers.length; i++)
{
CDOLockOwner readLockOwner = lockOwners[readers[i]];
assertTrue(readLockOwners.contains(readLockOwner));
}
for (int i = 1; i < lockOwners.length; i++)
{
CDOLockOwner readLockOwner = lockOwners[i];
boolean readLocked = readLockOwners.contains(readLockOwner);
assertEquals(readLocked, lockState.isLocked(LockType.READ, readLockOwner, false));
boolean locked = readLockOwner == writeLockOwner || readLockOwner == writeOptionOwner || readLocked;
assertEquals(locked, lockState.isLocked(null, readLockOwner, false));
}
}
catch (Error ex)
{
dumpActualLockState();
throw ex;
}
finally
{
cache.getSession().close();
}
}
public void verifyUnlocked()
{
verify(0, 0);
}
public void verifyUnmodified()
{
verify(initialWriter, initialOptioner, initialReaders);
}
public void verify(Class<? extends Throwable> type)
{
try
{
assertException(type, () -> update());
}
catch (Error ex)
{
dumpActualLockState();
throw ex;
}
finally
{
cache.getSession().close();
}
}
private void update()
{
if (ownerToRemove != 0)
{
TestLockState.this.update(ownerToRemove);
}
else
{
TestLockState.this.update(writer, optioner, readers);
}
}
private void dumpActualLockState()
{
IOUtil.ERR().println();
IOUtil.ERR().println("################################################");
IOUtil.ERR().println("Actual lock state: " //
+ index(lockState.getWriteLockOwner()) + ", " //
+ index(lockState.getWriteOptionOwner()) //
+ index(lockState.getReadLockOwners()));
IOUtil.ERR().println("################################################");
IOUtil.ERR().println();
}
private String index(Set<CDOLockOwner> lockOwners)
{
StringBuilder builder = new StringBuilder();
for (CDOLockOwner lockOwner : lockOwners)
{
builder.append(", ");
builder.append(index(lockOwner));
}
return builder.toString();
}
private String index(CDOLockOwner lockOwner)
{
for (int i = 0; i < lockOwners.length; i++)
{
if (lockOwners[i] == lockOwner)
{
return Integer.toString(i);
}
}
return null;
}
}
}
/**
* @author Eike Stepper
*/
@Requires(IRepositoryConfig.CAPABILITY_BRANCHING)
public static class WithSubBranch extends LockStateCacheTest
{
private CDOBranch testBranch;
@Override
protected CDOBranch getTestBranch(CDOSession session)
{
if (testBranch == null)
{
testBranch = createUniqueBranch(session.getBranchManager().getMainBranch(), "lock-state-tests");
}
return testBranch;
}
@Override
protected void doTearDown() throws Exception
{
testBranch = null;
super.doTearDown();
}
}
}