From cabb5af74239fd188e094aae8a5ef65d339876ff Mon Sep 17 00:00:00 2001 From: Joshua Kissoon Date: Thu, 6 Mar 2014 16:24:50 +0530 Subject: [PATCH] Finish Bucket Refresh Operation :) --- src/kademlia/core/KadServer.java | 4 +- src/kademlia/node/NodeId.java | 34 +++++++++- .../operation/BucketRefreshOperation.java | 36 +++++----- src/kademlia/routing/RoutingTable.java | 67 +++---------------- 4 files changed, 62 insertions(+), 79 deletions(-) diff --git a/src/kademlia/core/KadServer.java b/src/kademlia/core/KadServer.java index 1512d8f..63d78b7 100644 --- a/src/kademlia/core/KadServer.java +++ b/src/kademlia/core/KadServer.java @@ -170,13 +170,13 @@ public class KadServer Message msg = messageFactory.createMessage(messCode, din); din.close(); - System.out.println(this.localNode.getNodeId() + " Message Received: [Comm: " + comm + "] " + msg); + //System.out.println(this.localNode.getNodeId() + " Message Received: [Comm: " + comm + "] " + msg); /* Get a receiver for this message */ Receiver receiver; if (this.receivers.containsKey(comm)) { - System.out.println("Receiver found"); + //System.out.println("Receiver found"); /* If there is a reciever in the receivers to handle this */ synchronized (this) { diff --git a/src/kademlia/node/NodeId.java b/src/kademlia/node/NodeId.java index 27b1920..e3b7582 100644 --- a/src/kademlia/node/NodeId.java +++ b/src/kademlia/node/NodeId.java @@ -10,6 +10,7 @@ import java.io.DataOutputStream; import java.io.IOException; import java.math.BigInteger; import java.util.Arrays; +import java.util.BitSet; import java.util.Random; import kademlia.message.Streamable; @@ -126,14 +127,43 @@ public class NodeId implements Streamable /** * Generates a NodeId that is some distance away from this NodeId * - * @param distance + * @param distance in number of bits * * @return NodeId The newly generated NodeId */ public NodeId generateNodeIdByDistance(int distance) { byte[] result = new byte[ID_LENGTH / 8]; - int emptyBytes = distance / 8; + + /* Since distance = ID_LENGTH - prefixLength, we need to fill that amount with 0's */ + int numByteZeroes = (ID_LENGTH - distance) / 8; + int numBitZeroes = 8 - (distance % 8); + + /* Filling byte zeroes */ + for (int i = 0; i < numByteZeroes; i++) + { + result[i] = 0; + } + + /* Filling bit zeroes */ + BitSet bits = new BitSet(8); + bits.set(0, 8); + + for (int i = 0; i < numBitZeroes; i++) + { + /* Shift 1 zero into the start of the value */ + bits.clear(i); + } + bits.flip(0, 8); // Flip the bits since they're in reverse order + result[numByteZeroes] = (byte) bits.toByteArray()[0]; + + /* Set the remaining bytes to Maximum value */ + for (int i = numByteZeroes + 1; i < result.length; i++) + { + result[i] = Byte.MAX_VALUE; + } + + return this.xor(new NodeId(result)); } /** diff --git a/src/kademlia/operation/BucketRefreshOperation.java b/src/kademlia/operation/BucketRefreshOperation.java index dd401a7..5d9e09e 100644 --- a/src/kademlia/operation/BucketRefreshOperation.java +++ b/src/kademlia/operation/BucketRefreshOperation.java @@ -1,7 +1,6 @@ package kademlia.operation; import java.io.IOException; -import java.util.List; import kademlia.core.KadServer; import kademlia.node.Node; import kademlia.node.NodeId; @@ -25,27 +24,28 @@ public class BucketRefreshOperation implements Operation this.localNode = localNode; } + /** + * Each bucket need to be refreshed at every time interval t. + * Find an identifier in each bucket's range, use it to look for nodes closest to this identifier + * allowing the bucket to be refreshed. + * + * Then Do a NodeLookupOperation for each of the generated NodeIds, + * This will find the K-Closest nodes to that ID, and update the necessary K-Bucket + * + * @throws java.io.IOException + */ @Override public synchronized void execute() throws IOException { - System.out.println("Bucket Refresh Operation Started"); - - /* Get a list of NodeIds for each distance from the LocalNode NodeId */ - List refreshIds = this.localNode.getRoutingTable().getRefreshList(); - - /* Test whether each nodeId in this list is a different distance from our current NID */ - for (NodeId nid : refreshIds) + for (int i = 1; i < NodeId.ID_LENGTH; i++) { - System.out.println(localNode.getNodeId().getDistance(nid)); + /* Construct a NodeId that is i bits away from the current node Id */ + NodeId current = this.localNode.getNodeId().generateNodeIdByDistance(i); + + // System.out.println("Distance: " + localNode.getNodeId().getDistance(current) + " - ID: " + current); + + /* Run the Node Lookup Operation */ + new NodeLookupOperation(this.server, this.localNode, this.localNode.getNodeId()).execute(); } - - /* @todo Do a Node Lookup operation to refresh K-Buckets */ - new NodeLookupOperation(this.server, this.localNode, this.localNode.getNodeId()).execute(); - - /** - * @todo Send data in DHT to closest Nodes if they don't have it - * This is better than asking closest nodes for data, - * since the data may not always come from the closest nodes - */ } } diff --git a/src/kademlia/routing/RoutingTable.java b/src/kademlia/routing/RoutingTable.java index 0f3a8ee..07c8ed9 100644 --- a/src/kademlia/routing/RoutingTable.java +++ b/src/kademlia/routing/RoutingTable.java @@ -13,15 +13,15 @@ import kademlia.node.NodeId; public class RoutingTable { - + private final Node localNode; // The current node private final KadBucket[] buckets; - + { buckets = new KadBucket[NodeId.ID_LENGTH]; // 160 buckets; 1 for each level in the tree } - + public RoutingTable(Node localNode) { this.localNode = localNode; @@ -43,7 +43,7 @@ public class RoutingTable /* bucketId is the distance between these nodes */ int bucketId = this.localNode.getNodeId().getDistance(n.getNodeId()) - 1; - System.out.println(this.localNode.getNodeId() + " Adding Node " + n.getNodeId() + " to bucket at depth: " + bucketId); + //System.out.println(this.localNode.getNodeId() + " Adding Node " + n.getNodeId() + " to bucket at depth: " + bucketId); /* Put this contact to the bucket that stores contacts prefixLength distance away */ this.buckets[bucketId].insert(n); @@ -93,7 +93,7 @@ public class RoutingTable break; } } - + if (closest.size() >= num) { return closest; @@ -140,7 +140,7 @@ public class RoutingTable break; } } - + return closest; } @@ -150,62 +150,15 @@ public class RoutingTable public List getAllNodes() { List nodes = new ArrayList<>(); - + for (KadBucket b : this.buckets) { nodes.addAll(b.getNodes()); } - + return nodes; } - /** - * Each bucket need to be refreshed at every time interval t. - * Here we return an identifier in each bucket's range; - * this identifier will then be used to look for nodes closest to this identifier - * allowing the bucket to be refreshed. - * - * The first bucket containing only the local node is skipped. - * - * @return List A list of NodeIds for each distance (1 - NodeId.ID_LENGTH) from the LocalNode NodeId - */ - public List getRefreshList() - { - List refreshList = new ArrayList<>(NodeId.ID_LENGTH); - - for (int i = 1; i < NodeId.ID_LENGTH; i++) - { - /* Construct a NodeId that is i bits away from the current node Id */ - System.out.println("\nGenerating a new NodeId "); - BitSet bits = new BitSet(160); - - /* Fill the first i parts with 1 */ - for (int j = 0; j < i + 10; j++) - { - bits.set(j); - System.out.println("Got here 1 - j: " + j + "; bits: " + bits); - } - - /* Fill the last parts with 0 */ - for (int j = i; j < NodeId.ID_LENGTH; j++) - { - bits.clear(j); - System.out.println("Got here 2 - j: " + j + "; bits: " + bits); - } - - /** - * LocalNode NodeId xor the Bits we generated will give a new NodeId - * i distance away from our LocalNode NodeId, we add this to our refreshList - */ - System.out.println("Bits: " + bits.toByteArray()); - NodeId nid = this.localNode.getNodeId().xor(new NodeId(bits.toByteArray())); - System.out.println("NodeId: " + nid); - refreshList.add(nid); - } - - return refreshList; - } - @Override public String toString() { @@ -225,8 +178,8 @@ public class RoutingTable } } sb.append("\nPrinting Routing Table Ended ******************** "); - + return sb.toString(); } - + }