blob: dd99fa4d6fdde2c244e75091080fa74776a374df [file] [log] [blame]
/*
* Copyright (c) 2010-2013, 2015 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:
* Eike Stepper - initial API and implementation
* Andre Dietisheim - bug 256649
*/
package org.eclipse.emf.cdo.internal.common.commit;
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.commit.CDOCommitData;
import org.eclipse.emf.cdo.common.commit.CDOCommitHistory;
import org.eclipse.emf.cdo.common.commit.CDOCommitInfo;
import org.eclipse.emf.cdo.common.commit.CDOCommitInfoHandler;
import org.eclipse.emf.cdo.internal.common.bundle.OM;
import org.eclipse.emf.cdo.spi.common.commit.CDOCommitInfoUtil;
import org.eclipse.emf.cdo.spi.common.commit.InternalCDOCommitInfoManager;
import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.WeakHashMap;
/**
* @author Andre Dietisheim
*/
public class CDOCommitInfoManagerImpl extends CDOCommitHistoryProviderImpl<CDOBranch, CDOCommitHistory>
implements InternalCDOCommitInfoManager
{
private final Map<CDOCommitInfo, WeakReference<CDOCommitInfo>> cache;
private final Object cacheLock = new Object();
private final Map<CDOBranch, BranchInfoCache> branches = new WeakHashMap<CDOBranch, BranchInfoCache>();
private CDOCommonRepository repository;
private CommitInfoLoader loader;
private List<CDOCommitInfoHandler> handlers = new ArrayList<CDOCommitInfoHandler>();
public CDOCommitInfoManagerImpl(boolean caching)
{
if (caching)
{
cache = new WeakHashMap<CDOCommitInfo, WeakReference<CDOCommitInfo>>();
}
else
{
cache = null;
}
}
public CDOCommonRepository getRepository()
{
return repository;
}
public void setRepository(CDOCommonRepository repository)
{
checkInactive();
this.repository = repository;
}
public CommitInfoLoader getCommitInfoLoader()
{
return loader;
}
public void setCommitInfoLoader(CommitInfoLoader commitInfoLoader)
{
checkInactive();
loader = commitInfoLoader;
}
public CDOCommitInfoHandler[] getCommitInfoHandlers()
{
synchronized (handlers)
{
return handlers.toArray(new CDOCommitInfoHandler[handlers.size()]);
}
}
/**
* @since 4.0
*/
public void addCommitInfoHandler(CDOCommitInfoHandler handler)
{
synchronized (handlers)
{
handlers.add(handler);
}
}
/**
* @since 4.0
*/
public void removeCommitInfoHandler(CDOCommitInfoHandler handler)
{
synchronized (handlers)
{
handlers.remove(handler);
}
}
public void notifyCommitInfoHandlers(CDOCommitInfo commitInfo)
{
for (CDOCommitInfoHandler handler : getCommitInfoHandlers())
{
try
{
handler.handleCommitInfo(commitInfo);
}
catch (Exception ex)
{
OM.LOG.error(ex);
}
}
}
public CDOCommitInfo createCommitInfo(CDOBranch branch, long timeStamp, long previousTimeStamp, String userID,
String comment, CDOCommitData commitData)
{
checkActive();
CDOCommitInfo commitInfo = new CDOCommitInfoImpl(this, branch, timeStamp, previousTimeStamp, userID, comment,
commitData);
return intern(commitInfo);
}
public CDOCommitInfo getCommitInfo(long timeStamp)
{
checkActive();
if (cache != null)
{
synchronized (cacheLock)
{
for (CDOCommitInfo commitInfo : cache.keySet())
{
if (commitInfo.getTimeStamp() == timeStamp)
{
return commitInfo;
}
}
}
}
final CDOCommitInfo[] result = { null };
getCommitInfos(null, timeStamp, timeStamp, new CDOCommitInfoHandler()
{
public void handleCommitInfo(CDOCommitInfo commitInfo)
{
result[0] = commitInfo;
}
});
return result[0];
}
public CDOCommitInfo getCommitInfo(CDOBranch branch, long startTime, boolean up)
{
checkActive();
int count = up ? 1 : -1;
final CDOCommitInfo[] result = { null };
getCommitInfos(branch, startTime, null, null, count, new CDOCommitInfoHandler()
{
public void handleCommitInfo(CDOCommitInfo commitInfo)
{
result[0] = commitInfo;
}
});
return result[0];
}
public void getCommitInfos(CDOBranch branch, long startTime, long endTime, CDOCommitInfoHandler handler)
{
checkActive();
if (cache != null)
{
final CDOCommitInfoHandler delegate = handler;
handler = new CDOCommitInfoHandler()
{
public void handleCommitInfo(CDOCommitInfo commitInfo)
{
delegate.handleCommitInfo(intern(commitInfo));
}
};
}
loader.loadCommitInfos(branch, startTime, endTime, handler);
}
public void getCommitInfos(CDOBranch branch, long startTime, String reserved1, String reserved2, int count,
CDOCommitInfoHandler handler)
{
if (reserved1 != null || reserved2 != null)
{
throw new IllegalArgumentException("The parameters reserved1 and reserved2 are not supported");
}
long endTime = CDOCommitInfoUtil.encodeCount(count);
getCommitInfos(branch, startTime, endTime, handler);
}
public CDOCommitInfo getBaseOfBranch(CDOBranch branch)
{
if (branch.isMainBranch())
{
return null;
}
BranchInfoCache infoCache = getBranchInfoCache(branch);
CDOCommitInfo base = infoCache.getBase();
if (base == null)
{
base = loadBaseOfBranch(branch);
infoCache.setBase(base);
}
return base;
}
public CDOCommitInfo getFirstOfBranch(CDOBranch branch)
{
BranchInfoCache infoCache = getBranchInfoCache(branch);
CDOCommitInfo first = infoCache.getFirst();
if (first == null)
{
first = loadFirstOfBranch(branch);
infoCache.setFirst(first);
}
return first;
}
public CDOCommitInfo getLastOfBranch(CDOBranch branch)
{
BranchInfoCache infoCache = getBranchInfoCache(branch);
CDOCommitInfo last = infoCache.getLast();
if (last == null)
{
last = loadLastOfBranch(branch);
infoCache.setLast(last);
}
return last;
}
@Override
public String toString()
{
return "CommitInfoManager";
}
@Override
protected void doBeforeActivate() throws Exception
{
super.doBeforeActivate();
checkState(loader, "commitInfoLoader"); //$NON-NLS-1$
}
@Override
protected void doDeactivate() throws Exception
{
if (cache != null)
{
synchronized (cacheLock)
{
cache.clear();
}
}
super.doDeactivate();
}
@Override
protected CDOCommitHistory createHistory(CDOBranch key)
{
return new CDOCommitHistoryImpl(this, key);
}
private CDOCommitInfo intern(CDOCommitInfo commitInfo)
{
if (cache != null && commitInfo != null)
{
synchronized (cacheLock)
{
WeakReference<CDOCommitInfo> ref = cache.get(commitInfo);
CDOCommitInfo cachedCommitInfo = ref != null ? ref.get() : null;
if (cachedCommitInfo != null)
{
return cachedCommitInfo;
}
cache.put(commitInfo, new WeakReference<CDOCommitInfo>(commitInfo));
}
}
return commitInfo;
}
private BranchInfoCache getBranchInfoCache(CDOBranch branch)
{
BranchInfoCache infoCache = branches.get(branch);
if (infoCache == null)
{
infoCache = new BranchInfoCache();
branches.put(branch, infoCache);
}
return infoCache;
}
private CDOCommitInfo loadBaseOfBranch(CDOBranch branch)
{
CDOBranchPoint base = branch.getBase();
for (;;)
{
CDOBranch baseBranch = base.getBranch();
if (baseBranch == null)
{
break;
}
long baseTime = base.getTimeStamp();
CDOCommitInfo commitInfo = getCommitInfo(baseBranch, baseTime, false);
if (commitInfo != null)
{
return commitInfo;
}
base = baseBranch.getBase();
}
return null;
}
private CDOCommitInfo loadFirstOfBranch(CDOBranch branch)
{
return getCommitInfo(branch, 1L, true);
}
private CDOCommitInfo loadLastOfBranch(CDOBranch branch)
{
return getCommitInfo(branch, Long.MAX_VALUE, false);
}
/**
* @author Eike Stepper
*/
private static final class BranchInfoCache
{
private SoftReference<CDOCommitInfo> base;
private SoftReference<CDOCommitInfo> first;
private SoftReference<CDOCommitInfo> last;
public BranchInfoCache()
{
}
public CDOCommitInfo getBase()
{
return base != null ? base.get() : null;
}
public void setBase(CDOCommitInfo base)
{
this.base = new SoftReference<CDOCommitInfo>(base);
}
public CDOCommitInfo getFirst()
{
return first != null ? first.get() : null;
}
public void setFirst(CDOCommitInfo first)
{
this.first = new SoftReference<CDOCommitInfo>(first);
}
public CDOCommitInfo getLast()
{
return last != null ? last.get() : null;
}
public void setLast(CDOCommitInfo last)
{
this.last = new SoftReference<CDOCommitInfo>(last);
}
}
}