mirror of
https://github.com/ChronosX88/KademliaDHT.git
synced 2024-11-21 17:52:21 +00:00
Routing Table Improvement
- Setup the RoutingTable to store contact instead of node - This helps since we'll need more information in the routing to evict contacts, etc
This commit is contained in:
parent
c902ba26ab
commit
21b6667eb8
@ -10,7 +10,7 @@ import java.io.File;
|
||||
public class DefaultConfiguration implements KadConfiguration
|
||||
{
|
||||
|
||||
private final static long RESTORE_INTERVAL = 60 * 1000; // Default at 1 hour
|
||||
private final static long RESTORE_INTERVAL = 10 * 1000; // Default at 1 hour
|
||||
private final static long RESPONSE_TIMEOUT = 1500;
|
||||
private final static long OPERATION_TIMEOUT = 3000;
|
||||
private final static int CONCURRENCY = 10;
|
||||
|
@ -36,7 +36,7 @@ public class KadServer
|
||||
/* Server Objects */
|
||||
private final int udpPort;
|
||||
private final DatagramSocket socket;
|
||||
private boolean isRunning;
|
||||
private transient boolean isRunning;
|
||||
private final Map<Integer, Receiver> receivers;
|
||||
private final Timer timer; // Schedule future tasks
|
||||
private final Map<Integer, TimerTask> tasks; // Keep track of scheduled tasks
|
||||
@ -109,7 +109,7 @@ public class KadServer
|
||||
{
|
||||
if (!isRunning)
|
||||
{
|
||||
throw new IllegalStateException("Kad Server is not running.");
|
||||
throw new IllegalStateException("Kad Server is not running on node " + this.localNode);
|
||||
}
|
||||
|
||||
/* Generate a random communication ID */
|
||||
|
@ -4,7 +4,7 @@ import java.util.List;
|
||||
import kademlia.node.Node;
|
||||
|
||||
/**
|
||||
* A bucket used to store Nodes in the routing table.
|
||||
* A bucket used to store Contacts in the routing table.
|
||||
*
|
||||
* @author Joshua Kissoon
|
||||
* @created 20140215
|
||||
@ -13,12 +13,28 @@ public interface Bucket
|
||||
{
|
||||
|
||||
/**
|
||||
* Adds a new node to the bucket
|
||||
* Adds a contact to the bucket
|
||||
*
|
||||
* @param n the new node
|
||||
* @param c the new contact
|
||||
*/
|
||||
public void insert(Contact c);
|
||||
|
||||
/**
|
||||
* Create a new contact and insert it into the bucket.
|
||||
*
|
||||
* @param n The node to create the contact from
|
||||
*/
|
||||
public void insert(Node n);
|
||||
|
||||
/**
|
||||
* Checks if this bucket contain a contact
|
||||
*
|
||||
* @param c The contact to check for
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public boolean containsContact(Contact c);
|
||||
|
||||
/**
|
||||
* Checks if this bucket contain a node
|
||||
*
|
||||
@ -26,21 +42,28 @@ public interface Bucket
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public boolean containNode(Node n);
|
||||
public boolean containsNode(Node n);
|
||||
|
||||
/**
|
||||
* Remove a node from this bucket
|
||||
* Remove a contact from this bucket
|
||||
*
|
||||
* @param n The node to remove
|
||||
* @param c The contact to remove
|
||||
*/
|
||||
public void removeContact(Contact c);
|
||||
|
||||
/**
|
||||
* Remove the contact object related to a node from this bucket
|
||||
*
|
||||
* @param n The node of the contact to remove
|
||||
*/
|
||||
public void removeNode(Node n);
|
||||
|
||||
/**
|
||||
* Counts the number of nodes in this bucket.
|
||||
* Counts the number of contacts in this bucket.
|
||||
*
|
||||
* @return Integer The number of nodes in this bucket
|
||||
* @return Integer The number of contacts in this bucket
|
||||
*/
|
||||
public int numNodes();
|
||||
public int numContacts();
|
||||
|
||||
/**
|
||||
* @return Integer The depth of this bucket in the RoutingTable
|
||||
@ -48,7 +71,7 @@ public interface Bucket
|
||||
public int getDepth();
|
||||
|
||||
/**
|
||||
* @return An Iterable structure with all nodes in this bucket
|
||||
* @return An Iterable structure with all contacts in this bucket
|
||||
*/
|
||||
public List<Node> getNodes();
|
||||
public List<Contact> getContacts();
|
||||
}
|
||||
|
29
src/kademlia/routing/Contact.java
Normal file
29
src/kademlia/routing/Contact.java
Normal file
@ -0,0 +1,29 @@
|
||||
package kademlia.routing;
|
||||
|
||||
import kademlia.node.Node;
|
||||
|
||||
/**
|
||||
* Keeps information about contacts of the Node; Contacts are stored in the Buckets in the Routing Table.
|
||||
*
|
||||
* Contacts are used instead of nodes because more information is needed than just the node information.
|
||||
* - Information such as
|
||||
* -- Last alive time
|
||||
*
|
||||
* @author Joshua Kissoon
|
||||
* @since 20140425
|
||||
*/
|
||||
public class Contact
|
||||
{
|
||||
|
||||
private final Node n;
|
||||
|
||||
public Contact(Node n)
|
||||
{
|
||||
this.n = n;
|
||||
}
|
||||
|
||||
public Node getNode()
|
||||
{
|
||||
return this.n;
|
||||
}
|
||||
}
|
@ -17,11 +17,11 @@ public class KadBucket implements Bucket
|
||||
{
|
||||
|
||||
private final int depth;
|
||||
private final Map<NodeId, Node> nodes;
|
||||
private final Map<NodeId, Contact> contacts;
|
||||
|
||||
|
||||
{
|
||||
nodes = new HashMap<>();
|
||||
contacts = new HashMap<>();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -33,49 +33,55 @@ public class KadBucket implements Bucket
|
||||
}
|
||||
|
||||
@Override
|
||||
public void insert(Node n)
|
||||
public void insert(Contact c)
|
||||
{
|
||||
/* @todo Check if the bucket is filled already and handle the situation */
|
||||
/* Check if the contact is already in the bucket */
|
||||
if (this.nodes.containsKey(n.getNodeId()))
|
||||
if (this.contacts.containsKey(c.getNode().getNodeId()))
|
||||
{
|
||||
/* @todo If it is, then move it to the front */
|
||||
/* @todo Possibly use a doubly linked list instead of an ArrayList */
|
||||
}
|
||||
else
|
||||
{
|
||||
nodes.put(n.getNodeId(), n);
|
||||
contacts.put(c.getNode().getNodeId(), c);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this bucket contain a node
|
||||
*
|
||||
* @param n The node to check for
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
@Override
|
||||
public boolean containNode(Node n)
|
||||
public void insert(Node n)
|
||||
{
|
||||
return this.nodes.containsKey(n.getNodeId());
|
||||
this.insert(new Contact(n));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsContact(Contact c)
|
||||
{
|
||||
return this.contacts.containsKey(c.getNode().getNodeId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsNode(Node n)
|
||||
{
|
||||
return this.contacts.containsKey(n.getNodeId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeContact(Contact c)
|
||||
{
|
||||
this.contacts.remove(c.getNode().getNodeId());
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a node from this bucket
|
||||
*
|
||||
* @param n The node to remove
|
||||
*/
|
||||
@Override
|
||||
public void removeNode(Node n)
|
||||
{
|
||||
this.nodes.remove(n.getNodeId());
|
||||
this.contacts.remove(n.getNodeId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int numNodes()
|
||||
public int numContacts()
|
||||
{
|
||||
return this.nodes.size();
|
||||
return this.contacts.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -85,9 +91,9 @@ public class KadBucket implements Bucket
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Node> getNodes()
|
||||
public List<Contact> getContacts()
|
||||
{
|
||||
return new ArrayList<>(this.nodes.values());
|
||||
return new ArrayList<>(this.contacts.values());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -96,10 +102,10 @@ public class KadBucket implements Bucket
|
||||
StringBuilder sb = new StringBuilder("Bucket at depth: ");
|
||||
sb.append(this.depth);
|
||||
sb.append("\n Nodes: \n");
|
||||
for (Node n : this.nodes.values())
|
||||
for (Contact n : this.contacts.values())
|
||||
{
|
||||
sb.append("Node: ");
|
||||
sb.append(n.getNodeId().toString());
|
||||
sb.append(n.getNode().getNodeId().toString());
|
||||
sb.append("\n");
|
||||
}
|
||||
|
||||
|
@ -41,9 +41,19 @@ public class RoutingTable
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new node to the routing table based on how far it is from the LocalNode.
|
||||
* Adds a contact to the routing table based on how far it is from the LocalNode.
|
||||
*
|
||||
* @param n The contact to add
|
||||
* @param c The contact to add
|
||||
*/
|
||||
public final void insert(Contact c)
|
||||
{
|
||||
this.buckets[this.getBucketId(c.getNode().getNodeId())].insert(c);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a node to the routing table based on how far it is from the LocalNode.
|
||||
*
|
||||
* @param n The node to add
|
||||
*/
|
||||
public final void insert(Node n)
|
||||
{
|
||||
@ -60,7 +70,7 @@ public class RoutingTable
|
||||
int bucketId = this.getBucketId(n.getNodeId());
|
||||
|
||||
/* If the bucket has the contact, remove it */
|
||||
if (this.buckets[bucketId].containNode(n))
|
||||
if (this.buckets[bucketId].containsNode(n))
|
||||
{
|
||||
this.buckets[bucketId].removeNode(n);
|
||||
}
|
||||
@ -97,11 +107,11 @@ public class RoutingTable
|
||||
int bucketIndex = this.getBucketId(target);
|
||||
|
||||
/* Add the contacts from this bucket to the return contacts */
|
||||
for (Node c : this.buckets[bucketIndex].getNodes())
|
||||
for (Contact c : this.buckets[bucketIndex].getContacts())
|
||||
{
|
||||
if (closest.size() < numNodesRequired)
|
||||
{
|
||||
closest.add(c);
|
||||
closest.add(c.getNode());
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -120,11 +130,11 @@ public class RoutingTable
|
||||
*/
|
||||
for (int i = 1; (bucketIndex - i) >= 0; i++)
|
||||
{
|
||||
for (Node c : this.buckets[bucketIndex - i].getNodes())
|
||||
for (Contact c : this.buckets[bucketIndex - i].getContacts())
|
||||
{
|
||||
if (closest.size() < numNodesRequired)
|
||||
{
|
||||
closest.add(c);
|
||||
closest.add(c.getNode());
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -149,11 +159,11 @@ public class RoutingTable
|
||||
*/
|
||||
for (int i = 1; (bucketIndex + i) < NodeId.ID_LENGTH; i++)
|
||||
{
|
||||
for (Node c : this.buckets[bucketIndex + i].getNodes())
|
||||
for (Contact c : this.buckets[bucketIndex + i].getContacts())
|
||||
{
|
||||
if (closest.size() < numNodesRequired)
|
||||
{
|
||||
closest.add(c);
|
||||
closest.add(c.getNode());
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -180,12 +190,30 @@ public class RoutingTable
|
||||
|
||||
for (Bucket b : this.buckets)
|
||||
{
|
||||
nodes.addAll(b.getNodes());
|
||||
for (Contact c : b.getContacts())
|
||||
{
|
||||
nodes.add(c.getNode());
|
||||
}
|
||||
}
|
||||
|
||||
return nodes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return List A List of all Nodes in this RoutingTable
|
||||
*/
|
||||
public final List getAllContacts()
|
||||
{
|
||||
List<Contact> contacts = new ArrayList<>();
|
||||
|
||||
for (Bucket b : this.buckets)
|
||||
{
|
||||
contacts.addAll(b.getContacts());
|
||||
}
|
||||
|
||||
return contacts;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Bucket[] The buckets in this Kad Instance
|
||||
*/
|
||||
@ -210,12 +238,12 @@ public class RoutingTable
|
||||
StringBuilder sb = new StringBuilder("\nPrinting Routing Table Started ***************** \n");
|
||||
for (Bucket b : this.buckets)
|
||||
{
|
||||
if (b.numNodes() > 0)
|
||||
if (b.numContacts() > 0)
|
||||
{
|
||||
sb.append("# nodes in Bucket with depth ");
|
||||
sb.append(b.getDepth());
|
||||
sb.append(": ");
|
||||
sb.append(b.numNodes());
|
||||
sb.append(b.numContacts());
|
||||
sb.append("\n");
|
||||
sb.append(b.toString());
|
||||
sb.append("\n");
|
||||
|
@ -79,7 +79,10 @@ public class SaveStateTest
|
||||
Kademlia kadR2 = Kademlia.loadFromFile("JoshuaK");
|
||||
System.out.println(kadR2);
|
||||
}
|
||||
|
||||
catch (IllegalStateException e)
|
||||
{
|
||||
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
|
@ -13,6 +13,7 @@ import kademlia.routing.RoutingTable;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.List;
|
||||
import kademlia.node.Node;
|
||||
import kademlia.routing.Contact;
|
||||
|
||||
/**
|
||||
* A KadSerializer that serializes routing tables to JSON format
|
||||
@ -43,6 +44,10 @@ public class JsonRoutingTableSerializer implements KadSerializer<RoutingTable>
|
||||
|
||||
private final Gson gson;
|
||||
|
||||
Type contactCollectionType = new TypeToken<List<Contact>>()
|
||||
{
|
||||
}.getType();
|
||||
|
||||
|
||||
{
|
||||
gson = new Gson();
|
||||
@ -58,15 +63,11 @@ public class JsonRoutingTableSerializer implements KadSerializer<RoutingTable>
|
||||
/* Write the basic RoutingTable */
|
||||
gson.toJson(data, RoutingTable.class, writer);
|
||||
|
||||
/* Now Store the Nodes */
|
||||
Type collectionType = new TypeToken<List<Node>>()
|
||||
{
|
||||
}.getType();
|
||||
gson.toJson(data.getAllNodes(), collectionType, writer);
|
||||
/* Now Store the Contacts */
|
||||
gson.toJson(data.getAllContacts(), contactCollectionType, writer);
|
||||
|
||||
writer.endArray();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -80,16 +81,13 @@ public class JsonRoutingTableSerializer implements KadSerializer<RoutingTable>
|
||||
/* Read the basic RoutingTable */
|
||||
RoutingTable tbl = gson.fromJson(reader, RoutingTable.class);
|
||||
|
||||
/* Now get the nodes and add them back to the RoutingTable */
|
||||
Type collectionType = new TypeToken<List<Node>>()
|
||||
{
|
||||
}.getType();
|
||||
List<Node> nodes = gson.fromJson(reader, collectionType);
|
||||
/* Now get the Contacts and add them back to the RoutingTable */
|
||||
List<Contact> contacts = gson.fromJson(reader, contactCollectionType);
|
||||
tbl.initialize();
|
||||
|
||||
for (Node n : nodes)
|
||||
for (Contact c : contacts)
|
||||
{
|
||||
tbl.insert(n);
|
||||
tbl.insert(c);
|
||||
}
|
||||
|
||||
reader.endArray();
|
||||
|
Loading…
Reference in New Issue
Block a user