/** * 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.logoot; import collect.RangeList; import crdt.Factory; import java.util.List; import crdt.Operation; import jbenchmarker.core.SequenceOperation.OpType; /** * A Logoot document. Contains a list of Charater and the corresponding list of LogootIndentitifer. * @author urso mehdi */ public class LogootDocument<T> implements Factory<LogootDocument<T>>, TimestampedDocument { private int myClock; protected int replicaNumber; final protected RangeList<ListIdentifier> idTable; final protected RangeList<T> document; final protected LogootStrategy strategy; public LogootDocument(int r, LogootStrategy strategy) { super(); document = new RangeList<T>(); idTable = new RangeList<ListIdentifier>(); this.strategy = strategy; this.replicaNumber = r; myClock = 0; idTable.add(strategy.begin()); document.add(null); idTable.add(strategy.end()); document.add(null); } @Override public String view() { StringBuilder s = new StringBuilder(); for (int i=1; i< document.size()-1; ++i) { s.append(document.get(i)); } return s.toString(); } protected int dicho(ListIdentifier idToSearch) { int startIndex = 1, endIndex = idTable.size() - 1, middleIndex; while (startIndex < endIndex) { middleIndex = startIndex + (endIndex - startIndex) / 2; int c = idTable.get(middleIndex).compareTo(idToSearch); if (c == 0) { return middleIndex; } else if (c < 0) { startIndex = middleIndex + 1; } else { endIndex = middleIndex; } } return startIndex; } @Override public void apply(Operation op) { LogootOperation lg = (LogootOperation) op; ListIdentifier idToSearch = lg.getPosition(); int pos = dicho(idToSearch); //Insertion et Delete if (lg.getType() == OpType.insert) { idTable.add(pos, idToSearch); document.add(pos, (T) lg.getContent()); } else if (idTable.get(pos).equals(idToSearch)) { idTable.remove(pos); document.remove(pos); } } public void insert(int position, List<ListIdentifier> patch, List<T> lc) { idTable.addAll(position + 1, patch); document.addAll(position + 1, lc); } public void remove(int position, int offset) { idTable.removeRangeOffset(position + 1, offset); document.removeRangeOffset(position + 1, offset); } /** * Get the ith identifier in the table. O means begin marker. */ public ListIdentifier getId(int pos) { return idTable.get(pos); } @Override public int viewLength() { return document.size()-2; } // TODO : duplicate strategy ? @Override public LogootDocument<T> create() { return new LogootDocument<T>(replicaNumber, strategy); } @Override public int nextClock() { return this.myClock++; } void setClock(int c) { this.myClock = c; } public void setReplicaNumber(int replicaNumber) { this.replicaNumber = replicaNumber; } @Override public int getReplicaNumber() { return replicaNumber; } /** * Produce one new identifier after this position. */ public ListIdentifier getNewId(int postion) { return strategy.generateLineIdentifiers(this, idTable.get(postion), idTable.get(postion + 1), 1).get(0); } List<ListIdentifier> generateIdentifiers(int position, int N) { return strategy.generateLineIdentifiers(this, idTable.get(position), idTable.get(position + 1), N); } @Override public boolean equals(Object obj) { if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } final LogootDocument<T> other = (LogootDocument<T>) obj; if (this.idTable != other.idTable && (this.idTable == null || !this.idTable.equals(other.idTable))) { return false; } if (this.document != other.document && (this.document == null || !this.document.equals(other.document))) { return false; } return true; } @Override public int hashCode() { int hash = 7; hash = 97 * hash + (this.idTable != null ? this.idTable.hashCode() : 0); hash = 97 * hash + (this.document != null ? this.document.hashCode() : 0); return hash; } // Test & Debug purpose boolean isSorted() { Comparable p = null; for (Comparable c : this.idTable) { if (p != null) { int comp = p.compareTo(c); if (comp >= 0) { return false; } } p = c; } return true; } }