/** * 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 java.util.ArrayList; import java.util.List; /** * Boundary random logoot strategy that uses list identifiers. * @author urso */ public class BoundaryListStrategy extends RandomLogootStrategy { private final long bound; private final int base; private final long plus; private final long mask; /** * Boundary strategy for logoot list. base can be 8, 16, 32. Boundary = 2^base/2; */ public BoundaryListStrategy(int base) { if (base != 8 && base != 16 && base != 32) { throw new IllegalArgumentException("Illegal base."); } this.base = base; this.mask = (long) Math.pow(2, base) - 1; this.plus = (long) Math.pow(2, base - 1); this.bound = (long) Math.pow(2, base / 2); } /** * Generate N identifier between P and Q; */ @Override public List<ListIdentifier> generateLineIdentifiers(TimestampedDocument doc, ListIdentifier P, ListIdentifier Q, int n) { // assert P.compareTo(Q) < 0; LogootListPosition PP = (LogootListPosition) P; LogootListPosition QP = (LogootListPosition) Q; int index = 0; while (PP.getSafe(index) == QP.getSafe(index)) { ++index; } long interval, d = (long) QP.getSafe(index) - (long) PP.getSafe(index) - 1; if (d >= n) { interval = Math.min(d/n, bound); } else { while (d < n) { ++index; d = (d << base) + (long) QP.getSafe(index) - (long) PP.getSafe(index) + mask; } interval = Math.min(d/n, bound); } ArrayList<ListIdentifier> patch = new ArrayList<ListIdentifier>(); LogootListPosition NP = PP; for (int i = 0; i < n; i++) { NP = plus(index, NP, RandomLogootStrategy.nextLong(interval) + 1, doc.getReplicaNumber(), doc.nextClock()); patch.add(NP); } return patch; } private LogootListPosition plus(int index, LogootListPosition PP, long l, int replicaNumber, int clock) { LogootListPosition NP = new LogootListPosition(base, index + 1, replicaNumber, clock); while (l > 0) { long val = l + PP.getSafe(index); NP.set(index, (int) (val & mask)); l = (val + plus) >> base; --index; } while (index >= 0) { NP.set(index, PP.getSafe(index)); --index; } return NP; } @Override public ListIdentifier begin() { return new LogootListPosition(base, (int) (-plus)); } @Override public ListIdentifier end() { return new LogootListPosition(base, (int) (plus - 1)); } }