/** * 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.soct2; import collect.VectorClock; import crdt.Factory; import java.io.Serializable; import java.util.Map; import crdt.Operation; /** * * @param <O> Is type of operation managed in this algorithm * @author Stephane Martin * Algorithm SOCT2 With document, Log with transformations, and an vector clock. */ public class SOCT2 <O extends Operation> implements OTAlgorithm<O>, Serializable { final private VectorClock siteVC; final private SOCT2Log<O> log; //private Document doc; private int replicaNumber; final private GarbageCollector gc; /** * Make soct2 instance. */ public SOCT2(int siteId, Factory<SOCT2Log<O>> log, Factory<GarbageCollector> gc) { this.siteVC = new VectorClock(); this.log = log.create(); this.replicaNumber = siteId; this.gc = gc == null ? null : gc.create(); } /** * Make soct2 instance. */ public SOCT2(SOCT2TranformationInterface ot, int siteId, Factory<GarbageCollector> gc) { this(siteId, new SOCT2Log<O>(ot), gc); } /** * Make soct2 instance. */ public SOCT2(SOCT2TranformationInterface ot, Factory<GarbageCollector> gc) { this(ot, 0, gc); } /** * Make soct2 instance. */ public SOCT2(SOCT2TranformationInterface ot) { this(ot, 0, null); } /** * Make soct2 instance. */ public SOCT2(Factory<SOCT2Log<O>> log, Factory<GarbageCollector> gc) { this(0, log, gc); } /** * * @return the vector clock of the instance */ @Override public VectorClock getSiteVC() { return siteVC; } /** * @return return log object */ @Override public SOCT2Log getLog() { return log; } /** * Check if the operation is ready by its vector clock * @param siteId Site of operation * @param vcOp Vector clock of this operation. * @return true if its ready false else. */ @Override public boolean readyFor(int siteId, VectorClock vcOp) { //if (this.siteVC.getSafe(siteId) != vcOp.getSafe(siteId)) { Garbage collection if (this.siteVC.getSafe(siteId)+1 != vcOp.getSafe(siteId)) { return false; } for (Map.Entry<Integer, Integer> e : vcOp.entrySet()) { if ((e.getKey() != siteId) && (this.siteVC.getSafe(e.getKey()) < e.getValue())) { return false; } } return true; } /** * This method put on operation the vector clock, increse the vector clock * the operation is not applyed * @param op The operation * @return Soct2Message with vector clock. */ @Override public OTMessage estampileMessage(Operation op) { this.siteVC.inc(this.replicaNumber); OTMessage ret = new OTMessage(new VectorClock(siteVC), replicaNumber, op); //this.siteVC.inc(this.siteId); For garbage collection this.log.add(ret); //doc.apply((Operation)op); if (gc != null) { this.gc.garbage(this); //Garbage collector } return ret; } /** * Integre operation sent by another site or replicats. * The operation is returned to apply on document * @param soct2message Is a message which contains the operation and vector clock * @return operation to performe on document */ @Override public O integrateRemote(OTMessage soct2message) { if (this.readyFor(soct2message.getSiteId(), soct2message.getClock())) { if (gc != null) { this.gc.collect(this, soct2message); //Garbage collector } Operation op = this.log.merge(soct2message); if (gc != null) { this.gc.garbage(this); //Garbage collector } this.siteVC.inc(soct2message.getSiteId()); return (O)op; } else { throw new RuntimeException("it seems causal reception is broken in " + this.replicaNumber + " v: " + siteVC + " vs " + soct2message.getClock() + " from " + soct2message.getSiteId()); } } @Override public void setReplicaNumber(int siteId) { this.replicaNumber = siteId; } @Override public OTAlgorithm<O> create() { return new SOCT2<O>(log, gc); } @Override public int getReplicaNumber() { return replicaNumber; } @Override public SOCT2TranformationInterface<O> getTransformation() { return log.transforme; } }