package se.sics.gvod.ls.video.util;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;
import se.sics.asdistances.ASDistances;
import se.sics.asdistances.PrefixHandler;
import se.sics.gvod.common.Self;
import se.sics.gvod.net.VodAddress;
/**
*
* @author Niklas Wahlén <nwahlen@kth.se>
*/
public class VideoComparator implements Comparator<VodAddress> {
private ASDistances distances;
private Self self;
private Map<VodAddress, PeerStatistics> statistics;
/**
* Internal class for keeping statistics about peers
*/
private class PeerStatistics {
public double health;
public int availablePieces;
public int timeouts;
public long firstSeen;
public long lastSeen;
}
public VideoComparator(Self self) {
this.self = self;
distances = ASDistances.getInstance();
statistics = new HashMap<VodAddress, PeerStatistics>();
}
@Override
public int compare(VodAddress a1, VodAddress a2) {
if (a1 == null && a2 == null) {
return 0;
} else if (a1 == null) {
return 1;
} else if (a2 == null) {
return -1;
}
return compareDistances(a1, a2);
}
public int compareDistances(VodAddress a1, VodAddress a2) {
String ip1 = a1.getIp().getHostAddress();
String ip2 = a2.getIp().getHostAddress();
String selfIp = self.getIp().getHostAddress();
byte d1 = distances.getDistance(selfIp, ip1);
byte d2 = distances.getDistance(selfIp, ip2);
if (d1 < d2) {
return -1;
} else if (d1 > d2) {
return 1;
} else {
int sp1 = PrefixHandler.sharedPrefix(selfIp, ip1);
int sp2 = PrefixHandler.sharedPrefix(selfIp, ip2);
if (sp1 < sp2) {
return -1;
} else if (sp1 > sp2) {
return 1;
} else {
return 0;
}
}
}
public int compareStatistics(VodAddress a1, VodAddress a2) {
int value1 = 0;
int value2 = 0;
int retval = 0;
PeerStatistics stats1 = statistics.get(a1);
PeerStatistics stats2 = statistics.get(a2);
if (stats1.availablePieces > stats2.availablePieces) {
value1++;
} else if (stats1.availablePieces < stats2.availablePieces) {
value2++;
}
if (stats1.lastSeen > stats2.lastSeen) {
value1++;
} else if (stats1.lastSeen < stats2.lastSeen) {
value2++;
}
if (value1 > value2) {
retval = -1;
} else if (value1 < value2) {
retval = 1;
}
return retval;
}
public void addPeer(VodAddress a) {
if (!statistics.containsKey(a)) {
PeerStatistics aStats = new PeerStatistics();
aStats.firstSeen = System.currentTimeMillis();
statistics.put(a, aStats);
}
}
public void incAvailablePieces(VodAddress a) {
if(statistics.containsKey(a)) {
PeerStatistics s = statistics.get(a);
s.availablePieces++;
statistics.put(a, s);
}
}
public void updateLastSeen(VodAddress a) {
if(statistics.containsKey(a)) {
PeerStatistics s = statistics.get(a);
s.lastSeen = System.currentTimeMillis();
statistics.put(a, s);
}
}
public Long getLastSeen(VodAddress a) {
if(statistics.get(a) == null) {
return null;
}
return statistics.get(a).lastSeen;
}
public void incTimeouts(VodAddress a) {
if(statistics.containsKey(a)) {
PeerStatistics s = statistics.get(a);
s.timeouts++;
statistics.put(a, s);
}
}
public void removePeer(VodAddress a) {
statistics.remove(a);
}
public short getDistanceTo(VodAddress a) {
return distances.getDistance(self.getIp().getHostAddress(), a.getIp().getHostAddress());
}
}