/**
* 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.abt;
import java.util.Formatter;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
import java.util.NoSuchElementException;
import collect.VectorClock.Causality;
import jbenchmarker.core.SequenceOperation.OpType;
/**
*
* @author Roh
*/
public class ABTLog {
protected List<ABTOperation> Hi = new LinkedList<ABTOperation>();
protected List<ABTOperation> Hd = new LinkedList<ABTOperation>();
private int sid;
public ABTLog(int sid){
this.sid = sid;
}
public ABTOperation updateHR(final ABTOperation op){
ABTOperation o1 = null;
ABTOperation o2 = null;
List<ABTOperation> hih = new LinkedList<ABTOperation>();
List<ABTOperation> hic = new LinkedList<ABTOperation>();
convert2HC(op, Hi, hih, hic);
o2 = ITSQ(op, hic);
o1 = ITSQ(o2, Hd);
if(o1==null){
// do nothing
} else if(o1.getType()==OpType.delete){
Hd.add(o1);
} else if(o1.getType()==OpType.insert){
ListIterator<ABTOperation> li = Hd.listIterator();
ABTOperation ox = (ABTOperation)o2.clone();
ABTOperation oy = (ABTOperation)o2.clone();
ABTOperation oz = null;
while(li.hasNext()){
oz = li.next();
oy.pos = ox.pos;
IT(ox,oz);
IT(oz,oy);
}
Hi.add(o2);
}
return o1;
}
public ABTOperation updateHL(final ABTOperation op){
ABTOperation tmp = (ABTOperation)op.clone();
LinkedList<ABTOperation> sHd = new LinkedList<ABTOperation>();
ListIterator<ABTOperation> liHd = Hd.listIterator(Hd.size());
while(liHd.hasPrevious()){
if(op.getType()==OpType.insert){
ABTOperation top=(ABTOperation)liHd.previous().clone();
swap(tmp, top, true);
sHd.addFirst(top);
} else {
swap(tmp, (ABTOperation)liHd.previous(), false);
}
}
if(op.getType()==OpType.delete){
Hd.add(op);
} else if(op.getType()==OpType.insert){
Hi.add(tmp);
Hd = sHd;
}
return tmp;
}
private static void convert2HC(ABTOperation op1, List<ABTOperation> H, List<ABTOperation> hh, List<ABTOperation> hc){
ListIterator<ABTOperation> li = H.listIterator();
ABTOperation op2 = null;
while(li.hasNext()){
op2 = li.next();
switch(ABTOperation.getRelation(op1, op2)){
case CO:
hc.add(op2);
break;
case HA:
ListIterator<ABTOperation> lihc=hc.listIterator(hc.size());
while(lihc.hasPrevious()){
swap(op2,lihc.previous(), true);
}
hh.add(op2);
break;
case HB:
throw new RuntimeException(op1.getReplica()+":"+op1.vc+" "+op1.getReplica()+":"+op2.vc+": Causality violation");
}
}
}
private static void swap(ABTOperation o1, ABTOperation op2, boolean realswap){
ABTOperation o2;
if(!realswap) o2=(ABTOperation)op2.clone();
else o2=op2;
int pos1=(o1.getType()==OpType.insert?o1.pos:o1.pos-1);
int pos2=(o2.getType()==OpType.insert?o2.pos:o2.pos-1);
if(pos1 > pos2){
if(o2.getType()==OpType.insert) {
o1.pos = o1.pos - 1;
} else if(o2.getType()==OpType.delete){
o1.pos = o1.pos + 1;
}
} else if(pos1 == pos2){
if(o2.getType()==OpType.delete &&
o1.getType()==OpType.delete){
o1.pos = o1.pos+1;
} else if(o1.getType()==OpType.delete &&
o2.getType()==OpType.insert){
throw new RuntimeException("Not admissible swap");
} else if(o1.getType()==OpType.insert &&
o2.getType()==OpType.insert){
o2.pos = o2.pos + 1;
} else { // o1 = ins, op2=del
o2.pos = o2.pos +1;
}
} else { // o1.pos < op2.pos
if(o1.getType()==OpType.insert){
o2.pos = o2.pos + 1;
} else { //o1=del
o2.pos = o2.pos - 1;
}
}
}
private ABTOperation IT(ABTOperation o1, final ABTOperation o2){
int pos1=(o1.getType()==OpType.insert?o1.pos:o1.pos-1);
int pos2=(o2.getType()==OpType.insert?o2.pos:o2.pos-1);
if(pos2 < pos1){
if(o2.getType()==OpType.insert){
o1.pos = o1.pos + 1;
} else if(o2.getType()==OpType.delete){
o1.pos = o1.pos - 1;
}
} else if(pos2 == pos1){
if(o2.getType()==OpType.insert &&
o1.getType()==OpType.delete){
o1.pos = o1.pos + 1;
} else if(o2.getType()==OpType.insert &&
o1.getType()==OpType.insert &&
o2.getReplica() < o1.getReplica()){
o1.pos = o1.pos + 1;
} else if(o2.getType()==OpType.delete &&
o1.getType()==OpType.delete){
o1=null;
}
}
return o1;
}
//unproven code
private ABTOperation ET(ABTOperation o1, ABTOperation o2){
ABTOperation op = (ABTOperation)o1.clone();
if(o2.pos < o1.pos){
if(o2.getType()==OpType.insert){
op.pos = op.pos - 1;
} else if(o2.getType()==OpType.delete){
op.pos = op.pos + 1;
}
} else if(o2.pos == o1.pos){
if(o2.getType()==OpType.delete &&
o1.getType()==OpType.delete){
} else if(o1.getType()==OpType.delete &&
o2.getType()==OpType.insert){
throw new RuntimeException("Not admissible transformation");
}
}
return op;
}
private ABTOperation ITSQ(final ABTOperation op, final List<ABTOperation> H){
ABTOperation o = (ABTOperation)op.clone();
ListIterator<ABTOperation> li = H.listIterator();
while(li.hasNext()){
o=IT(o, li.next());
if(o==null) {
return o;
}
}
return o;
}
public void printHistory(List<ABTOperation> H){
for(int i=H.size();i>0;i--){
Formatter fmt = new Formatter();
fmt.format("%4d", i);
System.out.print("|"+fmt+":"+H.get(i-1)+"\t| ");
System.out.println("\t"+H.get(i-1).getReplica()+":"+H.get(i-1).vc+" ");
}
if(H.size()>0) System.out.println("+-----------------------+");
}
public void printHistory(){
int i=0;
int max=Hi.size()>Hd.size()? Hi.size() : Hd.size();
for(i=max;i>0;i--){
Formatter fmt = new Formatter();
fmt.format("%4d", i);
if(i<=Hi.size()) System.out.print("|"+fmt+":"+Hi.get(i-1)+"\t| ");
else System.out.print("|\t\t\t| ");
if(i<=Hd.size()) System.out.print("|"+fmt+":"+Hd.get(i-1)+"\t|");
else System.out.print("|\t\t\t|");
if(i<=Hi.size()) System.out.print("\t"+Hi.get(i-1).getReplica()+":"+Hi.get(i-1).vc+" ");
else System.out.print("\t\t\t");
if(i<=Hd.size()) System.out.print("\t"+Hd.get(i-1).getReplica()+":"+Hd.get(i-1).vc);
System.out.println("");
}
System.out.println("+-----------------------+ +---------------------+");
System.out.println(" Hi("+Hi.size()+") of site "+sid+" "+" Hd("+Hd.size()+") of site "+sid);
}
}