From 64bc75c17dcccfe26cd009660f743d7d0faa3ab4 Mon Sep 17 00:00:00 2001 From: Caspar De Groot Date: Thu, 15 Sep 2011 04:13:42 +0000 Subject: [356754] Raw replication of persistent locks https://bugs.eclipse.org/bugs/show_bug.cgi?id=356754 --- .../emf/cdo/common/lock/CDOLockChangeInfo.java | 5 + .../eclipse/emf/cdo/common/lock/CDOLockUtil.java | 11 +- .../common/lock/CDOLockChangeInfoImpl.java | 22 +++- .../internal/common/protocol/CDODataInputImpl.java | 7 ++ .../common/protocol/CDODataOutputImpl.java | 26 +++-- .../cdo/server/internal/db/DBStoreAccessor.java | 12 +++ .../emf/cdo/internal/server/LockManager.java | 45 +++++---- .../eclipse/emf/cdo/internal/server/Session.java | 5 +- .../server/syncing/SynchronizableRepository.java | 12 ++- .../emf/cdo/spi/server/InternalLockManager.java | 5 + .../emf/cdo/tests/db/AllTestsDBH2Offline.java | 4 + .../eclipse/emf/cdo/tests/AbstractSyncingTest.java | 8 ++ .../eclipse/emf/cdo/tests/AllTestsMEMOffline.java | 9 +- .../emf/cdo/tests/offline/OfflineDelayedTest.java | 4 - .../offline/OfflineLockRawReplicationTest.java | 23 +++++ .../emf/cdo/tests/offline/OfflineLockingTest.java | 111 --------------------- .../eclipse/emf/internal/cdo/CDOObjectImpl.java | 19 +--- .../emf/internal/cdo/object/CDOLegacyWrapper.java | 16 +-- .../cdo/util/DefaultLocksChangedEvent.java | 5 + .../eclipse/emf/internal/cdo/view/CDOViewImpl.java | 46 ++++++++- .../org/eclipse/emf/spi/cdo/InternalCDOObject.java | 6 -- .../src/org/eclipse/net4j/db/DBUtil.java | 9 ++ 22 files changed, 216 insertions(+), 194 deletions(-) create mode 100644 plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/offline/OfflineLockRawReplicationTest.java diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/lock/CDOLockChangeInfo.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/lock/CDOLockChangeInfo.java index 3669f9abe3..643901354f 100644 --- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/lock/CDOLockChangeInfo.java +++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/lock/CDOLockChangeInfo.java @@ -30,6 +30,11 @@ import org.eclipse.net4j.util.concurrent.IRWLockManager.LockType; */ public interface CDOLockChangeInfo extends CDOBranchPoint { + /** + * + */ + public boolean isInvalidateAll(); + /** * @return The branch at which the lock changes took place, same as getView().getBranch(). */ diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/lock/CDOLockUtil.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/lock/CDOLockUtil.java index 3250f5adfa..b0defe9ac4 100644 --- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/lock/CDOLockUtil.java +++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/lock/CDOLockUtil.java @@ -18,10 +18,10 @@ import org.eclipse.emf.cdo.common.id.CDOID; import org.eclipse.emf.cdo.common.lock.CDOLockChangeInfo.Operation; import org.eclipse.emf.cdo.common.lock.IDurableLockingManager.LockArea; import org.eclipse.emf.cdo.common.lock.IDurableLockingManager.LockGrade; +import org.eclipse.emf.cdo.internal.common.lock.CDOLockAreaImpl; import org.eclipse.emf.cdo.internal.common.lock.CDOLockChangeInfoImpl; import org.eclipse.emf.cdo.internal.common.lock.CDOLockOwnerImpl; import org.eclipse.emf.cdo.internal.common.lock.CDOLockStateImpl; -import org.eclipse.emf.cdo.internal.common.lock.CDOLockAreaImpl; import org.eclipse.emf.cdo.spi.common.lock.InternalCDOLockState; import org.eclipse.net4j.util.CheckUtil; @@ -72,7 +72,7 @@ public final class CDOLockUtil sessionID = session.getSessionID(); viewID = view.getViewID(); } - + CDOLockOwner owner = new CDOLockOwnerImpl(sessionID, viewID, durableLockingID, isDurableView); cdoLockState.addReadLockOwner(owner); } @@ -104,7 +104,7 @@ public final class CDOLockUtil int viewID = view.getViewID(); return new CDOLockOwnerImpl(sessionID, viewID, durableLockingID, false); } - + CheckUtil.checkNull(durableLockingID, "durableLockingID"); return new CDOLockOwnerImpl(0, 0, durableLockingID, true); // TODO (CD) Symbolic constants? } @@ -115,6 +115,11 @@ public final class CDOLockUtil return new CDOLockChangeInfoImpl(branch.getPoint(timestamp), lockOwner, cdoLockStates, op, lockType); } + public static CDOLockChangeInfo createLockChangeInfo() + { + return new CDOLockChangeInfoImpl(); + } + public static CDOLockChangeInfo createLockChangeInfo(long timestamp, CDOCommonView view, CDOBranch viewedBranch, Operation op, LockType lockType, CDOLockState[] cdoLockStates) { diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/lock/CDOLockChangeInfoImpl.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/lock/CDOLockChangeInfoImpl.java index e8a7a16b62..11a3091eb6 100644 --- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/lock/CDOLockChangeInfoImpl.java +++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/lock/CDOLockChangeInfoImpl.java @@ -33,6 +33,8 @@ public class CDOLockChangeInfoImpl implements CDOLockChangeInfo private final LockType lockType; + private final boolean isInvalidateAll; + public CDOLockChangeInfoImpl(CDOBranchPoint branchPoint, CDOLockOwner lockOwner, CDOLockState[] lockStates, Operation operation, LockType lockType) { @@ -41,16 +43,27 @@ public class CDOLockChangeInfoImpl implements CDOLockChangeInfo this.lockStates = lockStates; this.operation = operation; this.lockType = lockType; + isInvalidateAll = false; + } + + public CDOLockChangeInfoImpl() + { + branchPoint = null; + lockOwner = null; + lockStates = null; + operation = null; + lockType = null; + isInvalidateAll = true; } public CDOBranch getBranch() { - return branchPoint.getBranch(); + return branchPoint == null ? null : branchPoint.getBranch(); } public long getTimeStamp() { - return branchPoint.getTimeStamp(); + return branchPoint == null ? 0L : branchPoint.getTimeStamp(); } public CDOLockOwner getLockOwner() @@ -72,4 +85,9 @@ public class CDOLockChangeInfoImpl implements CDOLockChangeInfo { return lockType; } + + public boolean isInvalidateAll() + { + return isInvalidateAll; + } } diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/protocol/CDODataInputImpl.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/protocol/CDODataInputImpl.java index 8928db8eb3..1590d4027f 100644 --- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/protocol/CDODataInputImpl.java +++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/protocol/CDODataInputImpl.java @@ -30,6 +30,7 @@ import org.eclipse.emf.cdo.common.lock.CDOLockChangeInfo; import org.eclipse.emf.cdo.common.lock.CDOLockChangeInfo.Operation; import org.eclipse.emf.cdo.common.lock.CDOLockOwner; import org.eclipse.emf.cdo.common.lock.CDOLockState; +import org.eclipse.emf.cdo.common.lock.CDOLockUtil; import org.eclipse.emf.cdo.common.lock.IDurableLockingManager.LockArea; import org.eclipse.emf.cdo.common.lock.IDurableLockingManager.LockGrade; import org.eclipse.emf.cdo.common.model.CDOClassifierRef; @@ -270,6 +271,12 @@ public abstract class CDODataInputImpl extends ExtendedDataInput.Delegating impl public CDOLockChangeInfo readCDOLockChangeInfo() throws IOException { + boolean isInvalidateAll = readBoolean(); + if (isInvalidateAll) + { + return CDOLockUtil.createLockChangeInfo(); + } + CDOBranchPoint branchPoint = readCDOBranchPoint(); CDOLockOwner lockOwner = readCDOLockOwner(); Operation operation = readEnum(Operation.class); diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/protocol/CDODataOutputImpl.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/protocol/CDODataOutputImpl.java index ef3bcdaa6b..1ebd54b3dd 100644 --- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/protocol/CDODataOutputImpl.java +++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/protocol/CDODataOutputImpl.java @@ -227,16 +227,24 @@ public abstract class CDODataOutputImpl extends ExtendedDataOutput.Delegating im public void writeCDOLockChangeInfo(CDOLockChangeInfo lockChangeInfo) throws IOException { - writeCDOBranchPoint(lockChangeInfo); - writeCDOLockOwner(lockChangeInfo.getLockOwner()); - writeEnum(lockChangeInfo.getOperation()); - writeCDOLockType(lockChangeInfo.getLockType()); - - CDOLockState[] lockStates = lockChangeInfo.getLockStates(); - writeInt(lockStates.length); - for (CDOLockState lockState : lockStates) + if (lockChangeInfo.isInvalidateAll()) + { + writeBoolean(true); + } + else { - writeCDOLockState(lockState); + writeBoolean(false); + writeCDOBranchPoint(lockChangeInfo); + writeCDOLockOwner(lockChangeInfo.getLockOwner()); + writeEnum(lockChangeInfo.getOperation()); + writeCDOLockType(lockChangeInfo.getLockType()); + + CDOLockState[] lockStates = lockChangeInfo.getLockStates(); + writeInt(lockStates.length); + for (CDOLockState lockState : lockStates) + { + writeCDOLockState(lockState); + } } } diff --git a/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/DBStoreAccessor.java b/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/DBStoreAccessor.java index 42aca92d88..fc5ad2928f 100644 --- a/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/DBStoreAccessor.java +++ b/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/DBStoreAccessor.java @@ -1102,6 +1102,9 @@ public class DBStoreAccessor extends StoreAccessor implements IDBStoreAccessor, where = " WHERE " + CDODBSchema.COMMIT_INFOS_TIMESTAMP + " BETWEEN " + fromCommitTime + " AND " + toCommitTime; DBUtil.serializeTable(out, connection, CDODBSchema.COMMIT_INFOS, null, where); + DBUtil.serializeTable(out, connection, store.getDBSchema().getTable("cdo_lock_areas"), null, null); + DBUtil.serializeTable(out, connection, store.getDBSchema().getTable("cdo_locks"), null, null); + IIDHandler idHandler = store.getIDHandler(); idHandler.rawExport(connection, out, fromCommitTime, toCommitTime); @@ -1132,6 +1135,15 @@ public class DBStoreAccessor extends StoreAccessor implements IDBStoreAccessor, { DBUtil.deserializeTable(in, connection, CDODBSchema.BRANCHES, monitor.fork()); DBUtil.deserializeTable(in, connection, CDODBSchema.COMMIT_INFOS, monitor.fork()); + + // Delete all non-empty lock areas + String sql = "DELETE FROM cdo_lock_areas WHERE EXISTS (SELECT * FROM cdo_locks WHERE cdo_locks.area_id=cdo_lock_areas.id)"; + DBUtil.update(connection, sql); + DBUtil.deserializeTable(in, connection, store.getDBSchema().getTable("cdo_lock_areas"), monitor.fork()); + + DBUtil.clearTable(connection, "cdo_locks"); + DBUtil.deserializeTable(in, connection, store.getDBSchema().getTable("cdo_locks"), monitor.fork()); + store.getIDHandler().rawImport(connection, in, fromCommitTime, toCommitTime, monitor.fork()); rawImportPackageUnits(in, fromCommitTime, toCommitTime, packageUnits, monitor.fork()); mappingStrategy.rawImport(this, in, fromCommitTime, toCommitTime, monitor.fork(size)); diff --git a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/LockManager.java b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/LockManager.java index 5db93a490f..421c51de87 100644 --- a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/LockManager.java +++ b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/LockManager.java @@ -352,7 +352,7 @@ public class LockManager extends RWOLockManager implements Intern protected void doActivate() throws Exception { super.doActivate(); - loadDurableLocks(); + loadLocks(); getRepository().getSessionManager().addListener(sessionManagerListener); } @@ -391,7 +391,13 @@ public class LockManager extends RWOLockManager implements Intern throw new IllegalStateException("Store does not implement " + DurableLocking2.class.getSimpleName()); } - private void loadDurableLocks() + public void reloadLocks() + { + DurableLockLoader handler = new DurableLockLoader(); + getLockAreas(null, handler); + } + + private void loadLocks() { InternalStore store = repository.getStore(); IStoreAccessor reader = null; @@ -402,9 +408,7 @@ public class LockManager extends RWOLockManager implements Intern if (reader instanceof DurableLocking) { StoreThreadLocal.setAccessor(reader); - - DurableLockLoader handler = new DurableLockLoader(); - getLockAreas(null, handler); + reloadLocks(); } } finally @@ -578,10 +582,24 @@ public class LockManager extends RWOLockManager implements Intern { } + private IView getView(String lockAreaID) + { + IView view = openViews.get(lockAreaID); + if (view == null) + { + view = durableViews.get(lockAreaID); + } + return view; + } + public boolean handleLockArea(LockArea area) { String durableLockingID = area.getDurableLockingID(); - IView view = durableViews.get(durableLockingID); + IView view = getView(durableLockingID); + if (view != null) + { + unlock2(view); + } if (view == null) { view = new DurableView(durableLockingID); @@ -643,16 +661,6 @@ public class LockManager extends RWOLockManager implements Intern return grade; } - private IView getView(String lockAreaID) - { - IView view = openViews.get(lockAreaID); - if (view == null) - { - view = durableViews.get(lockAreaID); - } - return view; - } - private LockArea getLockAreaNoEx(String durableLockingID) { try @@ -683,11 +691,6 @@ public class LockManager extends RWOLockManager implements Intern else { accessor.updateLockArea(lockArea); - IView view = getView(durableLockingID); - if (view != null) - { - unlock2(view); - } new DurableLockLoader().handleLockArea(lockArea); } } diff --git a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/Session.java b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/Session.java index bb0205d2ba..811329e688 100644 --- a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/Session.java +++ b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/Session.java @@ -16,6 +16,7 @@ package org.eclipse.emf.cdo.internal.server; import org.eclipse.emf.cdo.common.CDOCommonRepository; import org.eclipse.emf.cdo.common.CDOCommonSession; +import org.eclipse.emf.cdo.common.branch.CDOBranch; import org.eclipse.emf.cdo.common.branch.CDOBranchPoint; import org.eclipse.emf.cdo.common.commit.CDOCommitInfo; import org.eclipse.emf.cdo.common.id.CDOID; @@ -491,7 +492,9 @@ public class Session extends Container implements InternalSession // only then do we send the lockChangeInfo. for (InternalView view : getViews()) { - if (view.options().isLockNotificationEnabled() && view.getBranch().equals(lockChangeInfo.getBranch())) + boolean notificationsEnabled = view.options().isLockNotificationEnabled(); + CDOBranch affectedBranch = lockChangeInfo.getBranch(); + if (notificationsEnabled && (view.getBranch().equals(affectedBranch) || affectedBranch == null)) { protocol.sendLockNotification(lockChangeInfo); break; diff --git a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/syncing/SynchronizableRepository.java b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/syncing/SynchronizableRepository.java index 2276dc9b99..2fb3a4a38d 100644 --- a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/syncing/SynchronizableRepository.java +++ b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/syncing/SynchronizableRepository.java @@ -24,6 +24,7 @@ import org.eclipse.emf.cdo.common.lock.CDOLockChangeInfo; import org.eclipse.emf.cdo.common.lock.CDOLockChangeInfo.Operation; import org.eclipse.emf.cdo.common.lock.CDOLockOwner; import org.eclipse.emf.cdo.common.lock.CDOLockState; +import org.eclipse.emf.cdo.common.lock.CDOLockUtil; import org.eclipse.emf.cdo.common.lock.IDurableLockingManager.LockArea; import org.eclipse.emf.cdo.common.model.CDOPackageUnit; import org.eclipse.emf.cdo.common.protocol.CDODataInput; @@ -317,7 +318,7 @@ public abstract class SynchronizableRepository extends Repository.Default implem StoreThreadLocal.setSession(replicatorSession); getLockManager().updateLockArea(area); - // TODO (CD) getSessionManager().sendLockNotification(sender, lockChangeInfo); + getSessionManager().sendLockNotification(null, CDOLockUtil.createLockChangeInfo()); return true; } finally @@ -340,6 +341,7 @@ public abstract class SynchronizableRepository extends Repository.Default implem accessor.rawImport(in, fromBranchID, toBranchID, fromCommitTime, toCommitTime, monitor); replicateRawReviseRevisions(); + replicateRawReloadLocks(); replicateRawNotifyClients(lastReplicatedCommitTime, toCommitTime); setLastReplicatedBranchID(toBranchID); @@ -380,6 +382,11 @@ public abstract class SynchronizableRepository extends Repository.Default implem } } + private void replicateRawReloadLocks() + { + getLockManager().reloadLocks(); + } + private void replicateRawNotifyClients(long fromCommitTime, long toCommitTime) { InternalCDOCommitInfoManager manager = getCommitInfoManager(); @@ -408,6 +415,9 @@ public abstract class SynchronizableRepository extends Repository.Default implem comment, data); sessionManager.sendCommitNotification(replicatorSession, commitInfo); } + + CDOLockChangeInfo lockChangeInfo = CDOLockUtil.createLockChangeInfo(); + sessionManager.sendLockNotification(replicatorSession, lockChangeInfo); } private Map replicateRawGetBranches(long fromCommitTime, long toCommitTime) diff --git a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalLockManager.java b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalLockManager.java index ab8d9a2c37..19d95044ca 100644 --- a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalLockManager.java +++ b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalLockManager.java @@ -136,4 +136,9 @@ public interface InternalLockManager extends IRWOLockManager, IDu * @since 4.1 */ public void setLockState(Object key, LockState lockState); + + /** + * @since 4.1 + */ + public void reloadLocks(); } diff --git a/plugins/org.eclipse.emf.cdo.tests.db/src/org/eclipse/emf/cdo/tests/db/AllTestsDBH2Offline.java b/plugins/org.eclipse.emf.cdo.tests.db/src/org/eclipse/emf/cdo/tests/db/AllTestsDBH2Offline.java index cb782e7730..c843dc08fd 100644 --- a/plugins/org.eclipse.emf.cdo.tests.db/src/org/eclipse/emf/cdo/tests/db/AllTestsDBH2Offline.java +++ b/plugins/org.eclipse.emf.cdo.tests.db/src/org/eclipse/emf/cdo/tests/db/AllTestsDBH2Offline.java @@ -21,6 +21,8 @@ import org.eclipse.emf.cdo.tests.offline.Bugzilla_329014_Test; import org.eclipse.emf.cdo.tests.offline.Bugzilla_351078_Test; import org.eclipse.emf.cdo.tests.offline.FailoverTest; import org.eclipse.emf.cdo.tests.offline.OfflineDelayedTest; +import org.eclipse.emf.cdo.tests.offline.OfflineLockRawReplicationTest; +import org.eclipse.emf.cdo.tests.offline.OfflineLockReplicationTest; import org.eclipse.emf.cdo.tests.offline.OfflineLockingTest; import org.eclipse.emf.cdo.tests.offline.OfflineRawTest; import org.eclipse.emf.cdo.tests.offline.OfflineTest; @@ -55,6 +57,8 @@ public class AllTestsDBH2Offline extends DBConfigs testClasses.add(OfflineRawTest.class); testClasses.add(OfflineDelayedTest.class); testClasses.add(OfflineLockingTest.class); + testClasses.add(OfflineLockReplicationTest.class); + testClasses.add(OfflineLockRawReplicationTest.class); testClasses.add(Bugzilla_329014_Test.class); testClasses.add(Bugzilla_328352_Test.class); diff --git a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/AbstractSyncingTest.java b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/AbstractSyncingTest.java index c9c94bf936..dd9c591346 100644 --- a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/AbstractSyncingTest.java +++ b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/AbstractSyncingTest.java @@ -245,4 +245,12 @@ public abstract class AbstractSyncingTest extends AbstractCDOTest ConcurrencyUtil.sleep(SLEEP_MILLIS); } } + + protected static CDOTransaction openTransaction(CDOSession session) + { + CDOTransaction tx = session.openTransaction(); + tx.options().setLockNotificationEnabled(true); + tx.enableDurableLocking(true); + return tx; + } } diff --git a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/AllTestsMEMOffline.java b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/AllTestsMEMOffline.java index c67d939679..4cf86a3376 100644 --- a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/AllTestsMEMOffline.java +++ b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/AllTestsMEMOffline.java @@ -14,6 +14,7 @@ import org.eclipse.emf.cdo.tests.config.IScenario; import org.eclipse.emf.cdo.tests.config.impl.ConfigTest; import org.eclipse.emf.cdo.tests.offline.FailoverTest; import org.eclipse.emf.cdo.tests.offline.OfflineDelayed2Test; +import org.eclipse.emf.cdo.tests.offline.OfflineLockReplicationTest; import org.eclipse.emf.cdo.tests.offline.OfflineLockingTest; import org.eclipse.emf.cdo.tests.offline.OfflineTest; @@ -41,12 +42,14 @@ public class AllTestsMEMOffline extends AllConfigs @Override protected void initTestClasses(List> testClasses, IScenario scenario) { - // MEM does not support raw replication - // testClasses.add(OfflineRawTest.class); - testClasses.add(OfflineLockingTest.class); + testClasses.add(OfflineLockReplicationTest.class); testClasses.add(OfflineTest.class); testClasses.add(OfflineDelayed2Test.class); testClasses.add(FailoverTest.class); + + // MEM does not support raw replication + // testClasses.add(OfflineRawTest.class); + // testClasses.add(OfflineLockRawReplicationTest.class); } } diff --git a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/offline/OfflineDelayedTest.java b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/offline/OfflineDelayedTest.java index a2055ca6e6..b8e6669f5a 100644 --- a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/offline/OfflineDelayedTest.java +++ b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/offline/OfflineDelayedTest.java @@ -117,10 +117,6 @@ public class OfflineDelayedTest extends AbstractSyncingTest waitForOnline(clone); } - // public void testXXX() throws Exception - // { - // } - public void _testSyncWhileCommittingToMaster_NewPackage() throws Exception { TestListener listener = new TestListener(); diff --git a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/offline/OfflineLockRawReplicationTest.java b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/offline/OfflineLockRawReplicationTest.java new file mode 100644 index 0000000000..229fcf4b53 --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/offline/OfflineLockRawReplicationTest.java @@ -0,0 +1,23 @@ +/** + * Copyright (c) 2004 - 2011 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; + +/** + * @author Caspar De Groot + */ +public class OfflineLockRawReplicationTest extends OfflineLockReplicationTest +{ + @Override + protected boolean isRawReplication() + { + return true; + } +} diff --git a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/offline/OfflineLockingTest.java b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/offline/OfflineLockingTest.java index 6c741957b1..9448830c13 100644 --- a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/offline/OfflineLockingTest.java +++ b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/offline/OfflineLockingTest.java @@ -17,21 +17,16 @@ 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.spi.server.InternalRepository; 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.util.CommitException; import org.eclipse.emf.cdo.view.CDOView; import org.eclipse.emf.cdo.view.CDOViewLocksChangedEvent; import org.eclipse.net4j.util.concurrent.IRWLockManager.LockType; -import org.eclipse.emf.common.util.EList; -import org.eclipse.emf.ecore.EObject; - /** * @author Caspar De Groot */ @@ -194,110 +189,4 @@ public class OfflineLockingTest extends AbstractSyncingTest clone1Session.close(); clone2Session.close(); } - - public void testCloneLocks_replicationToOtherClone() throws CommitException - { - InternalRepository repo1 = getRepository("repo1"); - assertEquals(true, repo1 instanceof OfflineClone); - InternalRepository repo2 = getRepository("repo2"); - assertEquals(true, repo2 instanceof OfflineClone); - - OfflineClone clone2 = (OfflineClone)repo2; - - waitForOnline(getRepository("repo1")); - waitForOnline(getRepository("repo2")); - - CDOSession clone1session = openSession("repo1"); - - // Store 3 objects in repo1 - CDOTransaction tx1_sess1 = openTransaction(clone1session); - CDOResource resource_tx1_sess1 = tx1_sess1.createResource(getResourcePath("test")); - Company companyA = getModel1Factory().createCompany(); - Company companyB = getModel1Factory().createCompany(); - Company companyC = getModel1Factory().createCompany(); - resource_tx1_sess1.getContents().add(companyA); - resource_tx1_sess1.getContents().add(companyB); - resource_tx1_sess1.getContents().add(companyC); - tx1_sess1.commit(); - - { - // Verify that they're visible in repo2 - CDOSession clone2session = openSession("repo2"); - CDOTransaction tx1_sess2 = openTransaction(clone2session); - CDOResource resource_tx1_sess2 = tx1_sess2.getResource(getResourcePath("test")); - assertEquals(3, resource_tx1_sess2.getContents().size()); - tx1_sess2.close(); - clone2session.close(); - } - - clone2.goOffline(); - waitForOffline(clone2); - - // Lock the objects in repo1. Since repo1 is ONLINE, this will also lock them - // in the master. - CDOUtil.getCDOObject(companyA).cdoReadLock().lock(); - CDOUtil.getCDOObject(companyB).cdoWriteLock().lock(); - CDOUtil.getCDOObject(companyC).cdoWriteOption().lock(); - - clone2.goOnline(); - waitForOnline(clone2); - - { - // Verify that the locks are visible in repo2 - CDOSession clone2session = openSession("repo2"); - CDOTransaction tx1_sess2 = openTransaction(clone2session); - CDOResource resource_tx1_sess2 = tx1_sess2.getResource(getResourcePath("test")); - EList contents = resource_tx1_sess2.getContents(); - CDOObject companyA_in_sess2 = CDOUtil.getCDOObject(contents.get(0)); - CDOObject companyB_in_sess2 = CDOUtil.getCDOObject(contents.get(1)); - CDOObject companyC_in_sess2 = CDOUtil.getCDOObject(contents.get(2)); - - assertEquals(true, companyA_in_sess2.cdoReadLock().isLockedByOthers()); - assertEquals(true, companyB_in_sess2.cdoWriteLock().isLockedByOthers()); - assertEquals(true, companyC_in_sess2.cdoWriteOption().isLockedByOthers()); - - tx1_sess2.close(); - clone2session.close(); - } - - clone2.goOffline(); - waitForOffline(clone2); - - // Unlock the objects in repo1. Since repo1 is ONLINE, this will also lock them - // in the master. - CDOUtil.getCDOObject(companyA).cdoReadLock().unlock(); - CDOUtil.getCDOObject(companyB).cdoWriteLock().unlock(); - CDOUtil.getCDOObject(companyC).cdoWriteOption().unlock(); - - clone2.goOnline(); - waitForOnline(clone2); - - { - // Verify in repo2 - CDOSession clone2session = openSession("repo2"); - CDOTransaction tx1_sess2 = openTransaction(clone2session); - CDOResource resource_tx1_sess2 = tx1_sess2.getResource(getResourcePath("test")); - EList contents = resource_tx1_sess2.getContents(); - CDOObject companyA_in_sess2 = CDOUtil.getCDOObject(contents.get(0)); - CDOObject companyB_in_sess2 = CDOUtil.getCDOObject(contents.get(1)); - CDOObject companyC_in_sess2 = CDOUtil.getCDOObject(contents.get(2)); - - assertEquals(false, companyA_in_sess2.cdoReadLock().isLockedByOthers()); - assertEquals(false, companyB_in_sess2.cdoWriteLock().isLockedByOthers()); - assertEquals(false, companyC_in_sess2.cdoWriteOption().isLockedByOthers()); - - tx1_sess2.close(); - clone2session.close(); - } - - clone1session.close(); - } - - private static CDOTransaction openTransaction(CDOSession session) - { - CDOTransaction tx = session.openTransaction(); - tx.options().setLockNotificationEnabled(true); - tx.enableDurableLocking(true); - return tx; - } } diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/CDOObjectImpl.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/CDOObjectImpl.java index ffe5f921ce..ff175845aa 100644 --- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/CDOObjectImpl.java +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/CDOObjectImpl.java @@ -86,8 +86,6 @@ public class CDOObjectImpl extends EStoreEObjectImpl implements InternalCDOObjec private InternalCDORevision revision; - private CDOLockState lockState; - /** * CDO uses this list instead of eSettings for transient objects. EMF uses eSettings as cache. CDO deactivates the * cache but EMF still used eSettings to store list wrappers. CDO needs another place to store the real list with the @@ -227,23 +225,12 @@ public class CDOObjectImpl extends EStoreEObjectImpl implements InternalCDOObjec */ public synchronized CDOLockState cdoLockState() { - if (lockState == null) + if (!FSMUtil.isTransient(this) && !FSMUtil.isNew(this)) { - if (!FSMUtil.isTransient(this) && !FSMUtil.isNew(this)) - { - lockState = view.getLockStates(Collections.singletonList(id))[0]; - } + return view.getLockStates(Collections.singletonList(id))[0]; } - return lockState; - } - - /** - * @since 4.1 - */ - public synchronized void cdoInternalSetLockState(CDOLockState lockState) - { - this.lockState = lockState; + return null; } public void cdoInternalSetID(CDOID id) diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/object/CDOLegacyWrapper.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/object/CDOLegacyWrapper.java index e0be18394d..49b1bd5440 100644 --- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/object/CDOLegacyWrapper.java +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/object/CDOLegacyWrapper.java @@ -97,8 +97,6 @@ public abstract class CDOLegacyWrapper extends CDOObjectWrapper protected InternalCDORevision revision; - protected CDOLockState lockState; - /** * It could happen that while revisionToInstance() is executed externally the internalPostLoad() method * will be called. This happens for example if internalPostInvalidate() is called. The leads to another @@ -127,20 +125,12 @@ public abstract class CDOLegacyWrapper extends CDOObjectWrapper public synchronized CDOLockState cdoLockState() { - if (lockState == null) + if (!FSMUtil.isTransient(this) && !FSMUtil.isNew(this)) { - if (!FSMUtil.isTransient(this) && !FSMUtil.isNew(this)) - { - lockState = view.getLockStates(Collections.singletonList(id))[0]; - } + return view.getLockStates(Collections.singletonList(id))[0]; } - return lockState; - } - - public synchronized void cdoInternalSetLockState(CDOLockState lockState) - { - this.lockState = lockState; + return null; } @Override diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/util/DefaultLocksChangedEvent.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/util/DefaultLocksChangedEvent.java index 3a3577d454..1376fcb4f8 100644 --- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/util/DefaultLocksChangedEvent.java +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/util/DefaultLocksChangedEvent.java @@ -74,4 +74,9 @@ public class DefaultLocksChangedEvent extends Event implements CDOLockChangeInfo { return lockChangeInfo.getLockType(); } + + public boolean isInvalidateAll() + { + return lockChangeInfo.isInvalidateAll(); + } } diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/view/CDOViewImpl.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/view/CDOViewImpl.java index a82b4134bb..d5251f84f6 100644 --- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/view/CDOViewImpl.java +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/view/CDOViewImpl.java @@ -103,6 +103,7 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; +import java.util.WeakHashMap; /** * @author Eike Stepper @@ -129,6 +130,8 @@ public class CDOViewImpl extends AbstractCDOView private QueueRunner invalidationRunner; + private Map lockStates = new WeakHashMap(); + @ExcludeFromDump private InvalidationRunnerLock invalidationRunnerLock = new InvalidationRunnerLock(); @@ -339,7 +342,7 @@ public class CDOViewImpl extends AbstractCDOView InternalCDOObject obj = getObject(id, false); if (obj != null) { - obj.cdoInternalSetLockState(lockState); + lockStates.put(obj, lockState); } } } @@ -368,6 +371,13 @@ public class CDOViewImpl extends AbstractCDOView return; } + if (lockChangeInfo.isInvalidateAll()) + { + lockStates.clear(); + fireLocksChangedEvent(sender, lockChangeInfo); + return; + } + // If lockChangeInfo pertains to a different view, do nothing. if (!lockChangeInfo.getBranch().equals(getBranch())) { @@ -552,9 +562,37 @@ public class CDOViewImpl extends AbstractCDOView public CDOLockState[] getLockStates(Collection ids) { - CDOSessionProtocol sessionProtocol = session.getSessionProtocol(); - CDOLockState[] lockStates = sessionProtocol.getLockStates(viewID, ids); - return lockStates; + List missing = new LinkedList(); + List lockStates = new LinkedList(); + for (CDOID id : ids) + { + CDOLockState lockState = null; + InternalCDOObject obj = getObject(id, false); + if (obj != null) + { + lockState = this.lockStates.get(obj); + } + if (lockState != null) + { + lockStates.add(lockState); + } + else + { + missing.add(id); + } + } + + if (missing.size() > 0) + { + CDOSessionProtocol sessionProtocol = session.getSessionProtocol(); + CDOLockState[] loadedLockStates = sessionProtocol.getLockStates(viewID, missing); + for (CDOLockState loadedLockState : loadedLockStates) + { + lockStates.add(loadedLockState); + } + } + + return lockStates.toArray(new CDOLockState[lockStates.size()]); } private CDOBranchPoint getBranchPointForID(CDOID id) diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/spi/cdo/InternalCDOObject.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/spi/cdo/InternalCDOObject.java index 4329baf19c..d30792ae40 100644 --- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/spi/cdo/InternalCDOObject.java +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/spi/cdo/InternalCDOObject.java @@ -14,7 +14,6 @@ package org.eclipse.emf.spi.cdo; import org.eclipse.emf.cdo.CDOObject; import org.eclipse.emf.cdo.CDOState; import org.eclipse.emf.cdo.common.id.CDOID; -import org.eclipse.emf.cdo.common.lock.CDOLockState; import org.eclipse.emf.cdo.common.model.CDOPackageTypeRegistry.CDOObjectMarker; import org.eclipse.emf.cdo.common.revision.CDORevision; import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision; @@ -56,11 +55,6 @@ public interface InternalCDOObject extends CDOObject, InternalEObject, InternalC public CDOState cdoInternalSetState(CDOState state); - /** - * @since 4.1 - */ - public void cdoInternalSetLockState(CDOLockState lockState); - public InternalEObject cdoInternalInstance(); public EStructuralFeature cdoInternalDynamicFeature(int dynamicFeatureID); diff --git a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/DBUtil.java b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/DBUtil.java index acebe265bf..bc77812f14 100644 --- a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/DBUtil.java +++ b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/DBUtil.java @@ -601,6 +601,15 @@ public final class DBUtil return result; } + /** + * @since 4.1 + */ + public static int clearTable(Connection connection, String tableName) + { + String sql = "DELETE FROM " + tableName; + return update(connection, sql); + } + public static int select(Connection connection, IDBRowHandler rowHandler, String where, IDBField... fields) throws DBException { -- cgit v1.2.3