/** * 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.core; import crdt.*; import crdt.simulator.IncorrectTraceException; import java.io.Serializable; import java.util.ArrayList; import java.util.List; import jbenchmarker.core.SequenceOperation.OpType; /** * Squeleton of mergeAlgorithm * * @author urso */ public abstract class MergeAlgorithm extends CRDT<String> implements Serializable { private static final boolean DEBUG = false; // Supported Document final private Document doc; final private List<String> states = new ArrayList<String>(1); /* private void applyOneRemote(CommutativeMessage mess){ }*/ /* * Constructor */ /** * * @param doc Document of this merge algorithm * @param siteId SiteID or replicat number */ public MergeAlgorithm(Document doc, int siteId) { this.doc = doc; this.setReplicaNumber(siteId); } public MergeAlgorithm(Document doc) { this.doc = doc; } /** * Integrate remote message from another replicas To be define by the * concrete merge algorithm * * @param message from another replicas * @throws IncorrectTraceException */ protected abstract void integrateRemote(crdt.Operation message) throws IncorrectTraceException; /** * * @return the document */ public Document getDoc() { return doc; } /** * This the mergeAlgorithm return in initial state */ public void reset() { } /** * Old school function need to be refactored in directly CRDT Message * * @param opt Sequence Operation * @return List of message for sequence * @throws IncorrectTraceException */ private List<? extends Operation> oldApplyLocal(SequenceOperation opt) throws IncorrectTraceException { switch (opt.getType()) { case insert: return localInsert(opt); case delete: return localDelete(opt); case replace: return localReplace(opt); case update: return localUpdate(opt); case move: return localMove(opt); case noop: return null; default: return null; //throw new IncorrectTraceException("Unsupported operation : " + opt); } } /** * Integreate local modification of the document. This function to stay * compatible with causal dispatcher localmodification is performed and a * sequence message is transformed to CRDTMessage. * * @param op local operation * @return CRDT message will be sent to another * @throws PreconditionException */ @Override public CRDTMessage applyLocal(LocalOperation op) throws PreconditionException { if (!(op instanceof SequenceOperation)) { throw new PreconditionException("Not a sequenceOperation : " + op); } List<? extends Operation> l = oldApplyLocal((SequenceOperation) op); if (l == null || l.isEmpty()) { return CRDTMessage.emptyMessage; } CRDTMessage m = null; for (Operation n : l) { if (m == null) { m = new OperationBasedOneMessage(n); } else { m = m.concat(new OperationBasedOneMessage(n)); } } if (DEBUG) { states.add(doc.view()); } return m; } final public CRDTMessage insert(int position, String content) throws PreconditionException { return applyLocal(SequenceOperation.insert(position, content)); } final public CRDTMessage remove(int position, int length) throws PreconditionException { return applyLocal(SequenceOperation.delete(position, length)); } /** * integrate remote operations. * * @param msg message generated by another replicas */ /*@Override public void applyRemote(CRDTMessage msg) { ((CommutativeMessage)msg).execute(this); if (DEBUG) states.add(doc.view()); }*/ @Override public void applyOneRemote(CRDTMessage mess) { try { integrateRemote(CRDTMessage2SequenceMessage(mess)); } catch (IncorrectTraceException ex) { throw new IllegalStateException(ex); } } public static Operation CRDTMessage2SequenceMessage(CRDTMessage mess) { return (Operation) ((OperationBasedOneMessage) mess).getOperation(); } /** * return document * * @return */ @Override public String lookup() { return doc.view(); } /** * The defaut behavior of localInsert and localDelete is to call * generateLocal. Either localXXXs or generateLocal should be overrriden. * * @param opt local modification * @return Messages generated by replication algorithm will sent to another * replicas * @throws IncorrectTraceException by default */ abstract protected List<? extends Operation> localInsert(SequenceOperation opt) throws IncorrectTraceException; abstract protected List<? extends Operation> localDelete(SequenceOperation opt) throws IncorrectTraceException; /** * Default behavior of update is to delete and insert */ protected List<? extends Operation> localUpdate(SequenceOperation opt) throws IncorrectTraceException{ return localReplace(opt); } /** * Default behavior of move is to delele plus insert */ protected List<? extends Operation> localMove(SequenceOperation opt) throws IncorrectTraceException { SequenceOperation del = new SequenceOperation(OpType.delete, opt.getPosition(), opt.getContent().size(), null), ins = new SequenceOperation(OpType.insert, opt.getDestination(), 0, opt.getContent()); List lop = localDelete(del); lop.addAll(localInsert(ins)); return lop; } /** * Default behavior of replace is to delele plus insert */ protected List<? extends Operation> localReplace(SequenceOperation opt) throws IncorrectTraceException { List lop = localDelete(opt); lop.addAll(localInsert(opt)); return lop; } /*protected List<Operation> localReplaceCorrecteId(SequenceOperation opt) throws IncorrectTraceException { System.out.println("--- localReplaceCorrecteId ---"); List<Operation> lop = localInsert(opt); int newPos = opt.getPosition()+opt.getContent().size(); opt.setPosition(newPos); lop.addAll(localDelete(opt)); return lop; }*/ }