/* * Copyright (c) 2010-2012, 2016 Eike Stepper (Berlin, Germany) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Eike Stepper - initial API and implementation */ package org.eclipse.emf.cdo.server.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.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.common.revision.CDORevisionUtil; import org.eclipse.emf.cdo.spi.common.branch.CDOBranchUtil; import org.eclipse.emf.cdo.spi.common.commit.CDORevisionAvailabilityInfo; import org.eclipse.emf.cdo.spi.server.InternalRepository; import org.eclipse.net4j.util.om.monitor.OMMonitor; import org.eclipse.emf.spi.cdo.CDOSessionProtocol.MergeDataResult; import java.io.IOException; import java.util.Collection; import java.util.HashSet; import java.util.Iterator; import java.util.Set; /** * @author Eike Stepper */ public class LoadMergeDataIndication extends CDOServerReadIndicationWithMonitoring { private CDORevisionAvailabilityInfo targetInfo; private CDORevisionAvailabilityInfo sourceInfo; private CDORevisionAvailabilityInfo targetBaseInfo; private CDORevisionAvailabilityInfo sourceBaseInfo; private int infos; private boolean auto; public LoadMergeDataIndication(CDOServerProtocol protocol) { super(protocol, CDOProtocolConstants.SIGNAL_LOAD_MERGE_DATA); } @Override protected int getIndicatingWorkPercent() { return 10; } @Override protected void indicating(CDODataInput in, OMMonitor monitor) throws Exception { infos = in.readInt(); monitor.begin(infos); try { targetInfo = readRevisionAvailabilityInfo(in, monitor.fork()); sourceInfo = readRevisionAvailabilityInfo(in, monitor.fork()); if (infos > 2) { targetBaseInfo = readRevisionAvailabilityInfo(in, monitor.fork()); } if (infos > 3) { sourceBaseInfo = readRevisionAvailabilityInfo(in, monitor.fork()); } } finally { monitor.done(); } } private CDORevisionAvailabilityInfo readRevisionAvailabilityInfo(CDODataInput in, OMMonitor monitor) throws IOException { if (in.readBoolean()) { CDOBranchPoint branchPoint = in.readCDOBranchPoint(); CDORevisionAvailabilityInfo info = new CDORevisionAvailabilityInfo(branchPoint); int size = in.readInt(); monitor.begin(size); try { for (int i = 0; i < size; i++) { CDOID id = in.readCDOID(); info.getAvailableRevisions().put(id, null); monitor.worked(); } return info; } finally { monitor.done(); } } auto = true; return new CDORevisionAvailabilityInfo(CDOBranchUtil.AUTO_BRANCH_POINT); } @Override protected void responding(CDODataOutput out, OMMonitor monitor) throws Exception { monitor.begin(2 + infos); try { InternalRepository repository = getRepository(); MergeDataResult result = repository.getMergeData2(targetInfo, sourceInfo, targetBaseInfo, sourceBaseInfo, monitor.fork()); Set<CDOID> targetIDs = result.getTargetIDs(); Set<CDOID> targetAndSourceIDs = new HashSet<CDOID>(); Set<CDOID> sourceIDs = result.getSourceIDs(); // Write IDs of objects that are changed only in target. for (CDOID id : targetIDs) { if (sourceIDs.remove(id)) { targetAndSourceIDs.add(id); } else { out.writeCDOID(id); } } out.writeCDOID(null); // Write IDs of objects that are changed in both target and source. for (CDOID id : targetAndSourceIDs) { out.writeCDOID(id); } out.writeCDOID(null); // Write IDs of objects that are changed only in source. for (CDOID id : sourceIDs) { out.writeCDOID(id); } out.writeCDOID(null); monitor.worked(); if (auto) { out.writeCDOBranchPoint(targetBaseInfo.getBranchPoint()); if (targetBaseInfo.getBranchPoint().equals(sourceBaseInfo.getBranchPoint())) { out.writeBoolean(false); infos = 3; } else { out.writeBoolean(true); out.writeCDOBranchPoint(sourceBaseInfo.getBranchPoint()); } } Set<CDORevisionKey> writtenRevisions = new HashSet<CDORevisionKey>(); writeRevisionAvailabilityInfo(out, targetInfo, writtenRevisions, monitor.fork()); writeRevisionAvailabilityInfo(out, sourceInfo, writtenRevisions, monitor.fork()); if (infos > 2) { writeRevisionAvailabilityInfo(out, targetBaseInfo, writtenRevisions, monitor.fork()); } if (infos > 3) { writeRevisionAvailabilityInfo(out, sourceBaseInfo, writtenRevisions, monitor.fork()); } CDOBranchUtil.writeBranchPointOrNull(out, result.getResultBase()); } finally { monitor.done(); } } private void writeRevisionAvailabilityInfo(final CDODataOutput out, CDORevisionAvailabilityInfo info, Set<CDORevisionKey> writtenRevisions, OMMonitor monitor) throws IOException { Collection<CDORevisionKey> revisions = info.getAvailableRevisions().values(); for (Iterator<CDORevisionKey> it = revisions.iterator(); it.hasNext();) { CDORevisionKey key = it.next(); if (key == null) { it.remove(); } } int size = revisions.size(); out.writeInt(size); monitor.begin(size); try { for (CDORevisionKey revision : revisions) { CDORevisionKey key = CDORevisionUtil.copyRevisionKey(revision); if (writtenRevisions.add(key)) { out.writeBoolean(true); out.writeCDORevision((CDORevision)revision, CDORevision.UNCHUNKED); // Exposes revision to client side } else { out.writeBoolean(false); out.writeCDORevisionKey(key); } monitor.worked(); } } finally { monitor.done(); } } }