/** * Replication Benchmarker * https://github.com/score-team/replication-benchmarker/ Copyright (C) 2013 * LORIA / Inria / SCORE Team * * This program is free software: you can redistribute it and/or modify it under * the terms of the GNU General Public License as published by the Free Software * Foundation, either version 3 of the License, or (at your option) any later * version. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see <http://www.gnu.org/licenses/>. */ package jbenchmarker.ot.ttf; import collect.VectorClock; import crdt.CRDT; import crdt.Factory; import crdt.Operation; import crdt.simulator.IncorrectTraceException; import java.util.ArrayList; import java.util.List; import jbenchmarker.core.*; import jbenchmarker.ot.soct2.OTAlgorithm; import jbenchmarker.ot.soct2.OTMessage; import jbenchmarker.ot.soct2.OTReplica; import jbenchmarker.ot.soct2.SOCT2; import jbenchmarker.ot.soct2.SOCT2TranformationInterface; /** * This TTF Merge Algorithm uses SOCT2 algorithm with TTF method * * @author oster urso */ public class TTFMergeAlgorithm<O extends TTFOperation> extends MergeAlgorithm implements OTReplica<String, O> { final private OTAlgorithm<O> otAlgo; public OTAlgorithm<O> getOtAlgo() { return otAlgo; } /** * Make new TTFMerge algorithm with docuement (TTFDocument) and site id or * replicat id. * * @param doc TTF Document * @param siteId SiteID */ public TTFMergeAlgorithm(TTFDocument doc, int siteId, Factory<OTAlgorithm<O>> otAlgo) { super(doc); this.otAlgo = otAlgo.create(); setReplicaNumber(siteId); } /** * Default SOCT2 Factory * */ public TTFMergeAlgorithm(int siteId) { this(new TTFDocument(), siteId, new SOCT2<O>(new TTFTransformations(), siteId, null)); setReplicaNumber(siteId); } public TTFMergeAlgorithm(Factory<OTAlgorithm<O>> otAlgo) { this(new TTFDocument(), 0, otAlgo); } @Override public TTFDocument getDoc() { return (TTFDocument) super.getDoc(); //To change body of generated methods, choose Tools | Templates. } /** * @return Vector Clock of site */ public VectorClock getClock() { return otAlgo.getSiteVC(); } protected TTFOperation deleteOperation(int pos) { return new TTFOperationWithId(SequenceOperation.OpType.delete, pos, null, getReplicaNumber()); } protected TTFOperation insertOperation(int pos, Object content) { return new TTFOperationWithId(SequenceOperation.OpType.insert, pos, content, getReplicaNumber()); } /* * This integrate local modifications and generate message to another * replicas */ @Override protected List<Operation> localDelete(SequenceOperation opt) throws IncorrectTraceException { TTFDocument doc = this.getDoc(); List<Operation> generatedOperations = new ArrayList<Operation>(); int mpos = doc.viewToModel(opt.getPosition()); int visibleIndex = 0; for (int i = 0; i < opt.getLenghOfADel(); i++) { // TODO: could be improved with an iterator on only visible characters while (!doc.getChar(mpos + visibleIndex).isVisible()) { visibleIndex++; } Operation op = deleteOperation(mpos + visibleIndex); generatedOperations.add(new TTFSequenceMessage(otAlgo.estampileMessage(op))); doc.apply(op); } return generatedOperations; } @Override protected List<Operation> localInsert(SequenceOperation opt) throws IncorrectTraceException { TTFDocument doc = this.getDoc(); List<Operation> generatedOperations = new ArrayList<Operation>(); int mpos = doc.viewToModel(opt.getPosition()); for (int i = 0; i < opt.getContent().size(); i++) { TTFOperation op = insertOperation(mpos, opt.getContent().get(i)); mpos = op.getPosition() + 1; generatedOperations.add(new TTFSequenceMessage(otAlgo.estampileMessage(op))); doc.apply(op); } return generatedOperations; } /** * Make a new mergeAlgorithm with 0 as site id. * * @return new TTFMergeAlgorithm */ @Override public CRDT<String> create() { return new TTFMergeAlgorithm(new TTFDocument(), 0, otAlgo); } /* * IntegrateRemote Operation */ @Override protected void integrateRemote(crdt.Operation message) throws IncorrectTraceException { integrateOneOperation(((TTFSequenceMessage) message).getSoct2Message()); } private void integrateOneOperation(OTMessage mess) { Operation op = otAlgo.integrateRemote(mess); //======================================================= computation(); if (((TTFOperation) op).getType() == SequenceOperation.OpType.noop) { nbrCleanMerge++; } //======================================================= this.getDoc().apply(op); } private void computation() { this.nbrInsConcur = otAlgo.getLog().nbrInsConcur; this.nbrInsDelConcur = otAlgo.getLog().nbrInsDelConcur; this.nbrDelDelConcur = otAlgo.getLog().nbrDelDelConcur; } @Override public void setReplicaNumber(int replicaNumber) { super.setReplicaNumber(replicaNumber); otAlgo.setReplicaNumber(replicaNumber); } @Override public SOCT2TranformationInterface<O> getTransformation() { return otAlgo.getTransformation(); } }