From 44077d344dc199d86329cb75ebef7bd79bda817d Mon Sep 17 00:00:00 2001 From: Joshua Kissoon Date: Mon, 24 Feb 2014 21:26:49 +0530 Subject: [PATCH] Started working on Node refreshing the K-Buckets and DHT content at every time interval t Started working on PUT, GET, STORE operation and on DHT Storage --- src/kademlia/core/Configuration.java | 2 +- src/kademlia/core/Kademlia.java | 61 +++++++++++++++----- src/kademlia/dht/DHTContent.java | 35 +++++++++++ src/kademlia/node/Node.java | 28 +++++---- src/kademlia/operation/ConnectOperation.java | 8 ++- src/kademlia/operation/Operation.java | 2 + src/kademlia/operation/RefreshOperation.java | 43 ++++++++++++++ src/kademlia/operation/StoreOperation.java | 41 +++++++++++++ src/kademlia/tests/DHTContentImpl.java | 12 ++++ 9 files changed, 203 insertions(+), 29 deletions(-) create mode 100644 src/kademlia/dht/DHTContent.java create mode 100644 src/kademlia/operation/RefreshOperation.java create mode 100644 src/kademlia/operation/StoreOperation.java create mode 100644 src/kademlia/tests/DHTContentImpl.java diff --git a/src/kademlia/core/Configuration.java b/src/kademlia/core/Configuration.java index 28dd6a9..81e0e29 100644 --- a/src/kademlia/core/Configuration.java +++ b/src/kademlia/core/Configuration.java @@ -26,7 +26,7 @@ public class Configuration /** * Maximum number of concurrent messages in transit. * */ - public static int CONCURRENCY = 2; + public static int CONCURRENCY = 10; /** * Log base exponent. diff --git a/src/kademlia/core/Kademlia.java b/src/kademlia/core/Kademlia.java index 1a242ab..5baa162 100644 --- a/src/kademlia/core/Kademlia.java +++ b/src/kademlia/core/Kademlia.java @@ -1,26 +1,29 @@ -/** - * @author Joshua Kissoon - * @created 20140215 - * @desc The main Kademlia network management class - */ package kademlia.core; import java.io.IOException; import java.net.InetAddress; import java.util.Timer; import java.util.TimerTask; +import kademlia.dht.DHTContent; import kademlia.exceptions.RoutingException; import kademlia.message.MessageFactory; import kademlia.node.Node; import kademlia.node.NodeId; import kademlia.operation.ConnectOperation; import kademlia.operation.Operation; +import kademlia.operation.RefreshOperation; +/** + * The main Kademlia network management class + * + * @author Joshua Kissoon + * @since 20140215 + */ public class Kademlia { /* Kademlia Attributes */ - private final String name; + private final String ownerId; /* Objects to be used */ private final Node localNode; @@ -36,7 +39,7 @@ public class Kademlia * The instance is bootstraped to an existing network by specifying the * address of a bootstrap node in the network. * - * @param name The Name of this node used for storage + * @param ownerId The Name of this node used for storage * @param defaultId Default id for the node * @param udpPort The UDP port to use for routing messages * @@ -44,9 +47,9 @@ public class Kademlia * from disk or a network error occurred while * attempting to connect to the network * */ - public Kademlia(String name, NodeId defaultId, int udpPort) throws IOException + public Kademlia(String ownerId, NodeId defaultId, int udpPort) throws IOException { - this.name = name; + this.ownerId = ownerId; this.localNode = new Node(defaultId, InetAddress.getLocalHost(), udpPort); this.messageFactory = new MessageFactory(localNode); this.server = new KadServer(udpPort, this.messageFactory, this.localNode); @@ -59,12 +62,15 @@ public class Kademlia @Override public void run() { - /** - * @todo Create Operation that - * Refreshes all buckets and sends HashMessages to all nodes that are - * among the K closest to mappings stored at this node. Also deletes any - * mappings that this node is no longer among the K closest to. - * */ + try + { + /* Runs a RefreshOperation to refresh K-Buckets and stored content */ + new RefreshOperation(server, localNode).execute(); + } + catch (IOException e) + { + System.err.println("Refresh Operation Failed; Message: " + e.getMessage()); + } } }, // Delay // Interval @@ -102,4 +108,29 @@ public class Kademlia Operation op = new ConnectOperation(this.server, this.localNode, n); op.execute(); } + + /** + * Stores the specified value under the given key + * This value is stored on K nodes on the network, or all nodes if there are > K total nodes in the network + * + * @param content The content to put onto the DHT + * + */ + public boolean put(DHTContent content) + { + + return false; + } + + /** + * Get some content stored on the DHT + * + * @param key The key of this content + * + * @return DHTContent The content + */ + public DHTContent get(NodeId key) + { + return null; + } } diff --git a/src/kademlia/dht/DHTContent.java b/src/kademlia/dht/DHTContent.java new file mode 100644 index 0000000..7cbeec5 --- /dev/null +++ b/src/kademlia/dht/DHTContent.java @@ -0,0 +1,35 @@ +package kademlia.dht; + +import kademlia.node.NodeId; + +/** + * Any piece of content that needs to be stored on the DHT + * + * @author Joshua Kissoon + * @since 20140224 + */ +public interface DHTContent +{ + + /** + * @return NodeId The DHT key for this content + */ + public NodeId getKey(); + + /** + * @return String The type of content + */ + public String getType(); + + /** + * Each content will have an expiry date for when a user should delete it form his/her machine + * + * @return long The expiry date of this content + */ + public long getExpiryDate(); + + /** + * @return The ID of the owner of this content + */ + public String getOwnerId(); +} diff --git a/src/kademlia/node/Node.java b/src/kademlia/node/Node.java index 8cfbd16..9bfbe65 100644 --- a/src/kademlia/node/Node.java +++ b/src/kademlia/node/Node.java @@ -1,8 +1,3 @@ -/** - * @author Joshua - * @created - * @desc - */ package kademlia.node; import java.io.DataInput; @@ -15,6 +10,13 @@ import java.util.Comparator; import kademlia.message.Streamable; import kademlia.routing.RoutingTable; +/** + * A Node in the Kademlia network + * + * @author Joshua Kissoon + * @since 20140202 + * @version 0.1 + */ public class Node implements Streamable { @@ -167,7 +169,9 @@ public class Node implements Streamable { Node n1 = (Node) o1; Node n2 = (Node) o2; - if(n1.getNodeId().equals(n2.getNodeId())) + + /* Check if they are equal and return 0 */ + if (n1.getNodeId().equals(n2.getNodeId())) { return 0; } @@ -179,18 +183,20 @@ public class Node implements Streamable int index2 = nodeId.xor(n2.getNodeId()).getFirstSetBitIndex(); //System.out.println("Node " + n2.getNodeId() + " distance: " + index2); - /* If the first node is closer to the given node, return 1 */ int retval; if (index1 < index2) { + /* If the first node is closer to the given node, return 1 */ retval = 1; } - else if (index1 > index2) - { - retval = -1; - } else { + /** + * If the first node is farther to the given node, return 1 + * + * @note -1 will also be returned if both nodes are the same distance away + * This really don't make a difference though, since they need to be sorted. + */ retval = -1; } diff --git a/src/kademlia/operation/ConnectOperation.java b/src/kademlia/operation/ConnectOperation.java index 3c1393f..80f99eb 100644 --- a/src/kademlia/operation/ConnectOperation.java +++ b/src/kademlia/operation/ConnectOperation.java @@ -67,8 +67,12 @@ public class ConnectOperation implements Operation, Receiver /* Perform lookup for our own ID to get nodes close to us */ Operation lookup = new NodeLookupOperation(this.server, this.localNode, this.localNode.getNodeId()); lookup.execute(); - - /* @todo Refresh buckets to get a good routing table */ + + /** + * @todo Refresh buckets to get a good routing table + * I think after the above lookup operation, K buckets will be filled + * Not sure if this operation is needed here + */ return null; } diff --git a/src/kademlia/operation/Operation.java b/src/kademlia/operation/Operation.java index ea7c480..d3fd135 100644 --- a/src/kademlia/operation/Operation.java +++ b/src/kademlia/operation/Operation.java @@ -17,6 +17,8 @@ public interface Operation * @return The return value can differ per operation * * @throws kademlia.exceptions.RoutingException + * + * @todo Remove the Object return type, those operations that return things should have a method to return the data */ public Object execute() throws IOException, RoutingException; } diff --git a/src/kademlia/operation/RefreshOperation.java b/src/kademlia/operation/RefreshOperation.java new file mode 100644 index 0000000..0f00cad --- /dev/null +++ b/src/kademlia/operation/RefreshOperation.java @@ -0,0 +1,43 @@ +package kademlia.operation; + +import java.io.IOException; +import kademlia.core.KadServer; +import kademlia.node.Node; + +/** + * At each time interval t, nodes need to refresh their K-Buckets and their Data Storage + * This Operation will manage refreshing the K-Buckets and data storage + * + * @author Joshua Kissoon + * @created 20140224 + */ +public class RefreshOperation implements Operation +{ + + private final KadServer server; + private final Node localNode; + + public RefreshOperation(KadServer server, Node localNode) + { + this.server = server; + this.localNode = localNode; + } + + @Override + public synchronized Object execute() throws IOException + { + /* @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 + */ + /** + * @todo Delete any content on this node that this node is not one of the K-Closest nodes to + * @todo Delete any expired content + */ + return null; + } +} diff --git a/src/kademlia/operation/StoreOperation.java b/src/kademlia/operation/StoreOperation.java new file mode 100644 index 0000000..e279137 --- /dev/null +++ b/src/kademlia/operation/StoreOperation.java @@ -0,0 +1,41 @@ +package kademlia.operation; + +import java.io.IOException; +import java.util.ArrayList; +import kademlia.core.KadServer; +import kademlia.dht.DHTContent; +import kademlia.node.Node; + +/** + * Operation that stores a DHT Content onto the K closest nodes to the content Key + * + * @author Joshua Kissoon + * @since 20140224 + */ +public class StoreOperation implements Operation +{ + + private final KadServer server; + private final Node localNode; + private final DHTContent content; + + /** + * @param server + * @param localNode + * @param content The content to be stored on the DHT + */ + public StoreOperation(KadServer server, Node localNode, DHTContent content) + { + this.server = server; + this.localNode = localNode; + this.content = content; + } + + @Override + public synchronized Object execute() throws IOException + { + /* Get the nodes on which we need to store the content */ + ArrayList nodes = new NodeLookupOperation(this.server, this.localNode, this.content.getKey()).execute(); + return null; + } +} diff --git a/src/kademlia/tests/DHTContentImpl.java b/src/kademlia/tests/DHTContentImpl.java new file mode 100644 index 0000000..4c25272 --- /dev/null +++ b/src/kademlia/tests/DHTContentImpl.java @@ -0,0 +1,12 @@ +package kademlia.tests; + +/** + * A simple DHT Content object to test DHT storage + * + * @author Joshua Kissoon + * @since 20140224 + */ +public class DHTContentImpl +{ + +}