package se.sics.gvod.ls.interas; import java.util.*; import se.sics.gvod.common.Self; import se.sics.gvod.common.VodDescriptor; import se.sics.gvod.net.VodAddress; /** * * @author Niklas Wahlén <nwahlen@kth.se> */ public class InterAsNeighbours { private Self self; private int maxSize; private TreeSet<VodDescriptor> neighboursTreeSet; private ArrayList<VodDescriptor> neighboursArrayList; private int type; private InterAsComparator comparator; public static final int TREE_SET = 1; public static final int ARRAY_LIST = 2; public InterAsNeighbours(Self self, int maxSize, int type) { this.self = self; this.maxSize = maxSize; this.type = type; this.comparator = new InterAsComparator(self.getDescriptor()); switch (type) { case TREE_SET: neighboursTreeSet = new TreeSet<VodDescriptor>(comparator); break; case ARRAY_LIST: neighboursArrayList = new ArrayList<VodDescriptor>(); break; default: // ... break; } } public void add(VodDescriptor d) { if (d.getVodAddress().getId() != self.getId()) { switch (type) { case TREE_SET: addToTreeSet(d); break; case ARRAY_LIST: addToArrayList(d); break; default: // ... break; } } } public void addToTreeSet(VodDescriptor d) { if (((neighboursTreeSet.size() < maxSize) || (neighboursTreeSet.comparator().compare(d, neighboursTreeSet.last()) > 0))) { if (neighboursTreeSet.add(d)) { if (neighboursTreeSet.size() > maxSize) { // Since the set is sorted (TreeSet) we remove the // "worst" neighbour after adding a new node neighboursTreeSet.remove(neighboursTreeSet.last()); // It would also be possible to compare the node to be // added with the worst node to see which should be kept } } else { // TODO: compare ages? (if we are here the entry already exists) } } } public void addToArrayList(VodDescriptor d) { boolean add = true; for (VodDescriptor d1 : neighboursArrayList) { if (d.getVodAddress().getId() == d1.getVodAddress().getId()) { add = false; } } if (add) { if (neighboursArrayList.size() < maxSize) { neighboursArrayList.add(d); } else { Collections.sort(neighboursArrayList, comparator); if (comparator.compare(d, neighboursArrayList.get(0)) > 0) { neighboursArrayList.remove(0); neighboursArrayList.add(d); } } } } public void addAll(Collection<VodDescriptor> ds) { for (VodDescriptor d : ds) { if (d.getVodAddress().getId() != self.getId()) { this.add(d); } } return; // switch (type) { // case TREE_SET: // neighboursTreeSet.addAll(ds); // break; // case ARRAY_LIST: // neighboursArrayList.addAll(ds); // break; // default: // break; // } } public void remove(VodDescriptor d) { switch (type) { case TREE_SET: neighboursTreeSet.remove(d); case ARRAY_LIST: neighboursArrayList.remove(d); default: throw new RuntimeException("Unknown storage type specified"); } } public boolean isEmpty() { switch (type) { case TREE_SET: return neighboursTreeSet.isEmpty(); case ARRAY_LIST: return neighboursArrayList.isEmpty(); default: throw new RuntimeException("Unknown storage type specified"); } } public int size() { switch (type) { case TREE_SET: return neighboursTreeSet.size(); case ARRAY_LIST: return neighboursArrayList.size(); default: throw new RuntimeException("Unknown storage type specified"); } } public VodDescriptor getBestNeighbour() { switch (type) { case TREE_SET: return neighboursTreeSet.first(); case ARRAY_LIST: Collections.sort(neighboursArrayList, comparator); return neighboursArrayList.get(neighboursArrayList.size() - 1); default: throw new RuntimeException("Unknown storage type specified"); } } public VodDescriptor getDescriptorFromAddress(VodAddress a) { for (VodDescriptor d1 : this.getAsCollection()) { if (d1.getVodAddress().getId() == a.getId()) { return d1; } } return null; } public Collection<VodDescriptor> getAsCollection() { switch (type) { case TREE_SET: return neighboursTreeSet; case ARRAY_LIST: return neighboursArrayList; default: throw new RuntimeException("Unknown storage type specified"); } } public void punish(int id) { comparator.punish(id); } public void decreasePenalites() { comparator.decreasePenalties(); } public int getType() { return type; } }