| /* |
| * Copyright (c) 2009-2016, 2018-2020 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 |
| * Simon McDuff - bug 226778 |
| * Simon McDuff - bug 230832 |
| * Simon McDuff - bug 233490 |
| * Simon McDuff - bug 213402 |
| * Victor Roldan Betancort - maintenance |
| * Christian W. Damus (CEA LIST) - bug 418454 |
| */ |
| package org.eclipse.emf.internal.cdo.session; |
| |
| import org.eclipse.emf.cdo.common.CDOCommonRepository; |
| import org.eclipse.emf.cdo.common.branch.CDOBranch; |
| import org.eclipse.emf.cdo.common.branch.CDOBranchPoint; |
| import org.eclipse.emf.cdo.common.branch.CDOBranchVersion; |
| import org.eclipse.emf.cdo.common.commit.CDOChangeKind; |
| import org.eclipse.emf.cdo.common.commit.CDOChangeSet; |
| import org.eclipse.emf.cdo.common.commit.CDOChangeSetData; |
| import org.eclipse.emf.cdo.common.commit.CDOCommitInfo; |
| import org.eclipse.emf.cdo.common.commit.CDOCommitInfoManager; |
| import org.eclipse.emf.cdo.common.id.CDOID; |
| import org.eclipse.emf.cdo.common.id.CDOIDGenerator; |
| import org.eclipse.emf.cdo.common.id.CDOIDUtil; |
| import org.eclipse.emf.cdo.common.lob.CDOLobInfo; |
| import org.eclipse.emf.cdo.common.lob.CDOLobStore; |
| import org.eclipse.emf.cdo.common.lock.CDOLockChangeInfo; |
| import org.eclipse.emf.cdo.common.model.CDOPackageUnit; |
| import org.eclipse.emf.cdo.common.protocol.CDOProtocol.CommitNotificationInfo; |
| import org.eclipse.emf.cdo.common.revision.CDOElementProxy; |
| import org.eclipse.emf.cdo.common.revision.CDOIDAndVersion; |
| import org.eclipse.emf.cdo.common.revision.CDOList; |
| import org.eclipse.emf.cdo.common.revision.CDORevisable; |
| import org.eclipse.emf.cdo.common.revision.CDORevision; |
| import org.eclipse.emf.cdo.common.revision.CDORevisionKey; |
| import org.eclipse.emf.cdo.common.revision.CDORevisionUtil; |
| import org.eclipse.emf.cdo.common.revision.delta.CDOAddFeatureDelta; |
| import org.eclipse.emf.cdo.common.revision.delta.CDOClearFeatureDelta; |
| import org.eclipse.emf.cdo.common.revision.delta.CDOFeatureDelta; |
| import org.eclipse.emf.cdo.common.revision.delta.CDOFeatureDeltaVisitor; |
| import org.eclipse.emf.cdo.common.revision.delta.CDOListFeatureDelta; |
| import org.eclipse.emf.cdo.common.revision.delta.CDOMoveFeatureDelta; |
| import org.eclipse.emf.cdo.common.revision.delta.CDORemoveFeatureDelta; |
| import org.eclipse.emf.cdo.common.revision.delta.CDORevisionDelta; |
| import org.eclipse.emf.cdo.common.revision.delta.CDOSetFeatureDelta; |
| import org.eclipse.emf.cdo.common.security.CDOPermission; |
| import org.eclipse.emf.cdo.common.util.CDOCommonUtil; |
| import org.eclipse.emf.cdo.common.util.CDOPackageNotFoundException; |
| import org.eclipse.emf.cdo.common.util.RepositoryStateChangedEvent; |
| import org.eclipse.emf.cdo.common.util.RepositoryTypeChangedEvent; |
| import org.eclipse.emf.cdo.eresource.EresourcePackage; |
| import org.eclipse.emf.cdo.etypes.EtypesPackage; |
| import org.eclipse.emf.cdo.internal.common.revision.delta.CDOMoveFeatureDeltaImpl; |
| import org.eclipse.emf.cdo.internal.common.revision.delta.CDOSetFeatureDeltaImpl; |
| import org.eclipse.emf.cdo.internal.common.revision.delta.CDOSingleValueFeatureDeltaImpl; |
| import org.eclipse.emf.cdo.session.CDOCollectionLoadingPolicy; |
| import org.eclipse.emf.cdo.session.CDORepositoryInfo; |
| 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.session.remote.CDORemoteSessionManager; |
| import org.eclipse.emf.cdo.spi.common.CDOLobStoreImpl; |
| import org.eclipse.emf.cdo.spi.common.branch.CDOBranchUtil; |
| import org.eclipse.emf.cdo.spi.common.branch.InternalCDOBranch; |
| import org.eclipse.emf.cdo.spi.common.branch.InternalCDOBranchManager; |
| import org.eclipse.emf.cdo.spi.common.commit.CDORevisionAvailabilityInfo; |
| import org.eclipse.emf.cdo.spi.common.commit.InternalCDOCommitInfoManager; |
| import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageRegistry; |
| import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageUnit; |
| import org.eclipse.emf.cdo.spi.common.revision.CDOFeatureDeltaVisitorImpl; |
| import org.eclipse.emf.cdo.spi.common.revision.DetachedCDORevision; |
| import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision; |
| import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevisionCache; |
| import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevisionDelta; |
| import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevisionManager; |
| import org.eclipse.emf.cdo.spi.common.revision.PointerCDORevision; |
| import org.eclipse.emf.cdo.spi.common.revision.SyntheticCDORevision; |
| import org.eclipse.emf.cdo.transaction.CDOTransaction; |
| import org.eclipse.emf.cdo.util.CDOUtil; |
| import org.eclipse.emf.cdo.view.CDOFetchRuleManager; |
| import org.eclipse.emf.cdo.view.CDOView; |
| |
| import org.eclipse.emf.internal.cdo.analyzer.NOOPFetchRuleManager; |
| import org.eclipse.emf.internal.cdo.bundle.OM; |
| import org.eclipse.emf.internal.cdo.messages.Messages; |
| import org.eclipse.emf.internal.cdo.object.CDOFactoryImpl; |
| import org.eclipse.emf.internal.cdo.session.remote.CDORemoteSessionManagerImpl; |
| import org.eclipse.emf.internal.cdo.util.DefaultLocksChangedEvent; |
| |
| import org.eclipse.net4j.util.AdapterUtil; |
| import org.eclipse.net4j.util.ReflectUtil.ExcludeFromDump; |
| import org.eclipse.net4j.util.WrappedException; |
| import org.eclipse.net4j.util.concurrent.ConcurrencyUtil; |
| import org.eclipse.net4j.util.concurrent.IExecutorServiceProvider; |
| import org.eclipse.net4j.util.concurrent.IRWLockManager; |
| import org.eclipse.net4j.util.concurrent.IRWLockManager.LockType; |
| import org.eclipse.net4j.util.concurrent.IRWOLockManager; |
| import org.eclipse.net4j.util.concurrent.RWOLockManager; |
| import org.eclipse.net4j.util.concurrent.RunnableWithName; |
| import org.eclipse.net4j.util.event.Event; |
| import org.eclipse.net4j.util.event.EventUtil; |
| import org.eclipse.net4j.util.event.IEvent; |
| import org.eclipse.net4j.util.event.IListener; |
| import org.eclipse.net4j.util.event.Notifier; |
| import org.eclipse.net4j.util.io.IOUtil; |
| import org.eclipse.net4j.util.lifecycle.ILifecycle; |
| import org.eclipse.net4j.util.lifecycle.LifecycleEventAdapter; |
| import org.eclipse.net4j.util.lifecycle.LifecycleUtil; |
| import org.eclipse.net4j.util.om.OMPlatform; |
| import org.eclipse.net4j.util.om.log.OMLogger; |
| import org.eclipse.net4j.util.om.trace.ContextTracer; |
| import org.eclipse.net4j.util.options.OptionsEvent; |
| import org.eclipse.net4j.util.registry.HashMapRegistry; |
| import org.eclipse.net4j.util.registry.IRegistry; |
| import org.eclipse.net4j.util.security.IPasswordCredentialsProvider; |
| |
| import org.eclipse.emf.common.util.ECollections; |
| import org.eclipse.emf.ecore.EPackage; |
| import org.eclipse.emf.ecore.EReference; |
| import org.eclipse.emf.ecore.EStructuralFeature; |
| import org.eclipse.emf.ecore.EcorePackage; |
| import org.eclipse.emf.spi.cdo.CDOPermissionUpdater; |
| import org.eclipse.emf.spi.cdo.CDOSessionProtocol; |
| import org.eclipse.emf.spi.cdo.CDOSessionProtocol.MergeDataResult; |
| import org.eclipse.emf.spi.cdo.CDOSessionProtocol.RefreshSessionResult; |
| import org.eclipse.emf.spi.cdo.InternalCDORemoteSessionManager; |
| import org.eclipse.emf.spi.cdo.InternalCDOSession; |
| import org.eclipse.emf.spi.cdo.InternalCDOSessionInvalidationEvent; |
| import org.eclipse.emf.spi.cdo.InternalCDOTransaction; |
| import org.eclipse.emf.spi.cdo.InternalCDOView; |
| import org.eclipse.emf.spi.cdo.InternalCDOView.ViewInvalidationData; |
| |
| import java.io.File; |
| import java.io.FileNotFoundException; |
| import java.io.FileOutputStream; |
| import java.io.FileWriter; |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.io.Reader; |
| import java.text.MessageFormat; |
| import java.util.ArrayList; |
| import java.util.Collections; |
| import java.util.HashMap; |
| import java.util.HashSet; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Map.Entry; |
| import java.util.Queue; |
| import java.util.Set; |
| import java.util.concurrent.ConcurrentLinkedQueue; |
| import java.util.concurrent.ExecutorService; |
| |
| /** |
| * @author Eike Stepper |
| */ |
| public abstract class CDOSessionImpl extends CDOTransactionContainerImpl implements InternalCDOSession, IExecutorServiceProvider |
| { |
| private static final ContextTracer TRACER = new ContextTracer(OM.DEBUG_SESSION, CDOSessionImpl.class); |
| |
| private static final boolean DEBUG_INVALIDATION = OMPlatform.INSTANCE.isProperty("org.eclipse.emf.internal.cdo.session.CDOSessionImpl.DEBUG_INVALIDATION"); |
| |
| private ExceptionHandler exceptionHandler; |
| |
| private CDOIDGenerator idGenerator; |
| |
| private InternalCDOPackageRegistry packageRegistry; |
| |
| private InternalCDOBranchManager branchManager; |
| |
| private InternalCDORevisionManager revisionManager; |
| |
| private InternalCDOCommitInfoManager commitInfoManager; |
| |
| private CDOSessionProtocol sessionProtocol; |
| |
| @ExcludeFromDump |
| private IListener sessionProtocolListener = new LifecycleEventAdapter() |
| { |
| @Override |
| protected void onDeactivated(ILifecycle lifecycle) |
| { |
| sessionProtocolDeactivated(); |
| } |
| }; |
| |
| private int sessionID; |
| |
| private String userID; |
| |
| private long lastUpdateTime; |
| |
| @ExcludeFromDump |
| private LastUpdateTimeLock lastUpdateTimeLock = new LastUpdateTimeLock(); |
| |
| private CDOSession.Options options = createOptions(); |
| |
| private final IRegistry<String, Object> properties = new HashMapRegistry<String, Object>() |
| { |
| @Override |
| public void setAutoCommit(boolean autoCommit) |
| { |
| throw new UnsupportedOperationException(); |
| } |
| }; |
| |
| private final SessionInvalidator invalidator = new SessionInvalidator(); |
| |
| private CDORepositoryInfo repositoryInfo; |
| |
| private CDOFetchRuleManager fetchRuleManager; |
| |
| private IRWOLockManager<CDOSessionImpl, Object> lockManager = new RWOLockManager<>(); |
| |
| @ExcludeFromDump |
| private Set<CDOSessionImpl> singletonCollection = Collections.singleton(this); |
| |
| private boolean mainBranchLocal; |
| |
| private IPasswordCredentialsProvider credentialsProvider; |
| |
| private InternalCDORemoteSessionManager remoteSessionManager; |
| |
| /** |
| * A map to track for every object that was committed since this session's last refresh, onto what CDOBranchPoint it |
| * was committed. (Used only for sticky transactions, see bug 290032 - Sticky views.) |
| */ |
| private Map<CDOID, CDOBranchPoint> committedSinceLastRefresh = CDOIDUtil.createMap(); |
| |
| static |
| { |
| // Ensure that these 3 packages are registered with the global package registry in stand-alone |
| EcorePackage.eINSTANCE.getClass(); |
| EtypesPackage.eINSTANCE.getClass(); |
| EresourcePackage.eINSTANCE.getClass(); |
| } |
| |
| public CDOSessionImpl() |
| { |
| } |
| |
| @Override |
| public CDORepositoryInfo getRepositoryInfo() |
| { |
| return repositoryInfo; |
| } |
| |
| @Override |
| public void setRepositoryInfo(CDORepositoryInfo repositoryInfo) |
| { |
| this.repositoryInfo = repositoryInfo; |
| } |
| |
| @Override |
| public int getSessionID() |
| { |
| return sessionID; |
| } |
| |
| @Override |
| public void setSessionID(int sessionID) |
| { |
| this.sessionID = sessionID; |
| } |
| |
| @Override |
| public String getUserID() |
| { |
| return userID; |
| } |
| |
| @Override |
| public void setUserID(String userID) |
| { |
| this.userID = userID; |
| } |
| |
| @Override |
| public ExceptionHandler getExceptionHandler() |
| { |
| return exceptionHandler; |
| } |
| |
| @Override |
| public void setExceptionHandler(ExceptionHandler exceptionHandler) |
| { |
| checkInactive(); |
| this.exceptionHandler = exceptionHandler; |
| } |
| |
| @Override |
| public CDOIDGenerator getIDGenerator() |
| { |
| return idGenerator; |
| } |
| |
| @Override |
| public void setIDGenerator(CDOIDGenerator idGenerator) |
| { |
| checkInactive(); |
| this.idGenerator = idGenerator; |
| } |
| |
| @Override |
| public InternalCDOPackageRegistry getPackageRegistry() |
| { |
| return packageRegistry; |
| } |
| |
| @Override |
| public void setPackageRegistry(InternalCDOPackageRegistry packageRegistry) |
| { |
| this.packageRegistry = packageRegistry; |
| } |
| |
| @Override |
| public InternalCDOBranchManager getBranchManager() |
| { |
| return branchManager; |
| } |
| |
| @Override |
| public void setBranchManager(InternalCDOBranchManager branchManager) |
| { |
| checkInactive(); |
| this.branchManager = branchManager; |
| } |
| |
| @Override |
| public InternalCDORevisionManager getRevisionManager() |
| { |
| return revisionManager; |
| } |
| |
| @Override |
| public void setRevisionManager(InternalCDORevisionManager revisionManager) |
| { |
| checkInactive(); |
| this.revisionManager = revisionManager; |
| } |
| |
| @Override |
| public InternalCDOCommitInfoManager getCommitInfoManager() |
| { |
| return commitInfoManager; |
| } |
| |
| @Override |
| public void setCommitInfoManager(InternalCDOCommitInfoManager commitInfoManager) |
| { |
| checkInactive(); |
| this.commitInfoManager = commitInfoManager; |
| } |
| |
| @Override |
| public CDOSessionProtocol getSessionProtocol() |
| { |
| return sessionProtocol; |
| } |
| |
| @Override |
| public void setSessionProtocol(CDOSessionProtocol sessionProtocol) |
| { |
| if (exceptionHandler == null) |
| { |
| this.sessionProtocol = sessionProtocol; |
| } |
| else |
| { |
| if (this.sessionProtocol instanceof DelegatingSessionProtocol) |
| { |
| ((DelegatingSessionProtocol)this.sessionProtocol).setDelegate(sessionProtocol); |
| } |
| else |
| { |
| this.sessionProtocol = new DelegatingSessionProtocol(sessionProtocol, exceptionHandler); |
| } |
| } |
| } |
| |
| /** |
| * @since 3.0 |
| */ |
| @Override |
| public CDOFetchRuleManager getFetchRuleManager() |
| { |
| return fetchRuleManager; |
| } |
| |
| @Override |
| public ExecutorService getExecutorService() |
| { |
| return ConcurrencyUtil.getExecutorService(sessionProtocol); |
| } |
| |
| /** |
| * @since 3.0 |
| */ |
| @Override |
| public void setFetchRuleManager(CDOFetchRuleManager fetchRuleManager) |
| { |
| if (fetchRuleManager == null) |
| { |
| fetchRuleManager = new NOOPFetchRuleManager() |
| { |
| @Override |
| public CDOCollectionLoadingPolicy getCollectionLoadingPolicy() |
| { |
| return options().getCollectionLoadingPolicy(); |
| } |
| }; |
| } |
| |
| this.fetchRuleManager = fetchRuleManager; |
| } |
| |
| @Override |
| @Deprecated |
| public org.eclipse.emf.cdo.common.protocol.CDOAuthenticator getAuthenticator() |
| { |
| throw new UnsupportedOperationException(); |
| } |
| |
| @Override |
| @Deprecated |
| public void setAuthenticator(org.eclipse.emf.cdo.common.protocol.CDOAuthenticator authenticator) |
| { |
| throw new UnsupportedOperationException(); |
| } |
| |
| @Override |
| public IPasswordCredentialsProvider getCredentialsProvider() |
| { |
| return credentialsProvider; |
| } |
| |
| @Override |
| public void setCredentialsProvider(IPasswordCredentialsProvider credentialsProvider) |
| { |
| this.credentialsProvider = credentialsProvider; |
| } |
| |
| public boolean isMainBranchLocal() |
| { |
| return mainBranchLocal; |
| } |
| |
| @Override |
| public void setMainBranchLocal(boolean mainBranchLocal) |
| { |
| this.mainBranchLocal = mainBranchLocal; |
| } |
| |
| @Override |
| public InternalCDORemoteSessionManager getRemoteSessionManager() |
| { |
| return remoteSessionManager; |
| } |
| |
| @Override |
| public void setRemoteSessionManager(InternalCDORemoteSessionManager remoteSessionManager) |
| { |
| this.remoteSessionManager = remoteSessionManager; |
| } |
| |
| @Override |
| public CDOLobStore getLobStore() |
| { |
| final CDOLobStore cache = options().getLobCache(); |
| return new CDOLobStore.Delegating() |
| { |
| @Override |
| public InputStream getBinary(final CDOLobInfo info) throws IOException |
| { |
| for (;;) |
| { |
| try |
| { |
| return super.getBinary(info); |
| } |
| catch (FileNotFoundException couldNotBeRead) |
| { |
| try |
| { |
| loadBinary(info); |
| } |
| catch (FileNotFoundException couldNotBeCreated) |
| { |
| // Try to read again |
| } |
| } |
| } |
| } |
| |
| @Override |
| public Reader getCharacter(CDOLobInfo info) throws IOException |
| { |
| for (;;) |
| { |
| try |
| { |
| return super.getCharacter(info); |
| } |
| catch (FileNotFoundException couldNotBeRead) |
| { |
| try |
| { |
| loadCharacter(info); |
| } |
| catch (FileNotFoundException couldNotBeCreated) |
| { |
| // Try to read again |
| } |
| } |
| } |
| } |
| |
| private void loadBinary(final CDOLobInfo info) throws IOException |
| { |
| File file = getDelegate().getBinaryFile(info.getID()); |
| FileOutputStream out = new FileOutputStream(file); |
| loadLobAsync(info, file, out); |
| } |
| |
| private void loadCharacter(final CDOLobInfo info) throws IOException |
| { |
| File file = getDelegate().getCharacterFile(info.getID()); |
| FileWriter out = new FileWriter(file); |
| loadLobAsync(info, file, out); |
| } |
| |
| @Override |
| protected CDOLobStore getDelegate() |
| { |
| return cache; |
| } |
| }; |
| } |
| |
| protected void loadLobAsync(final CDOLobInfo info, final File file, final Object outputStreamOrWriter) |
| { |
| ConcurrencyUtil.execute(this, new RunnableWithName() |
| { |
| @Override |
| public String getName() |
| { |
| return "CDOLobLoader-" + info.getIDString(); |
| } |
| |
| @Override |
| protected void doRun() |
| { |
| try |
| { |
| CDOSessionProtocol sessionProtocol = getSessionProtocol(); |
| sessionProtocol.loadLob(info, outputStreamOrWriter); |
| } |
| catch (Throwable t) |
| { |
| OM.LOG.error(t); |
| IOUtil.delete(file); |
| } |
| } |
| }); |
| } |
| |
| @Override |
| public void close() |
| { |
| LifecycleUtil.deactivate(this, OMLogger.Level.DEBUG); |
| } |
| |
| /** |
| * @since 2.0 |
| */ |
| @Override |
| public boolean isClosed() |
| { |
| return !isActive(); |
| } |
| |
| /** |
| * @since 2.0 |
| */ |
| @Override |
| public CDOSession.Options options() |
| { |
| return options; |
| } |
| |
| @Override |
| public IRegistry<String, Object> properties() |
| { |
| return properties; |
| } |
| |
| /** |
| * @since 2.0 |
| */ |
| protected CDOSession.Options createOptions() |
| { |
| return new OptionsImpl(); |
| } |
| |
| @Override |
| public Object processPackage(Object value) |
| { |
| CDOFactoryImpl.prepareDynamicEPackage(value); |
| return value; |
| } |
| |
| @Override |
| public EPackage[] loadPackages(CDOPackageUnit packageUnit) |
| { |
| if (packageUnit.getOriginalType().isGenerated()) |
| { |
| if (!options().isGeneratedPackageEmulationEnabled()) |
| { |
| throw new CDOPackageNotFoundException(packageUnit.getID()); |
| } |
| } |
| |
| return getSessionProtocol().loadPackages(packageUnit); |
| } |
| |
| @Override |
| public void acquireAtomicRequestLock(Object key) |
| { |
| try |
| { |
| lockManager.lock(LockType.WRITE, key, this, IRWLockManager.WAIT); |
| } |
| catch (InterruptedException ex) |
| { |
| throw WrappedException.wrap(ex); |
| } |
| } |
| |
| @Override |
| public void releaseAtomicRequestLock(Object key) |
| { |
| lockManager.unlock(LockType.WRITE, key, singletonCollection); |
| } |
| |
| @Override |
| protected void initViewSynced(InternalCDOView view) |
| { |
| view.setSession(this); |
| view.setLastUpdateTime(getLastUpdateTime()); |
| } |
| |
| @Override |
| protected CDOBranch getMainBranch() |
| { |
| return getBranchManager().getMainBranch(); |
| } |
| |
| protected Map<CDORevision, CDOPermission> updatePermissions(CDOCommitInfo commitInfo) |
| { |
| CDOPermissionUpdater permissionUpdater = options().getPermissionUpdater(); |
| if (permissionUpdater != null) |
| { |
| Set<InternalCDORevision> revisions = new HashSet<>(); |
| revisionManager.getCache().forEachCurrentRevision(r -> { |
| if (!(r instanceof SyntheticCDORevision)) |
| { |
| revisions.add((InternalCDORevision)r); |
| } |
| }); |
| |
| return permissionUpdater.updatePermissions(CDOSessionImpl.this, revisions); |
| } |
| |
| return null; |
| } |
| |
| /** |
| * @since 2.0 |
| */ |
| @Override |
| public long refresh() |
| { |
| checkActive(); |
| if (options().isPassiveUpdateEnabled()) |
| { |
| return CDOBranchPoint.UNSPECIFIED_DATE; |
| } |
| |
| return refresh(false); |
| } |
| |
| @Override |
| public long refresh(RefreshSessionResult.Provider provider) |
| { |
| Map<CDOBranch, List<InternalCDOView>> views = new HashMap<>(); |
| Map<CDOBranch, Map<CDOID, InternalCDORevision>> viewedRevisions = new HashMap<>(); |
| collectViewedRevisions(views, viewedRevisions); |
| cleanupRevisionCache(viewedRevisions); |
| |
| RefreshSessionResult result = provider.getRefreshSessionResult(views, viewedRevisions); |
| |
| setLastUpdateTime(result.getLastUpdateTime()); |
| registerPackageUnits(result.getPackageUnits()); |
| |
| for (Entry<CDOBranch, List<InternalCDOView>> entry : views.entrySet()) |
| { |
| CDOBranch branch = entry.getKey(); |
| List<InternalCDOView> branchViews = entry.getValue(); |
| processRefreshSessionResult(result, branch, branchViews, viewedRevisions); |
| } |
| |
| return result.getLastUpdateTime(); |
| } |
| |
| protected final long refresh(final boolean enablePassiveUpdates) |
| { |
| return refresh(new RefreshSessionResult.Provider() |
| { |
| @Override |
| public RefreshSessionResult getRefreshSessionResult(Map<CDOBranch, List<InternalCDOView>> views, |
| Map<CDOBranch, Map<CDOID, InternalCDORevision>> viewedRevisions) |
| { |
| CDOSessionProtocol sessionProtocol = getSessionProtocol(); |
| long lastUpdateTime = getLastUpdateTime(); |
| int initialChunkSize = options().getCollectionLoadingPolicy().getInitialChunkSize(); |
| |
| return sessionProtocol.refresh(lastUpdateTime, viewedRevisions, initialChunkSize, enablePassiveUpdates); |
| } |
| }); |
| } |
| |
| @Override |
| public void processRefreshSessionResult(RefreshSessionResult result, CDOBranch branch, List<InternalCDOView> branchViews, |
| Map<CDOBranch, Map<CDOID, InternalCDORevision>> viewedRevisions) |
| { |
| Map<CDOID, InternalCDORevision> oldRevisions = viewedRevisions.get(branch); |
| |
| InternalCDORevisionManager revisionManager = getRevisionManager(); |
| List<CDORevisionKey> changedObjects = new ArrayList<>(); |
| List<InternalCDORevision> newRevisions = result.getChangedObjects(branch); |
| |
| for (InternalCDORevision newRevision : newRevisions) |
| { |
| revisionManager.addRevision(newRevision); |
| |
| CDOID id = newRevision.getID(); |
| InternalCDORevision oldRevision = oldRevisions.get(id); |
| InternalCDORevisionDelta delta = newRevision.compare(oldRevision); |
| changedObjects.add(delta); |
| } |
| |
| List<CDOIDAndVersion> detachedObjects = result.getDetachedObjects(branch); |
| for (CDOIDAndVersion detachedObject : detachedObjects) |
| { |
| CDOID id = detachedObject.getID(); |
| revisionManager.reviseLatest(id, branch); |
| } |
| |
| long lastUpdateTime = result.getLastUpdateTime(); |
| for (InternalCDOView view : branchViews) |
| { |
| ViewInvalidationData invalidationData = new ViewInvalidationData(); |
| invalidationData.setBranch(view.getBranch()); |
| invalidationData.setLastUpdateTime(lastUpdateTime); |
| invalidationData.setAllChangedObjects(changedObjects); |
| invalidationData.setAllDetachedObjects(detachedObjects); |
| invalidationData.setOldRevisions(oldRevisions); |
| invalidationData.setClearResourcePathCache(true); |
| |
| view.invalidate(invalidationData); |
| } |
| } |
| |
| private void collectViewedRevisions(Map<CDOBranch, List<InternalCDOView>> views, Map<CDOBranch, Map<CDOID, InternalCDORevision>> viewedRevisions) |
| { |
| for (InternalCDOView view : getViews()) |
| { |
| if (view.getTimeStamp() == CDOView.UNSPECIFIED_DATE) |
| { |
| CDOBranch branch = view.getBranch(); |
| Map<CDOID, InternalCDORevision> revisions = viewedRevisions.get(branch); |
| boolean needNewMap = revisions == null; |
| if (needNewMap) |
| { |
| revisions = CDOIDUtil.createMap(); |
| } |
| |
| view.collectViewedRevisions(revisions); |
| if (!revisions.isEmpty()) |
| { |
| List<InternalCDOView> list = views.get(branch); |
| if (list == null) |
| { |
| list = new ArrayList<>(); |
| views.put(branch, list); |
| } |
| |
| list.add(view); |
| |
| if (needNewMap) |
| { |
| viewedRevisions.put(branch, revisions); |
| } |
| } |
| } |
| } |
| } |
| |
| private void cleanupRevisionCache(Map<CDOBranch, Map<CDOID, InternalCDORevision>> viewedRevisions) |
| { |
| Set<InternalCDORevision> set = new HashSet<>(); |
| for (Map<CDOID, InternalCDORevision> revisions : viewedRevisions.values()) |
| { |
| for (InternalCDORevision revision : revisions.values()) |
| { |
| set.add(revision); |
| } |
| } |
| |
| InternalCDORevisionCache cache = getRevisionManager().getCache(); |
| List<CDORevision> currentRevisions = cache.getCurrentRevisions(); |
| for (CDORevision revision : currentRevisions) |
| { |
| if (!set.contains(revision)) |
| { |
| cache.removeRevision(revision.getID(), revision); |
| } |
| } |
| } |
| |
| @Override |
| public long getLastUpdateTime() |
| { |
| synchronized (lastUpdateTimeLock) |
| { |
| return lastUpdateTime; |
| } |
| } |
| |
| @Override |
| public void setLastUpdateTime(long lastUpdateTime) |
| { |
| synchronized (lastUpdateTimeLock) |
| { |
| if (this.lastUpdateTime < lastUpdateTime) |
| { |
| this.lastUpdateTime = lastUpdateTime; |
| } |
| |
| lastUpdateTimeLock.notifyAll(); |
| } |
| } |
| |
| @Override |
| public void waitForUpdate(long updateTime) |
| { |
| waitForUpdate(updateTime, NO_TIMEOUT); |
| } |
| |
| @Override |
| public boolean waitForUpdate(long updateTime, long timeoutMillis) |
| { |
| long end = timeoutMillis == NO_TIMEOUT ? Long.MAX_VALUE : System.currentTimeMillis() + timeoutMillis; |
| InternalCDOView views[] = getViews(); |
| if (views.length > 0) |
| { |
| for (CDOView view : views) |
| { |
| long viewTimeoutMillis = timeoutMillis == NO_TIMEOUT ? NO_TIMEOUT : end - System.currentTimeMillis(); |
| boolean ok = view.waitForUpdate(updateTime, viewTimeoutMillis); |
| if (!ok) |
| { |
| return false; |
| } |
| } |
| |
| return true; |
| } |
| |
| // Session without views |
| for (;;) |
| { |
| synchronized (lastUpdateTimeLock) |
| { |
| if (lastUpdateTime >= updateTime) |
| { |
| return true; |
| } |
| |
| long now = System.currentTimeMillis(); |
| if (now >= end) |
| { |
| return false; |
| } |
| |
| try |
| { |
| lastUpdateTimeLock.wait(end - now); |
| } |
| catch (InterruptedException ex) |
| { |
| throw WrappedException.wrap(ex); |
| } |
| } |
| } |
| } |
| |
| @Override |
| public boolean runAfterUpdate(final long updateTime, final Runnable runnable) |
| { |
| synchronized (lastUpdateTimeLock) |
| { |
| if (lastUpdateTime < updateTime) |
| { |
| addListener(new IListener() |
| { |
| @Override |
| public void notifyEvent(IEvent event) |
| { |
| if (event instanceof CDOSessionInvalidationEvent) |
| { |
| CDOSessionInvalidationEvent e = (CDOSessionInvalidationEvent)event; |
| if (e.getTimeStamp() >= updateTime) |
| { |
| removeListener(this); |
| runnable.run(); |
| } |
| } |
| } |
| }); |
| |
| return false; |
| } |
| } |
| |
| runnable.run(); |
| return true; |
| } |
| |
| /** |
| * @since 3.0 |
| */ |
| @Override |
| public Object resolveElementProxy(CDORevision revision, EStructuralFeature feature, int accessIndex, int serverIndex) |
| { |
| if (!((InternalCDORevision)revision).isUnchunked()) |
| { |
| CDOCollectionLoadingPolicy policy = options().getCollectionLoadingPolicy(); |
| return policy.resolveProxy(revision, feature, accessIndex, serverIndex); |
| } |
| |
| return revision.data().get(feature, accessIndex); |
| } |
| |
| /** |
| * @since 4.0 |
| */ |
| @Override |
| public void resolveAllElementProxies(CDORevision revision) |
| { |
| InternalCDORevision internalRevision = (InternalCDORevision)revision; |
| if (!internalRevision.isUnchunked()) |
| { |
| CDOCollectionLoadingPolicy policy = options().getCollectionLoadingPolicy(); |
| |
| for (EReference reference : internalRevision.getClassInfo().getAllPersistentReferences()) |
| { |
| if (reference.isMany()) |
| { |
| CDOList list = internalRevision.getListOrNull(reference); |
| if (list != null) |
| { |
| for (Iterator<Object> it = list.iterator(); it.hasNext();) |
| { |
| Object element = it.next(); |
| if (element instanceof CDOElementProxy) |
| { |
| policy.resolveAllProxies(internalRevision, reference); |
| break; |
| } |
| } |
| } |
| } |
| } |
| |
| internalRevision.setUnchunked(); |
| } |
| } |
| |
| @Override |
| public void ensureChunks(InternalCDORevision revision, int chunkSize) |
| { |
| resolveAllElementProxies(revision); |
| } |
| |
| @Override |
| public void handleRepositoryTypeChanged(CDOCommonRepository.Type oldType, CDOCommonRepository.Type newType) |
| { |
| fireEvent(new RepositoryTypeChangedEvent(this, oldType, newType)); |
| } |
| |
| @Override |
| public void handleRepositoryStateChanged(CDOCommonRepository.State oldState, CDOCommonRepository.State newState) |
| { |
| fireEvent(new RepositoryStateChangedEvent(this, oldState, newState)); |
| } |
| |
| @Override |
| @Deprecated |
| public void handleBranchNotification(InternalCDOBranch branch) |
| { |
| throw new UnsupportedOperationException(); |
| } |
| |
| @Override |
| @Deprecated |
| public void handleCommitNotification(CDOCommitInfo commitInfo) |
| { |
| throw new UnsupportedOperationException(); |
| } |
| |
| @Override |
| @Deprecated |
| public void handleCommitNotification(CDOCommitInfo commitInfo, boolean clearResourcePathCache) |
| { |
| throw new UnsupportedOperationException(); |
| } |
| |
| @Override |
| public void handleCommitNotification(CommitNotificationInfo info) |
| { |
| try |
| { |
| CDOCommitInfo commitInfo = info.getCommitInfo(); |
| registerPackageUnits(commitInfo.getNewPackageUnits()); |
| |
| InvalidationData invalidationData = new InvalidationData(); |
| invalidationData.setCommitInfo(commitInfo); |
| invalidationData.setSender(null); |
| invalidationData.setClearResourcePathCache(info.isClearResourcePathCache()); |
| invalidationData.setSecurityImpact(info.getSecurityImpact()); |
| invalidationData.setNewPermissions(info.getNewPermissions()); |
| invalidationData.setLockChangeInfo(info.getLockChangeInfo()); |
| |
| invalidate(invalidationData); |
| } |
| catch (RuntimeException ex) |
| { |
| if (isActive()) |
| { |
| OM.LOG.error(ex); |
| } |
| else |
| { |
| OM.LOG.info(Messages.getString("CDOSessionImpl.2")); //$NON-NLS-1$ |
| } |
| } |
| } |
| |
| @Override |
| public void handleLockNotification(CDOLockChangeInfo lockChangeInfo, InternalCDOView sender) |
| { |
| for (InternalCDOView view : getViews()) |
| { |
| if (view != sender) |
| { |
| view.handleLockNotification(sender, lockChangeInfo); |
| } |
| } |
| |
| fireEvent(new SessionLocksChangedEvent(sender, lockChangeInfo)); |
| } |
| |
| private void registerPackageUnits(List<CDOPackageUnit> packageUnits) |
| { |
| InternalCDOPackageRegistry packageRegistry = getPackageRegistry(); |
| for (CDOPackageUnit newPackageUnit : packageUnits) |
| { |
| packageRegistry.putPackageUnit((InternalCDOPackageUnit)newPackageUnit); |
| } |
| } |
| |
| /** |
| * Computes/adjusts CDOMoveFeatureDelta.value, CDORemoveFeatureDelta.value and CDOSetFeatureDelta.oldValue. |
| * <p> |
| * Implicitely adjusts the underlying CDORevisionDelta. |
| */ |
| private void addOldValuesToDelta(final CDORevision oldRevision, CDORevisionDelta revisionDelta) |
| { |
| CDOFeatureDeltaVisitor visitor = new CDOFeatureDeltaVisitorImpl() |
| { |
| private List<Object> workList; |
| |
| @Override |
| public void visit(CDOAddFeatureDelta delta) |
| { |
| workList.add(delta.getIndex(), delta.getValue()); |
| } |
| |
| @Override |
| public void visit(CDOClearFeatureDelta delta) |
| { |
| workList.clear(); |
| } |
| |
| @Override |
| public void visit(CDOListFeatureDelta deltas) |
| { |
| @SuppressWarnings("unchecked") |
| List<Object> list = (List<Object>)((InternalCDORevision)oldRevision).getValue(deltas.getFeature()); |
| if (list != null) |
| { |
| workList = new ArrayList<>(list); |
| super.visit(deltas); |
| } |
| } |
| |
| @Override |
| public void visit(CDOMoveFeatureDelta delta) |
| { |
| Object value = workList.get(delta.getOldPosition()); |
| ((CDOMoveFeatureDeltaImpl)delta).setValue(value); // Adjust delta |
| ECollections.move(workList, delta.getNewPosition(), delta.getOldPosition()); |
| } |
| |
| @Override |
| public void visit(CDORemoveFeatureDelta delta) |
| { |
| Object oldValue = workList.remove(delta.getIndex()); |
| ((CDOSingleValueFeatureDeltaImpl)delta).setValue(oldValue); // Adjust delta |
| } |
| |
| @Override |
| public void visit(CDOSetFeatureDelta delta) |
| { |
| EStructuralFeature feature = delta.getFeature(); |
| Object value = null; |
| if (feature.isMany()) |
| { |
| value = workList.set(delta.getIndex(), delta.getValue()); |
| } |
| else |
| { |
| value = ((InternalCDORevision)oldRevision).getValue(feature); |
| } |
| |
| ((CDOSetFeatureDeltaImpl)delta).setOldValue(value); // Adjust delta |
| } |
| }; |
| |
| for (CDOFeatureDelta featureDelta : revisionDelta.getFeatureDeltas()) |
| { |
| featureDelta.accept(visitor); |
| } |
| } |
| |
| @Override |
| public Object startLocalCommit() |
| { |
| return invalidator.startLocalCommit(); |
| } |
| |
| @Override |
| public void endLocalCommit(Object token) |
| { |
| invalidator.endLocalCommit(token); |
| } |
| |
| @Override |
| @Deprecated |
| public void invalidate(CDOCommitInfo commitInfo, InternalCDOTransaction sender) |
| { |
| throw new UnsupportedOperationException(); |
| } |
| |
| @Override |
| @Deprecated |
| public void invalidate(CDOCommitInfo commitInfo, InternalCDOTransaction sender, boolean clearResourcePathCache) |
| { |
| throw new UnsupportedOperationException(); |
| } |
| |
| @Override |
| @Deprecated |
| public void invalidate(CDOCommitInfo commitInfo, InternalCDOTransaction sender, boolean clearResourcePathCache, byte securityImpact, |
| Map<CDOID, CDOPermission> newPermissions) |
| { |
| throw new UnsupportedOperationException(); |
| } |
| |
| @Override |
| public void invalidate(InvalidationData invalidationData) |
| { |
| invalidator.scheduleInvalidations(invalidationData); |
| } |
| |
| @Override |
| @SuppressWarnings({ "unchecked", "rawtypes" }) |
| public Object getAdapter(Class adapter) |
| { |
| return AdapterUtil.adapt(this, adapter, false); |
| } |
| |
| @Override |
| public String toString() |
| { |
| String name = repositoryInfo == null ? "?" : repositoryInfo.getName(); //$NON-NLS-1$ |
| if (userID != null && userID.length() != 0) |
| { |
| name = userID + "@" + name; |
| } |
| |
| return MessageFormat.format("Session{0} [{1}]", sessionID, name); //$NON-NLS-1$ |
| } |
| |
| @Override |
| public CDOBranchPoint getCommittedSinceLastRefresh(CDOID id) |
| { |
| if (isSticky()) |
| { |
| return committedSinceLastRefresh.get(id); |
| } |
| |
| return null; |
| } |
| |
| @Override |
| public void setCommittedSinceLastRefresh(CDOID id, CDOBranchPoint branchPoint) |
| { |
| if (isSticky()) |
| { |
| committedSinceLastRefresh.put(id, branchPoint); |
| } |
| } |
| |
| @Override |
| public void clearCommittedSinceLastRefresh() |
| { |
| if (isSticky()) |
| { |
| committedSinceLastRefresh.clear(); |
| } |
| } |
| |
| @Override |
| public boolean isSticky() |
| { |
| return !options().isPassiveUpdateEnabled() && getRepositoryInfo().isSupportingAudits(); |
| } |
| |
| @Override |
| public CDOChangeSetData compareRevisions(CDOBranchPoint source, CDOBranchPoint target) |
| { |
| long now = getLastUpdateTime(); |
| |
| if (target.getTimeStamp() == CDOBranchPoint.UNSPECIFIED_DATE) |
| { |
| target = target.getBranch().getPoint(now); |
| } |
| |
| if (source.getTimeStamp() == CDOBranchPoint.UNSPECIFIED_DATE) |
| { |
| source = source.getBranch().getPoint(now); |
| } |
| |
| CDORevisionAvailabilityInfo targetInfo = createRevisionAvailabilityInfo2(target); |
| CDORevisionAvailabilityInfo sourceInfo = createRevisionAvailabilityInfo2(source); |
| |
| MergeDataResult result = sessionProtocol.loadMergeData2(targetInfo, sourceInfo, null, null); |
| Set<CDOID> ids = result.getTargetIDs(); |
| |
| cacheRevisions2(targetInfo); |
| cacheRevisions2(sourceInfo); |
| |
| return CDORevisionUtil.createChangeSetData(ids, sourceInfo, targetInfo); |
| } |
| |
| @Override |
| public MergeData getMergeData(CDOBranchPoint target, CDOBranchPoint source, CDOBranchPoint sourceBase, boolean computeChangeSets) |
| { |
| return getMergeData(target, source, null, sourceBase, computeChangeSets); |
| } |
| |
| @Override |
| public MergeData getMergeData(CDOBranchPoint target, CDOBranchPoint source, CDOBranchPoint targetBase, CDOBranchPoint sourceBase, boolean computeChangeSets) |
| { |
| boolean auto; |
| if (sourceBase == CDOBranchUtil.AUTO_BRANCH_POINT) |
| { |
| auto = true; |
| targetBase = CDOBranchUtil.AUTO_BRANCH_POINT; |
| } |
| else |
| { |
| auto = false; |
| CDOBranchPoint ancestor = null; |
| |
| if (sourceBase == null) |
| { |
| ancestor = CDOBranchUtil.getAncestor(target, source); |
| sourceBase = ancestor; |
| } |
| |
| if (targetBase == null) |
| { |
| if (ancestor == null) |
| { |
| ancestor = CDOBranchUtil.getAncestor(target, source); |
| } |
| |
| targetBase = ancestor; |
| } |
| } |
| |
| boolean sameBase = sourceBase.equals(targetBase); |
| |
| CDORevisionAvailabilityInfo targetInfo = createRevisionAvailabilityInfo2(target); |
| CDORevisionAvailabilityInfo sourceInfo = createRevisionAvailabilityInfo2(source); |
| CDORevisionAvailabilityInfo targetBaseInfo = createRevisionAvailabilityInfo2(targetBase); |
| CDORevisionAvailabilityInfo sourceBaseInfo = sameBase && !auto ? null : createRevisionAvailabilityInfo2(sourceBase); |
| |
| MergeDataResult result = sessionProtocol.loadMergeData2(targetInfo, sourceInfo, targetBaseInfo, sourceBaseInfo); |
| |
| if (auto) |
| { |
| sourceBase = sourceBaseInfo.getBranchPoint(); |
| targetBase = targetBaseInfo.getBranchPoint(); |
| sameBase = sourceBase.equals(targetBase); |
| } |
| |
| cacheRevisions2(targetInfo); |
| cacheRevisions2(sourceInfo); |
| cacheRevisions2(targetBaseInfo); |
| |
| if (sameBase) |
| { |
| sourceBaseInfo = targetBaseInfo; |
| } |
| else |
| { |
| cacheRevisions2(sourceBaseInfo); |
| } |
| |
| CDOChangeSet targetChanges = null; |
| CDOChangeSet sourceChanges = null; |
| if (computeChangeSets) |
| { |
| targetChanges = createChangeSet(result.getTargetIDs(), targetBaseInfo, targetInfo); |
| sourceChanges = createChangeSet(result.getSourceIDs(), sourceBaseInfo, sourceInfo); |
| } |
| |
| return new MergeData(target, targetInfo, targetBase, targetBaseInfo, result.getTargetIDs(), targetChanges, source, sourceInfo, sourceBase, sourceBaseInfo, |
| result.getSourceIDs(), sourceChanges, result.getResultBase()); |
| } |
| |
| @Override |
| @Deprecated |
| public CDORevisionAvailabilityInfo createRevisionAvailabilityInfo(CDOBranchPoint branchPoint) |
| { |
| throw new UnsupportedOperationException(); |
| } |
| |
| private CDORevisionAvailabilityInfo createRevisionAvailabilityInfo2(CDOBranchPoint branchPoint) |
| { |
| InternalCDORevisionManager revisionManager = getRevisionManager(); |
| CDORevisionAvailabilityInfo info = new CDORevisionAvailabilityInfo(branchPoint, revisionManager); |
| |
| if (branchPoint != CDOBranchUtil.AUTO_BRANCH_POINT) |
| { |
| InternalCDORevisionCache cache = revisionManager.getCache(); |
| |
| List<CDORevision> revisions = cache.getRevisions(branchPoint); |
| for (CDORevision revision : revisions) |
| { |
| if (revision instanceof PointerCDORevision) |
| { |
| PointerCDORevision pointer = (PointerCDORevision)revision; |
| CDOBranchVersion target = pointer.getTarget(); |
| if (target != null) |
| { |
| revision = cache.getRevisionByVersion(pointer.getID(), target); |
| } |
| } |
| else if (revision instanceof DetachedCDORevision) |
| { |
| revision = null; |
| } |
| |
| if (revision != null) |
| { |
| resolveAllElementProxies(revision); |
| info.addRevision(revision); |
| } |
| } |
| } |
| |
| return info; |
| } |
| |
| @Override |
| @Deprecated |
| public void cacheRevisions(CDORevisionAvailabilityInfo info) |
| { |
| throw new UnsupportedOperationException(); |
| } |
| |
| private void cacheRevisions2(CDORevisionAvailabilityInfo info) |
| { |
| InternalCDORevisionManager revisionManager = getRevisionManager(); |
| CDOBranch branch = info.getBranchPoint().getBranch(); |
| for (CDORevisionKey key : info.getAvailableRevisions().values()) |
| { |
| CDORevision revision = (CDORevision)key; |
| revisionManager.addRevision(revision); |
| |
| if (revision.getBranch() != branch) |
| { |
| CDOID id = revision.getID(); |
| CDORevision firstRevision = revisionManager.getCache().getRevisionByVersion(id, branch.getVersion(CDOBranchVersion.FIRST_VERSION)); |
| if (firstRevision != null) |
| { |
| long revised = firstRevision.getTimeStamp() - 1L; |
| CDOBranchVersion target = CDOBranchUtil.copyBranchVersion(revision); |
| PointerCDORevision pointer = new PointerCDORevision(revision.getEClass(), id, branch, revised, target); |
| revisionManager.addRevision(pointer); |
| } |
| } |
| } |
| } |
| |
| private CDOChangeSet createChangeSet(Set<CDOID> ids, CDORevisionAvailabilityInfo startInfo, CDORevisionAvailabilityInfo endInfo) |
| { |
| CDOChangeSetData data = CDORevisionUtil.createChangeSetData(ids, startInfo, endInfo); |
| return CDORevisionUtil.createChangeSet(startInfo.getBranchPoint(), endInfo.getBranchPoint(), data); |
| } |
| |
| @Override |
| protected void doActivate() throws Exception |
| { |
| super.doActivate(); |
| |
| Runnable runnable = SessionUtil.getTestDelayInSessionActivation(); |
| if (runnable != null) |
| { |
| runnable.run(); |
| } |
| |
| InternalCDORemoteSessionManager remoteSessionManager = new CDORemoteSessionManagerImpl(); |
| remoteSessionManager.setLocalSession(this); |
| setRemoteSessionManager(remoteSessionManager); |
| remoteSessionManager.activate(); |
| |
| checkState(sessionProtocol, "sessionProtocol"); //$NON-NLS-1$ |
| checkState(remoteSessionManager, "remoteSessionManager"); //$NON-NLS-1$ |
| } |
| |
| @Override |
| protected void doDeactivate() throws Exception |
| { |
| super.doDeactivate(); |
| |
| unhookSessionProtocol(); |
| |
| CDORemoteSessionManager remoteSessionManager = getRemoteSessionManager(); |
| setRemoteSessionManager(null); |
| LifecycleUtil.deactivate(remoteSessionManager); |
| |
| CDOSessionProtocol sessionProtocol = getSessionProtocol(); |
| LifecycleUtil.deactivate(sessionProtocol); |
| setSessionProtocol(null); |
| } |
| |
| /** |
| * Makes this session start listening to its protocol |
| */ |
| protected CDOSessionProtocol hookSessionProtocol() |
| { |
| EventUtil.addListener(sessionProtocol, sessionProtocolListener); |
| return sessionProtocol; |
| } |
| |
| /** |
| * Makes this session stop listening to its protocol |
| */ |
| protected void unhookSessionProtocol() |
| { |
| EventUtil.removeListener(sessionProtocol, sessionProtocolListener); |
| } |
| |
| protected void sessionProtocolDeactivated() |
| { |
| deactivate(); |
| } |
| |
| /** |
| * A separate class for better monitor debugging. |
| * |
| * @author Eike Stepper |
| */ |
| private static final class LastUpdateTimeLock |
| { |
| } |
| |
| /** |
| * @author Eike Stepper |
| * @since 2.0 |
| */ |
| protected class OptionsImpl extends Notifier implements Options |
| { |
| private boolean generatedPackageEmulationEnabled; |
| |
| private boolean passiveUpdateEnabled = true; |
| |
| private PassiveUpdateMode passiveUpdateMode = PassiveUpdateMode.INVALIDATIONS; |
| |
| private LockNotificationMode lockNotificationMode = LockNotificationMode.IF_REQUIRED_BY_VIEWS; |
| |
| private CDOCollectionLoadingPolicy collectionLoadingPolicy; |
| |
| private CDOLobStore lobCache = CDOLobStoreImpl.INSTANCE; |
| |
| private CDOPermissionUpdater permissionUpdater = CDOPermissionUpdater.SERVER; |
| |
| private boolean delegableViewLockEnabled; |
| |
| public OptionsImpl() |
| { |
| setCollectionLoadingPolicy(null); // Init default |
| } |
| |
| @Override |
| public CDOSession getContainer() |
| { |
| return CDOSessionImpl.this; |
| } |
| |
| @Override |
| public boolean isGeneratedPackageEmulationEnabled() |
| { |
| return generatedPackageEmulationEnabled; |
| } |
| |
| @Override |
| public synchronized void setGeneratedPackageEmulationEnabled(boolean generatedPackageEmulationEnabled) |
| { |
| this.generatedPackageEmulationEnabled = generatedPackageEmulationEnabled; |
| if (this.generatedPackageEmulationEnabled != generatedPackageEmulationEnabled) |
| { |
| this.generatedPackageEmulationEnabled = generatedPackageEmulationEnabled; |
| // TODO Check inconsistent state if switching off? |
| |
| IListener[] listeners = getListeners(); |
| if (listeners != null) |
| { |
| fireEvent(new GeneratedPackageEmulationEventImpl(), listeners); |
| } |
| } |
| } |
| |
| @Override |
| public boolean isPassiveUpdateEnabled() |
| { |
| return passiveUpdateEnabled; |
| } |
| |
| @Override |
| public synchronized void setPassiveUpdateEnabled(boolean passiveUpdateEnabled) |
| { |
| if (this.passiveUpdateEnabled != passiveUpdateEnabled) |
| { |
| this.passiveUpdateEnabled = passiveUpdateEnabled; |
| CDOSessionProtocol protocol = getSessionProtocol(); |
| if (protocol != null) |
| { |
| if (passiveUpdateEnabled) |
| { |
| refresh(true); |
| } |
| else |
| { |
| protocol.disablePassiveUpdate(); |
| } |
| |
| IListener[] listeners = getListeners(); |
| if (listeners != null) |
| { |
| fireEvent(new PassiveUpdateEventImpl(!passiveUpdateEnabled, passiveUpdateEnabled, passiveUpdateMode, passiveUpdateMode), listeners); |
| } |
| } |
| } |
| } |
| |
| @Override |
| public PassiveUpdateMode getPassiveUpdateMode() |
| { |
| return passiveUpdateMode; |
| } |
| |
| @Override |
| public void setPassiveUpdateMode(PassiveUpdateMode passiveUpdateMode) |
| { |
| checkArg(passiveUpdateMode, "passiveUpdateMode"); //$NON-NLS-1$ |
| if (this.passiveUpdateMode != passiveUpdateMode) |
| { |
| PassiveUpdateMode oldMode = this.passiveUpdateMode; |
| this.passiveUpdateMode = passiveUpdateMode; |
| CDOSessionProtocol protocol = getSessionProtocol(); |
| if (protocol != null) |
| { |
| protocol.setPassiveUpdateMode(passiveUpdateMode); |
| |
| IListener[] listeners = getListeners(); |
| if (listeners != null) |
| { |
| fireEvent(new PassiveUpdateEventImpl(passiveUpdateEnabled, passiveUpdateEnabled, oldMode, passiveUpdateMode), listeners); |
| } |
| } |
| } |
| } |
| |
| @Override |
| public LockNotificationMode getLockNotificationMode() |
| { |
| return lockNotificationMode; |
| } |
| |
| @Override |
| public void setLockNotificationMode(LockNotificationMode lockNotificationMode) |
| { |
| checkArg(lockNotificationMode, "lockNotificationMode"); //$NON-NLS-1$ |
| if (this.lockNotificationMode != lockNotificationMode) |
| { |
| LockNotificationMode oldMode = this.lockNotificationMode; |
| this.lockNotificationMode = lockNotificationMode; |
| CDOSessionProtocol protocol = getSessionProtocol(); |
| if (protocol != null) |
| { |
| protocol.setLockNotificationMode(lockNotificationMode); |
| |
| IListener[] listeners = getListeners(); |
| if (listeners != null) |
| { |
| fireEvent(new LockNotificationModeEventImpl(oldMode, lockNotificationMode), listeners); |
| } |
| } |
| } |
| this.lockNotificationMode = lockNotificationMode; |
| } |
| |
| @Override |
| public CDOCollectionLoadingPolicy getCollectionLoadingPolicy() |
| { |
| synchronized (this) |
| { |
| return collectionLoadingPolicy; |
| } |
| } |
| |
| @Override |
| public void setCollectionLoadingPolicy(CDOCollectionLoadingPolicy policy) |
| { |
| if (policy == null) |
| { |
| policy = CDOUtil.createCollectionLoadingPolicy(CDORevision.UNCHUNKED, CDORevision.UNCHUNKED); |
| } |
| |
| CDOSession oldSession = policy.getSession(); |
| if (oldSession != null) |
| { |
| throw new IllegalArgumentException("Policy is already associated with " + oldSession); |
| } |
| |
| policy.setSession(CDOSessionImpl.this); |
| |
| IListener[] listeners = getListeners(); |
| IEvent event = null; |
| |
| synchronized (this) |
| { |
| if (collectionLoadingPolicy != policy) |
| { |
| collectionLoadingPolicy = policy; |
| if (listeners != null) |
| { |
| event = new CollectionLoadingPolicyEventImpl(); |
| } |
| } |
| } |
| |
| if (event != null) |
| { |
| fireEvent(event, listeners); |
| } |
| } |
| |
| @Override |
| public CDOLobStore getLobCache() |
| { |
| synchronized (this) |
| { |
| return lobCache; |
| } |
| } |
| |
| @Override |
| public void setLobCache(CDOLobStore cache) |
| { |
| if (cache == null) |
| { |
| cache = CDOLobStoreImpl.INSTANCE; |
| } |
| |
| IListener[] listeners = getListeners(); |
| IEvent event = null; |
| |
| synchronized (this) |
| { |
| if (lobCache != cache) |
| { |
| lobCache = cache; |
| if (listeners != null) |
| { |
| event = new LobCacheEventImpl(); |
| } |
| } |
| } |
| |
| if (event != null) |
| { |
| fireEvent(event, listeners); |
| } |
| } |
| |
| @Override |
| public CDOPermissionUpdater getPermissionUpdater() |
| { |
| synchronized (this) |
| { |
| return permissionUpdater; |
| } |
| } |
| |
| @Override |
| public void setPermissionUpdater(CDOPermissionUpdater permissionUpdater) |
| { |
| IListener[] listeners = getListeners(); |
| IEvent event = null; |
| |
| synchronized (this) |
| { |
| if (this.permissionUpdater != permissionUpdater) |
| { |
| this.permissionUpdater = permissionUpdater; |
| if (listeners != null) |
| { |
| event = new PermissionUpdaterEventImpl(); |
| } |
| } |
| } |
| |
| if (event != null) |
| { |
| fireEvent(event, listeners); |
| } |
| } |
| |
| @Override |
| public boolean isDelegableViewLockEnabled() |
| { |
| synchronized (this) |
| { |
| return delegableViewLockEnabled; |
| } |
| } |
| |
| @Override |
| public void setDelegableViewLockEnabled(boolean delegableViewLockEnabled) |
| { |
| IListener[] listeners = getListeners(); |
| IEvent event = null; |
| |
| synchronized (this) |
| { |
| if (this.delegableViewLockEnabled != delegableViewLockEnabled) |
| { |
| this.delegableViewLockEnabled = delegableViewLockEnabled; |
| if (listeners != null) |
| { |
| event = new DelegableViewLockEventImpl(); |
| } |
| } |
| } |
| |
| if (event != null) |
| { |
| fireEvent(event, listeners); |
| } |
| } |
| |
| /** |
| * @author Eike Stepper |
| */ |
| private final class GeneratedPackageEmulationEventImpl extends OptionsEvent implements GeneratedPackageEmulationEvent |
| { |
| private static final long serialVersionUID = 1L; |
| |
| public GeneratedPackageEmulationEventImpl() |
| { |
| super(OptionsImpl.this); |
| } |
| } |
| |
| /** |
| * @author Eike Stepper |
| */ |
| private final class PassiveUpdateEventImpl extends OptionsEvent implements PassiveUpdateEvent |
| { |
| private static final long serialVersionUID = 1L; |
| |
| private boolean oldEnabled; |
| |
| private boolean newEnabled; |
| |
| private PassiveUpdateMode oldMode; |
| |
| private PassiveUpdateMode newMode; |
| |
| public PassiveUpdateEventImpl(boolean oldEnabled, boolean newEnabled, PassiveUpdateMode oldMode, PassiveUpdateMode newMode) |
| { |
| super(OptionsImpl.this); |
| this.oldEnabled = oldEnabled; |
| this.newEnabled = newEnabled; |
| this.oldMode = oldMode; |
| this.newMode = newMode; |
| } |
| |
| @Override |
| public boolean getOldEnabled() |
| { |
| return oldEnabled; |
| } |
| |
| @Override |
| public boolean getNewEnabled() |
| { |
| return newEnabled; |
| } |
| |
| @Override |
| public PassiveUpdateMode getOldMode() |
| { |
| return oldMode; |
| } |
| |
| @Override |
| public PassiveUpdateMode getNewMode() |
| { |
| return newMode; |
| } |
| } |
| |
| /** |
| * @author Caspar De Groot |
| */ |
| private final class LockNotificationModeEventImpl extends OptionsEvent implements LockNotificationModeEvent |
| { |
| private static final long serialVersionUID = 1L; |
| |
| private LockNotificationMode oldMode, newMode; |
| |
| public LockNotificationModeEventImpl(LockNotificationMode oldMode, LockNotificationMode newMode) |
| { |
| super(OptionsImpl.this); |
| this.oldMode = oldMode; |
| this.newMode = newMode; |
| } |
| |
| @Override |
| public LockNotificationMode getOldMode() |
| { |
| return oldMode; |
| } |
| |
| @Override |
| public LockNotificationMode getNewMode() |
| { |
| return newMode; |
| } |
| } |
| |
| /** |
| * @author Eike Stepper |
| */ |
| private final class CollectionLoadingPolicyEventImpl extends OptionsEvent implements CollectionLoadingPolicyEvent |
| { |
| private static final long serialVersionUID = 1L; |
| |
| public CollectionLoadingPolicyEventImpl() |
| { |
| super(OptionsImpl.this); |
| } |
| } |
| |
| /** |
| * @author Eike Stepper |
| */ |
| private final class LobCacheEventImpl extends OptionsEvent implements LobCacheEvent |
| { |
| private static final long serialVersionUID = 1L; |
| |
| public LobCacheEventImpl() |
| { |
| super(OptionsImpl.this); |
| } |
| } |
| |
| /** |
| * @author Eike Stepper |
| */ |
| private final class PermissionUpdaterEventImpl extends OptionsEvent implements PermissionUpdaterEvent |
| { |
| private static final long serialVersionUID = 1L; |
| |
| public PermissionUpdaterEventImpl() |
| { |
| super(OptionsImpl.this); |
| } |
| } |
| |
| /** |
| * @author Eike Stepper |
| */ |
| private final class DelegableViewLockEventImpl extends OptionsEvent implements DelegableViewLockEvent |
| { |
| private static final long serialVersionUID = 1L; |
| |
| public DelegableViewLockEventImpl() |
| { |
| super(OptionsImpl.this); |
| } |
| } |
| } |
| |
| /** |
| * @author Eike Stepper |
| */ |
| private final class SessionInvalidator |
| { |
| private final Set<Object> unfinishedLocalCommits = new HashSet<>(); |
| |
| private final List<SessionInvalidation> invalidationQueue = new ArrayList<>(); |
| |
| private final Queue<Runnable> postInvalidationQueue = new ConcurrentLinkedQueue<>(); |
| |
| private int lastCommitNumber; |
| |
| public SessionInvalidator() |
| { |
| } |
| |
| public synchronized Object startLocalCommit() |
| { |
| if (!isActive()) |
| { |
| return null; |
| } |
| |
| CommitToken token = new CommitToken(++lastCommitNumber, Thread.currentThread().getName()); |
| |
| if (DEBUG_INVALIDATION) |
| { |
| IOUtil.OUT().println(CDOSessionImpl.this + " [" + getLastUpdateTime() % 10000 + "] startLocalCommit: " + token); |
| } |
| |
| unfinishedLocalCommits.add(token); |
| return token; |
| } |
| |
| public synchronized void endLocalCommit(Object token) |
| { |
| if (DEBUG_INVALIDATION) |
| { |
| IOUtil.OUT().println(CDOSessionImpl.this + " [" + getLastUpdateTime() % 10000 + "] endLocalCommit: " + token); |
| } |
| |
| unfinishedLocalCommits.remove(token); |
| } |
| |
| public void scheduleInvalidations(InvalidationData invalidationData) |
| { |
| SessionInvalidation invalidation = new SessionInvalidation(invalidationData); |
| |
| synchronized (this) |
| { |
| invalidationQueue.add(invalidation); |
| Collections.sort(invalidationQueue); |
| |
| if (DEBUG_INVALIDATION) |
| { |
| IOUtil.OUT().println(CDOSessionImpl.this + " [" + getLastUpdateTime() % 10000 + "] " + invalidation.getPreviousTimeStamp() % 10000 + " --> " |
| + invalidation.getTimeStamp() % 10000 + " reorderQueue=" + invalidationQueue + " unfinishedLocalCommits=" + unfinishedLocalCommits); |
| } |
| } |
| |
| while (isActive()) |
| { |
| synchronized (this) |
| { |
| if (invalidationQueue.isEmpty() || !canProcess(invalidationQueue.get(0))) |
| { |
| break; |
| } |
| |
| SessionInvalidation invalidation0 = invalidationQueue.remove(0); |
| Runnable postInvalidationRunnable = invalidation0.process(); |
| if (postInvalidationRunnable != null) |
| { |
| postInvalidationQueue.add(postInvalidationRunnable); |
| } |
| } |
| |
| Runnable postInvalidationRunnable; |
| while ((postInvalidationRunnable = postInvalidationQueue.poll()) != null) |
| { |
| postInvalidationRunnable.run(); |
| } |
| } |
| } |
| |
| private boolean canProcess(SessionInvalidation invalidation) |
| { |
| if (options().isPassiveUpdateEnabled()) |
| { |
| long previousTimeStamp = invalidation.getPreviousTimeStamp(); |
| long lastUpdateTime = getLastUpdateTime(); |
| return previousTimeStamp <= lastUpdateTime; // Can be smaller in replication scenarios |
| } |
| |
| return unfinishedLocalCommits.size() == 1; // Ourselves |
| } |
| } |
| |
| /** |
| * @author Eike Stepper |
| */ |
| private final class SessionInvalidation implements Comparable<SessionInvalidation> |
| { |
| private final InvalidationData invalidationData; |
| |
| private final CDOCommitInfo commitInfo; |
| |
| public SessionInvalidation(InvalidationData invalidationData) |
| { |
| this.invalidationData = invalidationData; |
| commitInfo = invalidationData.getCommitInfo(); |
| } |
| |
| public long getTimeStamp() |
| { |
| return commitInfo.getTimeStamp(); |
| } |
| |
| public long getPreviousTimeStamp() |
| { |
| return commitInfo.getPreviousTimeStamp(); |
| } |
| |
| @Override |
| public int compareTo(SessionInvalidation o) |
| { |
| return CDOCommonUtil.compareTimeStamps(getTimeStamp(), o.getTimeStamp()); |
| } |
| |
| @Override |
| public String toString() |
| { |
| return Long.toString(getTimeStamp() % 10000); |
| } |
| |
| public Runnable process() |
| { |
| long timeStamp = getTimeStamp(); |
| |
| if (DEBUG_INVALIDATION) |
| { |
| IOUtil.OUT().println(CDOSessionImpl.this + " [" + getLastUpdateTime() % 10000 + "] " + timeStamp % 10000 + " INVALIDATE"); |
| } |
| |
| try |
| { |
| InternalCDOView[] views = getViews(); |
| Map<CDORevision, CDOPermission> oldPermissions = null; |
| Map<CDOID, InternalCDORevision> oldRevisions = null; |
| |
| CDOBranch branch = commitInfo.getBranch(); |
| boolean success = branch != null; |
| if (success) |
| { |
| oldRevisions = reviseRevisions(); |
| |
| if (invalidationData.getSecurityImpact() != CommitNotificationInfo.IMPACT_NONE) |
| { |
| oldPermissions = updatePermissions(commitInfo); |
| } |
| |
| commitInfoManager.setLastCommitOfBranch(branch, timeStamp); |
| } |
| |
| if (options.isPassiveUpdateEnabled()/* || sender != null */) |
| { |
| setLastUpdateTime(timeStamp); |
| } |
| |
| Map<CDORevision, CDOPermission> oldPermissionsFinal = oldPermissions; |
| Map<CDOID, InternalCDORevision> oldRevisionsFinal = oldRevisions; |
| |
| return () -> { |
| CDOLockChangeInfo lockChangeInfo = invalidationData.getLockChangeInfo(); |
| InternalCDOTransaction sender = invalidationData.getSender(); |
| |
| if (success) |
| { |
| fireEvent(new SessionInvalidationEvent(sender, commitInfo, invalidationData.getSecurityImpact(), oldPermissionsFinal)); |
| fireEvent(new SessionLocksChangedEvent(sender, lockChangeInfo)); |
| |
| commitInfoManager.notifyCommitInfoHandlers(commitInfo); |
| } |
| |
| for (InternalCDOView view : views) |
| { |
| invalidateView(commitInfo, view, sender, oldRevisionsFinal, invalidationData.isClearResourcePathCache(), lockChangeInfo); |
| } |
| }; |
| } |
| catch (RuntimeException ex) |
| { |
| if (isActive()) |
| { |
| throw ex; |
| } |
| |
| if (TRACER.isEnabled()) |
| { |
| TRACER.trace(Messages.getString("CDOSessionImpl.2")); //$NON-NLS-1$ |
| } |
| } |
| |
| return null; |
| } |
| |
| private Map<CDOID, InternalCDORevision> reviseRevisions() |
| { |
| Map<CDOID, InternalCDORevision> oldRevisions = null; |
| CDOBranch newBranch = commitInfo.getBranch(); |
| long timeStamp = getTimeStamp(); |
| |
| // Cache new revisions |
| for (CDOIDAndVersion key : commitInfo.getNewObjects()) |
| { |
| if (key instanceof InternalCDORevision) |
| { |
| InternalCDORevision newRevision = (InternalCDORevision)key; |
| addNewRevision(newRevision); |
| } |
| } |
| |
| // Apply deltas and cache the resulting new revisions, if possible... |
| for (CDORevisionKey key : commitInfo.getChangedObjects()) |
| { |
| CDOID id = key.getID(); |
| if (key instanceof CDORevisionDelta) |
| { |
| CDORevisionDelta revisionDelta = (CDORevisionDelta)key; |
| |
| InternalCDORevision oldRevision = revisionManager.getRevisionByVersion(id, revisionDelta, CDORevision.UNCHUNKED, false); |
| if (oldRevision != null) |
| { |
| addOldValuesToDelta(oldRevision, revisionDelta); |
| |
| InternalCDORevision newRevision = oldRevision.copy(); |
| newRevision.adjustForCommit(newBranch, timeStamp); |
| |
| CDORevisable target = revisionDelta.getTarget(); |
| if (target != null) |
| { |
| newRevision.setVersion(target.getVersion()); |
| } |
| |
| boolean bypassPermissionChecks = newRevision.bypassPermissionChecks(true); |
| |
| try |
| { |
| revisionDelta.applyTo(newRevision); |
| } |
| finally |
| { |
| newRevision.bypassPermissionChecks(bypassPermissionChecks); |
| newRevision.freeze(); |
| } |
| |
| addNewRevision(newRevision); |
| if (oldRevisions == null) |
| { |
| oldRevisions = CDOIDUtil.createMap(); |
| } |
| |
| oldRevisions.put(id, oldRevision); |
| } |
| } |
| else |
| { |
| // ... otherwise try to revise old revision if it is in the same branch |
| if (key.getBranch() == newBranch) |
| { |
| revisionManager.reviseVersion(id, key, timeStamp); |
| } |
| } |
| } |
| |
| // Revise old revisions |
| for (CDOIDAndVersion key : commitInfo.getDetachedObjects()) |
| { |
| CDOID id = key.getID(); |
| revisionManager.reviseLatest(id, newBranch); |
| } |
| |
| return oldRevisions; |
| } |
| |
| private void addNewRevision(InternalCDORevision newRevision) |
| { |
| Map<CDOID, CDOPermission> newPermissions = invalidationData.getNewPermissions(); |
| if (newPermissions != null) |
| { |
| CDOPermission newPermission = newPermissions.get(newRevision.getID()); |
| if (newPermission != null) |
| { |
| newRevision.setPermission(newPermission); |
| } |
| } |
| |
| revisionManager.addRevision(newRevision); |
| } |
| |
| private void invalidateView(CDOCommitInfo commitInfo, InternalCDOView view, InternalCDOTransaction sender, Map<CDOID, InternalCDORevision> oldRevisions, |
| boolean clearResourcePathCache, CDOLockChangeInfo lockChangeInfo) |
| { |
| try |
| { |
| byte securityImpact = invalidationData.getSecurityImpact(); |
| |
| ViewInvalidationData invalidationData = new ViewInvalidationData(); |
| invalidationData.setLastUpdateTime(getTimeStamp()); |
| invalidationData.setSecurityImpact(securityImpact); |
| invalidationData.setAsync(true); |
| |
| // The committing view (sender) is already valid, just the timestamp must be set "in sequence". |
| // Setting the sender's timestamp synchronously can lead to deadlock |
| if (view != sender) |
| { |
| invalidationData.setBranch(commitInfo.getBranch()); |
| invalidationData.setAllChangedObjects(commitInfo.getChangedObjects()); |
| invalidationData.setAllDetachedObjects(commitInfo.getDetachedObjects()); |
| invalidationData.setOldRevisions(oldRevisions); |
| invalidationData.setClearResourcePathCache(clearResourcePathCache); |
| invalidationData.setLockChangeInfo(lockChangeInfo); |
| } |
| |
| view.invalidate(invalidationData); |
| } |
| catch (RuntimeException ex) |
| { |
| if (view.isActive()) |
| { |
| OM.LOG.error(ex); |
| } |
| else |
| { |
| if (TRACER.isEnabled()) |
| { |
| TRACER.trace(Messages.getString("CDOSessionImpl.1")); //$NON-NLS-1$ |
| } |
| } |
| } |
| } |
| } |
| |
| /** |
| * @author Eike Stepper |
| */ |
| private final class SessionInvalidationEvent extends Event implements InternalCDOSessionInvalidationEvent |
| { |
| private static final long serialVersionUID = 1L; |
| |
| private InternalCDOTransaction sender; |
| |
| private CDOCommitInfo commitInfo; |
| |
| private byte securityImpact; |
| |
| private Map<CDORevision, CDOPermission> oldPermissions; |
| |
| public SessionInvalidationEvent(InternalCDOTransaction sender, CDOCommitInfo commitInfo, byte securityImpact, |
| Map<CDORevision, CDOPermission> oldPermissions) |
| { |
| super(CDOSessionImpl.this); |
| this.sender = sender; |
| this.commitInfo = commitInfo; |
| this.securityImpact = securityImpact; |
| this.oldPermissions = oldPermissions; |
| } |
| |
| @Override |
| public CDOSession getSource() |
| { |
| return (CDOSession)super.getSource(); |
| } |
| |
| @Override |
| public CDOCommitInfoManager getCommitInfoManager() |
| { |
| return commitInfo.getCommitInfoManager(); |
| } |
| |
| @Override |
| public CDOTransaction getLocalTransaction() |
| { |
| return sender; |
| } |
| |
| @Override |
| @Deprecated |
| public InternalCDOView getView() |
| { |
| return sender; |
| } |
| |
| @Override |
| public boolean isRemote() |
| { |
| return sender == null; |
| } |
| |
| @Override |
| public CDOBranch getBranch() |
| { |
| return commitInfo.getBranch(); |
| } |
| |
| @Override |
| public long getTimeStamp() |
| { |
| return commitInfo.getTimeStamp(); |
| } |
| |
| @Override |
| public long getPreviousTimeStamp() |
| { |
| return commitInfo.getPreviousTimeStamp(); |
| } |
| |
| @Override |
| public CDOCommitInfo getPreviousCommitInfo() |
| { |
| return commitInfo.getPreviousCommitInfo(); |
| } |
| |
| @Override |
| public String getUserID() |
| { |
| return commitInfo.getUserID(); |
| } |
| |
| @Override |
| public String getComment() |
| { |
| return commitInfo.getComment(); |
| } |
| |
| @Override |
| public CDOBranchPoint getMergeSource() |
| { |
| return commitInfo.getMergeSource(); |
| } |
| |
| @Override |
| public CDOCommitInfo getMergedCommitInfo() |
| { |
| CDOBranchPoint mergeSource = getMergeSource(); |
| return mergeSource == null ? null : commitInfoManager.getCommitInfo(mergeSource.getBranch(), mergeSource.getTimeStamp(), false); |
| } |
| |
| @Override |
| public boolean isEmpty() |
| { |
| return false; |
| } |
| |
| @Override |
| public boolean isInitialCommit() |
| { |
| return commitInfo.isInitialCommit(); |
| } |
| |
| @Override |
| public boolean isCommitDataLoaded() |
| { |
| return commitInfo.isCommitDataLoaded(); |
| } |
| |
| @Override |
| public CDOChangeSetData copy() |
| { |
| return commitInfo.copy(); |
| } |
| |
| @Override |
| public void merge(CDOChangeSetData changeSetData) |
| { |
| commitInfo.merge(changeSetData); |
| } |
| |
| @Override |
| public List<CDOPackageUnit> getNewPackageUnits() |
| { |
| return commitInfo.getNewPackageUnits(); |
| } |
| |
| @Override |
| public List<CDOIDAndVersion> getNewObjects() |
| { |
| return commitInfo.getNewObjects(); |
| } |
| |
| @Override |
| public List<CDORevisionKey> getChangedObjects() |
| { |
| return commitInfo.getChangedObjects(); |
| } |
| |
| @Override |
| public List<CDOIDAndVersion> getDetachedObjects() |
| { |
| return commitInfo.getDetachedObjects(); |
| } |
| |
| @Override |
| public Map<CDOID, CDOChangeKind> getChangeKinds() |
| { |
| return commitInfo.getChangeKinds(); |
| } |
| |
| @Override |
| public CDOChangeKind getChangeKind(CDOID id) |
| { |
| return commitInfo.getChangeKind(id); |
| } |
| |
| @Override |
| public byte getSecurityImpact() |
| { |
| return securityImpact; |
| } |
| |
| @Override |
| public Map<CDORevision, CDOPermission> getOldPermissions() |
| { |
| return oldPermissions; |
| } |
| |
| @Override |
| public String toString() |
| { |
| return "CDOSessionInvalidationEvent[" + commitInfo + "]"; //$NON-NLS-1$ //$NON-NLS-2$ |
| } |
| } |
| |
| /** |
| * @author Caspar De Groot |
| * @since 4.1 |
| */ |
| private final class SessionLocksChangedEvent extends DefaultLocksChangedEvent implements CDOSessionLocksChangedEvent |
| { |
| private static final long serialVersionUID = 1L; |
| |
| public SessionLocksChangedEvent(InternalCDOView sender, CDOLockChangeInfo lockChangeInfo) |
| { |
| super(CDOSessionImpl.this, sender, lockChangeInfo); |
| } |
| |
| @Override |
| public CDOSession getSource() |
| { |
| return (CDOSession)super.getSource(); |
| } |
| |
| @Override |
| protected String formatEventName() |
| { |
| return "CDOSessionLocksChangedEvent"; |
| } |
| } |
| } |