124 lines
3.3 KiB
Java
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;
|
|
}
|
|
} |