blob: 65f35229231d03be6775c6cde47ed5866f764088 [file] [log] [blame]
/*
* Copyright (c) 2010-2012, 2014, 2016 Eike Stepper (Berlin, Germany) and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Eike Stepper - initial API and implementation
*/
package org.eclipse.emf.cdo.internal.net4j.protocol;
import org.eclipse.emf.cdo.common.branch.CDOBranchPoint;
import org.eclipse.emf.cdo.common.id.CDOID;
import org.eclipse.emf.cdo.common.id.CDOIDUtil;
import org.eclipse.emf.cdo.common.protocol.CDODataInput;
import org.eclipse.emf.cdo.common.protocol.CDODataOutput;
import org.eclipse.emf.cdo.common.protocol.CDOProtocolConstants;
import org.eclipse.emf.cdo.common.revision.CDORevision;
import org.eclipse.emf.cdo.common.revision.CDORevisionKey;
import org.eclipse.emf.cdo.spi.common.branch.CDOBranchUtil;
import org.eclipse.emf.cdo.spi.common.commit.CDORevisionAvailabilityInfo;
import org.eclipse.net4j.util.om.monitor.OMMonitor;
import org.eclipse.emf.spi.cdo.CDOSessionProtocol.MergeDataResult;
import java.io.IOException;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
/**
* @author Eike Stepper
*/
public class LoadMergeDataRequest extends CDOClientRequestWithMonitoring<MergeDataResult>
{
private CDORevisionAvailabilityInfo targetInfo;
private CDORevisionAvailabilityInfo sourceInfo;
private CDORevisionAvailabilityInfo targetBaseInfo;
private CDORevisionAvailabilityInfo sourceBaseInfo;
private int infos;
private boolean auto;
public LoadMergeDataRequest(CDOClientProtocol protocol, CDORevisionAvailabilityInfo targetInfo,
CDORevisionAvailabilityInfo sourceInfo, CDORevisionAvailabilityInfo targetBaseInfo,
CDORevisionAvailabilityInfo sourceBaseInfo)
{
super(protocol, CDOProtocolConstants.SIGNAL_LOAD_MERGE_DATA);
this.targetInfo = targetInfo;
this.sourceInfo = sourceInfo;
this.targetBaseInfo = targetBaseInfo;
this.sourceBaseInfo = sourceBaseInfo;
infos = 2 + (targetBaseInfo != null ? 1 : 0) + (sourceBaseInfo != null ? 1 : 0);
}
@Override
protected void requesting(CDODataOutput out, OMMonitor monitor) throws IOException
{
out.writeInt(infos);
monitor.begin(infos);
try
{
writeRevisionAvailabilityInfo(out, targetInfo, monitor.fork());
writeRevisionAvailabilityInfo(out, sourceInfo, monitor.fork());
if (infos > 2)
{
writeRevisionAvailabilityInfo(out, targetBaseInfo, monitor.fork());
}
if (infos > 3)
{
writeRevisionAvailabilityInfo(out, sourceBaseInfo, monitor.fork());
}
}
finally
{
monitor.done();
}
}
private void writeRevisionAvailabilityInfo(CDODataOutput out, CDORevisionAvailabilityInfo info, OMMonitor monitor)
throws IOException
{
CDOBranchPoint branchPoint = info.getBranchPoint();
if (branchPoint != CDOBranchUtil.AUTO_BRANCH_POINT)
{
out.writeBoolean(true);
Set<CDOID> availableRevisions = info.getAvailableRevisions().keySet();
int size = availableRevisions.size();
out.writeCDOBranchPoint(branchPoint);
out.writeInt(size);
monitor.begin(size);
try
{
for (CDOID id : availableRevisions)
{
out.writeCDOID(id);
monitor.worked();
}
}
finally
{
monitor.done();
}
}
else
{
out.writeBoolean(false);
auto = true;
}
}
@Override
protected MergeDataResult confirming(CDODataInput in, OMMonitor monitor) throws IOException
{
MergeDataResult result = new MergeDataResult();
monitor.begin(1 + infos);
try
{
// Read IDs of objects that are changed only in target.
for (;;)
{
CDOID id = in.readCDOID();
if (CDOIDUtil.isNull(id))
{
break;
}
result.getTargetIDs().add(id);
}
// Read IDs of objects that are changed in both target and source.
for (;;)
{
CDOID id = in.readCDOID();
if (CDOIDUtil.isNull(id))
{
break;
}
result.getTargetIDs().add(id);
result.getSourceIDs().add(id);
}
// Read IDs of objects that are changed only in source.
for (;;)
{
CDOID id = in.readCDOID();
if (CDOIDUtil.isNull(id))
{
break;
}
result.getSourceIDs().add(id);
}
monitor.worked();
if (auto)
{
targetBaseInfo.setBranchPoint(in.readCDOBranchPoint());
if (in.readBoolean())
{
sourceBaseInfo.setBranchPoint(in.readCDOBranchPoint());
}
else
{
sourceBaseInfo.setBranchPoint(targetBaseInfo.getBranchPoint());
infos = 3;
}
}
readRevisionAvailabilityInfo(in, targetInfo, result.getTargetIDs(), monitor.fork());
readRevisionAvailabilityInfo(in, sourceInfo, result.getSourceIDs(), monitor.fork());
if (infos > 2)
{
readRevisionAvailabilityInfo(in, targetBaseInfo, result.getTargetIDs(), monitor.fork());
}
if (infos > 3)
{
readRevisionAvailabilityInfo(in, sourceBaseInfo, result.getSourceIDs(), monitor.fork());
}
result.setResultBase(CDOBranchUtil.readBranchPointOrNull(in));
return result;
}
finally
{
monitor.done();
}
}
private void readRevisionAvailabilityInfo(CDODataInput in, CDORevisionAvailabilityInfo info, Set<CDOID> result,
OMMonitor monitor) throws IOException
{
int size = in.readInt();
monitor.begin(size + 1);
try
{
for (int i = 0; i < size; i++)
{
CDORevision revision;
if (in.readBoolean())
{
revision = in.readCDORevision();
}
else
{
CDORevisionKey key = in.readCDORevisionKey();
revision = getRevision(key, targetInfo);
if (revision == null && sourceInfo != null)
{
revision = getRevision(key, sourceInfo);
}
if (revision == null && targetBaseInfo != null)
{
revision = getRevision(key, targetBaseInfo);
}
if (revision == null)
{
throw new IllegalStateException("Missing revision: " + key);
}
}
info.addRevision(revision);
monitor.worked();
}
Set<Map.Entry<CDOID, CDORevisionKey>> entrySet = info.getAvailableRevisions().entrySet();
for (Iterator<Map.Entry<CDOID, CDORevisionKey>> it = entrySet.iterator(); it.hasNext();)
{
Map.Entry<CDOID, CDORevisionKey> entry = it.next();
if (!result.contains(entry.getKey()))
{
it.remove();
}
}
monitor.worked();
}
finally
{
monitor.done();
}
}
private CDORevision getRevision(CDORevisionKey key, CDORevisionAvailabilityInfo info)
{
CDORevisionKey revision = info.getRevision(key.getID());
if (revision instanceof CDORevision)
{
if (key.equals(revision))
{
return (CDORevision)revision;
}
}
return null;
}
}