/* * Copyright (c) 2011, 2012, 2016 Eike Stepper (Berlin, 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: * Caspar De Groot - initial API and implementation */ package org.eclipse.emf.cdo.tests.offline; import org.eclipse.emf.cdo.CDOObject; import org.eclipse.emf.cdo.common.lock.CDOLockChangeInfo.Operation; import org.eclipse.emf.cdo.eresource.CDOResource; import org.eclipse.emf.cdo.internal.server.syncing.OfflineClone; import org.eclipse.emf.cdo.session.CDOSession; import org.eclipse.emf.cdo.session.CDOSessionInvalidationEvent; import org.eclipse.emf.cdo.session.CDOSessionLocksChangedEvent; import org.eclipse.emf.cdo.tests.AbstractSyncingTest; import org.eclipse.emf.cdo.tests.model1.Company; import org.eclipse.emf.cdo.tests.util.TestListener2; import org.eclipse.emf.cdo.transaction.CDOTransaction; import org.eclipse.emf.cdo.util.CDOUtil; import org.eclipse.emf.cdo.view.CDOView; import org.eclipse.emf.cdo.view.CDOViewLocksChangedEvent; import org.eclipse.net4j.util.concurrent.IRWLockManager.LockType; /** * @author Caspar De Groot */ public class OfflineLockingTest extends AbstractSyncingTest { public void testLockAndUnlockThrough() throws Exception { assertEquals(true, getRepository("repo1") instanceof OfflineClone); CDOSession masterSession = openSession("master"); CDOSession cloneSession = openSession("repo1"); waitForOnline(cloneSession.getRepositoryInfo()); CDOTransaction cloneTx = cloneSession.openTransaction(); cloneTx.enableDurableLocking(); CDOResource res = cloneTx.createResource(getResourcePath("test")); Company company = getModel1Factory().createCompany(); res.getContents().add(company); cloneTx.commit(); CDOObject cdoCompany = CDOUtil.getCDOObject(company); CDOView masterView = masterSession.openView(); masterView.options().setLockNotificationEnabled(true); TestListener2 masterViewListener = new TestListener2(CDOViewLocksChangedEvent.class); masterView.addListener(masterViewListener); CDOObject cdoCompanyOnMaster = masterView.getObject(cdoCompany.cdoID()); cdoCompany.cdoWriteLock().lock(); masterViewListener.waitFor(1); assertEquals(true, cdoCompanyOnMaster.cdoWriteLock().isLockedByOthers()); cdoCompany.cdoWriteLock().unlock(); masterViewListener.waitFor(2); assertEquals(false, cdoCompanyOnMaster.cdoWriteLock().isLockedByOthers()); cloneSession.close(); masterSession.close(); } public void testCloneLocks_arrivalInOtherClone() throws Exception { // Create a 2nd clone repository assertEquals(true, getRepository("repo1") instanceof OfflineClone); assertEquals(true, getRepository("repo2") instanceof OfflineClone); CDOSession clone1Session = openSession("repo1"); TestListener2 session1lockListener = new TestListener2(CDOSessionLocksChangedEvent.class, "session1lockListener"); clone1Session.addListener(session1lockListener); waitForOnline(clone1Session.getRepositoryInfo()); CDOSession clone2Session = openSession("repo2"); TestListener2 session2invalidationListener = new TestListener2(CDOSessionInvalidationEvent.class, "session2invalidationListener"); clone2Session.addListener(session2invalidationListener); TestListener2 session2lockListener = new TestListener2(CDOSessionLocksChangedEvent.class, "session2lockListener"); clone2Session.addListener(session2lockListener); waitForOnline(clone2Session.getRepositoryInfo()); CDOTransaction clone1Tx = openTransaction(clone1Session); CDOResource resourceInSession1 = clone1Tx.createResource(getResourcePath("test")); Company companyA = getModel1Factory().createCompany(); Company companyB = getModel1Factory().createCompany(); Company companyC = getModel1Factory().createCompany(); resourceInSession1.getContents().add(companyA); resourceInSession1.getContents().add(companyB); resourceInSession1.getContents().add(companyC); clone1Tx.commit(); CDOObject companyA_session1 = CDOUtil.getCDOObject(companyA); CDOObject companyB_session1 = CDOUtil.getCDOObject(companyB); CDOObject companyC_session1 = CDOUtil.getCDOObject(companyC); session2invalidationListener.setTimeout(Integer.MAX_VALUE); session2invalidationListener.waitFor(1); // Wait for the commit notification CDOTransaction clone2Tx = openTransaction(clone2Session); CDOResource resourceInSession2 = clone2Tx.getResource(getResourcePath("test")); CDOObject companyA_session2 = CDOUtil.getCDOObject(resourceInSession2.getContents().get(0)); CDOObject companyB_session2 = CDOUtil.getCDOObject(resourceInSession2.getContents().get(1)); CDOObject companyC_session2 = CDOUtil.getCDOObject(resourceInSession2.getContents().get(2)); CDOSessionLocksChangedEvent e; // Verify that thusfar we haven't received any locking events in session 1 assertEquals(0, session1lockListener.getEvents().size()); // Perform the lock in session 2, connected to clone 2 companyA_session2.cdoWriteLock().lock(); // Wait for the lock notification in session 1, which is connected to clone 1 session1lockListener.waitFor(1); e = (CDOSessionLocksChangedEvent)session1lockListener.getEvents().get(0); assertSame(LockType.WRITE, e.getLockType()); assertSame(Operation.LOCK, e.getOperation()); assertEquals(true, companyA_session1.cdoWriteLock().isLockedByOthers()); // Perform the unlock in session 2, connected to clone 2 companyA_session2.cdoWriteLock().unlock(); // Wait for the lock notification in session 1, which is connected to clone 1 session1lockListener.waitFor(2); e = (CDOSessionLocksChangedEvent)session1lockListener.getEvents().get(1); assertSame(LockType.WRITE, e.getLockType()); assertSame(Operation.UNLOCK, e.getOperation()); assertEquals(false, companyA_session1.cdoWriteLock().isLockedByOthers()); // Now vice versa . . . session2lockListener.getEvents().clear(); // Perform the lock in session 1, connected to clone 1 companyA_session1.cdoWriteLock().lock(); // Wait for the lock notification in session 2, which is connected to clone 2 session2lockListener.waitFor(1); e = (CDOSessionLocksChangedEvent)session2lockListener.getEvents().get(0); assertSame(LockType.WRITE, e.getLockType()); assertSame(Operation.LOCK, e.getOperation()); assertEquals(true, companyA_session2.cdoWriteLock().isLockedByOthers()); // Perform the unlock in session 1, connected to clone 1 companyA_session1.cdoWriteLock().unlock(); // Wait for the lock notification in session 1, which is connected to clone 1 session2lockListener.waitFor(2); e = (CDOSessionLocksChangedEvent)session2lockListener.getEvents().get(1); assertSame(LockType.WRITE, e.getLockType()); assertSame(Operation.UNLOCK, e.getOperation()); assertEquals(false, companyA_session2.cdoWriteLock().isLockedByOthers()); // Now try an unlock-all . . . session1lockListener.getEvents().clear(); companyA_session2.cdoReadLock().lock(); companyB_session2.cdoWriteLock().lock(); companyC_session2.cdoWriteOption().lock(); session1lockListener.waitFor(3); assertEquals(true, companyA_session1.cdoReadLock().isLockedByOthers()); assertEquals(true, companyB_session1.cdoWriteLock().isLockedByOthers()); assertEquals(true, companyC_session1.cdoWriteOption().isLockedByOthers()); clone2Tx.unlockObjects(); session1lockListener.waitFor(4); assertEquals(false, companyA_session1.cdoReadLock().isLockedByOthers()); assertEquals(false, companyA_session1.cdoWriteLock().isLockedByOthers()); assertEquals(false, companyA_session1.cdoWriteOption().isLockedByOthers()); clone1Session.close(); clone2Session.close(); } }