package routingtable; import java.util.ArrayList; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; import node.Identifier; public class Bucket { private final static Logger LOGGER = Logger.getLogger(Bucket.class .getName()); private int size; public List entries = new ArrayList(); public Bucket left = null; public Bucket right = null; private int level = 0; public Bucket(int size, int level) { this.level = level; this.size = size; } public void update(BucketEntry entry) { update(this, entry); } private void update(Bucket bucket, BucketEntry newEntry) { if (!bucket.isLeaf()) { if (newEntry.id.isBitSetAt(level)) { update(bucket.right, newEntry); } else { update(bucket.left, newEntry); } } else if (bucket.isLeaf() && bucket.hasSpace()) { if (entries.contains(newEntry)) { // Move to beginning LOGGER.log( Level.FINE, "Node {0} ({1}) already in routing table. Move to end of bucket.", new Object[] { newEntry.id, newEntry.address }); if (entries.size() > 1) { entries.remove(newEntry); entries.add(newEntry); } } else { LOGGER.log(Level.INFO, "Added new node {0} ({1}) to routing table.", new Object[] { newEntry.id, newEntry.address }); entries.add(newEntry); } } else { // TODO: only split if necessary // Leaf, but full -> split Bucket newLeft = new Bucket(size, level + 1); Bucket newRight = new Bucket(size, level + 1); // Add the new entry and in the following loop distribute all // existing entries to left/right entries.add(newEntry); for (BucketEntry entry : entries) { if (entry.id.isBitSetAt(level)) { newLeft.entries .add(new BucketEntry(entry.id, entry.address)); } else { newRight.entries .add(new BucketEntry(entry.id, entry.address)); } } bucket.entries = null; bucket.left = newLeft; bucket.right = newRight; } } public boolean hasNode(Identifier id) { return hasNode(this, id); } private boolean hasNode(Bucket bucket, Identifier idToFind) { if (bucket.isLeaf()) { for (BucketEntry entry : bucket.entries) { if (entry.id.equals(idToFind)) { return true; } } return false; } else { if (idToFind.isBitSetAt(level)) { return bucket.hasNode(bucket.left, idToFind); } else { return bucket.hasNode(bucket.right, idToFind); } } } private boolean isLeaf() { return left == null && right == null; } private boolean hasSpace() { return entries.size() < size; } public List getClosestNodesTo(Identifier id) { List result = new ArrayList(); // TODO return result; } }