/** * 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 crdt.set.lastwriterwins; import crdt.CRDTMessage; import crdt.PreconditionException; import crdt.set.CRDTSet; import crdt.set.ConvergentSet; import java.util.*; /** * * @author score */ public class ConvergentLwwSet<T> extends ConvergentSet<T> { private HashMap<T, Integer> mapA; //add element private HashMap<T, Integer> mapR; //for removing elements HashSet<T> lookup; public ConvergentLwwSet() { this.mapA = new HashMap<T, Integer>(); this.mapR = new HashMap<T, Integer>(); lookup = new HashSet(); } @Override public Set lookup() { return lookup; } @Override public void applyOneRemote(CRDTMessage stat) { ConvergentLwwSet lSC = (ConvergentLwwSet) stat; HashMap<T, Integer> statA = lSC.getMapA(); HashMap<T, Integer> statR = lSC.getMapR(); boolean before,after; for (T t : statA.keySet()) { before = lookup.contains(t); if (mapA.get(t) == null || (mapA.get(t) != null && statA.get(t) > mapA.get(t))) { mapA.put(t, statA.get(t)); } if (statR.containsKey(t) && (mapR.get(t) == null || statR.get(t) > mapR.get(t))) { mapR.put(t, statR.get(t)); } //element does not exist in mapR or existe in mapR but counter in mapA is the biggest if (!mapR.keySet().contains(t) || (mapR.keySet().contains(t) && mapA.get(t) > mapR.get(t))) { lookup.add(t); } //element exist in mapR and his counter in mapR is greater thant in mapA if (mapR.keySet().contains(t) && mapR.get(t) >= mapA.get(t)) { lookup.remove(t); } after = lookup.contains(t); if (!before && after) { notifyAdd(t); } if (before && !after) { notifyDel(t); } } } public HashMap getMapA() { return mapA; } public void setMapA(HashMap<T, Integer> t) { mapA.clear(); mapA = t; } public HashMap getMapR() { return mapR; } public void setMapR(HashMap<T, Integer> t) { mapR.clear(); mapR = t; } @Override public ConvergentLwwSet<T> innerAdd(T t) { int time=0; if (mapA.containsKey(t)) { time= mapA.get(t); } mapA.put(t,time + 1); lookup.add(t); return this; } @Override public ConvergentLwwSet<T> innerRemove(T t) throws PreconditionException { int time=0; if (mapR.containsKey(t)) { time= mapR.get(t); } mapR.put(t,time + 1); //LwwOperation newOp = new LwwOperation(SetOperation.OpType.del, t, 0); lookup.remove(t); return this; } @Override public boolean contains(T t) { return(this.lookup().contains(t)); } @Override public CRDTSet<T> create() { return new ConvergentLwwSet(); } @Override public ConvergentLwwSet<T> clone() { ConvergentLwwSet<T> clone = new ConvergentLwwSet<T>(); clone.mapA = (HashMap<T, Integer>) this.mapA.clone(); clone.mapR = (HashMap<T, Integer>) this.mapR.clone(); clone.lookup = (HashSet<T>) this.lookup.clone(); return clone; } }