2012-12-19 09:17:27 +01:00

124 lines
3.3 KiB
Java

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<BucketEntry> entries = new ArrayList<BucketEntry>();
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<BucketEntry> getClosestNodesTo(Identifier id) {
List<BucketEntry> result = new ArrayList<BucketEntry>();
// TODO
return result;
}
}