package edu.berkeley.lipstick.util;
import java.io.Serializable;
import java.util.HashSet;
import java.util.concurrent.ConcurrentHashMap;
import java.util.Iterator;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
public class WriteClock implements Serializable {
ConcurrentHashMap<String, AtomicLong> clock;
public static int IS_EQUAL = -1;
public static int HAPPENS_BEFORE = -2;
public static int HAPPENS_AFTER = -3;
public static int IS_CONCURRENT = -4;
public WriteClock() {
clock = new ConcurrentHashMap<String, AtomicLong>();
}
public WriteClock(WriteClock wc) {
if(wc != null) {
clock = new ConcurrentHashMap<String, AtomicLong>();
for(String key : wc.getWriters())
clock.put(key, new AtomicLong(wc.getValue(key)));
}
else {
clock = new ConcurrentHashMap<String, AtomicLong>();
}
}
public final long getValue(String which) {
if(clock.containsKey(which))
return clock.get(which).get();
else
return 0;
}
public void incrementValue(String which) {
if(! clock.containsKey(which))
clock.put(which, new AtomicLong(1));
else
clock.get(which).incrementAndGet();
}
public void setValue(String which, long value) {
if(clock.get(which) == null)
clock.put(which, new AtomicLong(value));
else
clock.get(which).set(value);
}
public final Set<String> getWriters() {
return clock.keySet();
}
public void mergeClock(WriteClock otherClock) {
Iterator<String> otherIt = otherClock.getWriters().iterator();
while(otherIt.hasNext())
{
String otherWriter = otherIt.next();
if(clock.containsKey(otherWriter)) {
clock.put(otherWriter, new AtomicLong(Math.max(this.getValue(otherWriter), otherClock.getValue(otherWriter))));
}
else
{
clock.put(otherWriter, new AtomicLong(otherClock.getValue(otherWriter)));
}
}
}
public final int compareToClock(WriteClock otherClock) {
boolean earlier = false;
boolean later = false;
Set<String> toCheck = new HashSet<String>();
toCheck.addAll(otherClock.getWriters());
toCheck.addAll(getWriters());
for(String writer : toCheck) {
long ourWrite = getValue(writer);
long theirWrite = otherClock.getValue(writer);
if(ourWrite < theirWrite)
earlier = true;
else if(ourWrite > theirWrite)
later = true;
}
if(earlier && !later)
return HAPPENS_BEFORE;
else if(!earlier && later)
return HAPPENS_AFTER;
else if(earlier && later)
return IS_CONCURRENT;
else
return IS_EQUAL;
}
public final boolean happensBefore(WriteClock otherClock) {
return compareToClock(otherClock) == HAPPENS_BEFORE;
}
public final boolean equals(WriteClock otherClock) {
return compareToClock(otherClock) == IS_EQUAL;
}
}