Started working on the RefreshOperations

This commit is contained in:
Joshua Kissoon 2014-03-06 11:21:08 +05:30
parent e4726b93f8
commit acd7885dba
10 changed files with 205 additions and 26 deletions

View File

@ -80,9 +80,12 @@ is divided into following sections:
</and> </and>
</condition> </condition>
<condition property="do.archive"> <condition property="do.archive">
<or>
<not> <not>
<istrue value="${jar.archive.disabled}"/> <istrue value="${jar.archive.disabled}"/>
</not> </not>
<istrue value="${not.archive.disabled}"/>
</or>
</condition> </condition>
<condition property="do.mkdist"> <condition property="do.mkdist">
<and> <and>
@ -1199,11 +1202,14 @@ is divided into following sections:
</not> </not>
</and> </and>
</condition> </condition>
<javadoc additionalparam="${javadoc.additionalparam}" author="${javadoc.author}" charset="UTF-8" destdir="${dist.javadoc.dir}" docencoding="UTF-8" encoding="${javadoc.encoding.used}" failonerror="true" noindex="${javadoc.noindex}" nonavbar="${javadoc.nonavbar}" notree="${javadoc.notree}" private="${javadoc.private}" source="${javac.source}" splitindex="${javadoc.splitindex}" use="${javadoc.use}" useexternalfile="true" version="${javadoc.version}" windowtitle="${javadoc.windowtitle}"> <condition else="" property="bug5101868workaround" value="*.java">
<matches pattern="1\.[56](\..*)?" string="${java.version}"/>
</condition>
<javadoc additionalparam="-J-Dfile.encoding=${file.encoding} ${javadoc.additionalparam}" author="${javadoc.author}" charset="UTF-8" destdir="${dist.javadoc.dir}" docencoding="UTF-8" encoding="${javadoc.encoding.used}" failonerror="true" noindex="${javadoc.noindex}" nonavbar="${javadoc.nonavbar}" notree="${javadoc.notree}" private="${javadoc.private}" source="${javac.source}" splitindex="${javadoc.splitindex}" use="${javadoc.use}" useexternalfile="true" version="${javadoc.version}" windowtitle="${javadoc.windowtitle}">
<classpath> <classpath>
<path path="${javac.classpath}"/> <path path="${javac.classpath}"/>
</classpath> </classpath>
<fileset dir="${src.dir}" excludes="*.java,${excludes}" includes="${includes}"> <fileset dir="${src.dir}" excludes="${bug5101868workaround},${excludes}" includes="${includes}">
<filename name="**/*.java"/> <filename name="**/*.java"/>
</fileset> </fileset>
<fileset dir="${build.generated.sources.dir}" erroronmissingdir="false"> <fileset dir="${build.generated.sources.dir}" erroronmissingdir="false">
@ -1277,7 +1283,7 @@ is divided into following sections:
<mkdir dir="${build.test.results.dir}"/> <mkdir dir="${build.test.results.dir}"/>
</target> </target>
<target depends="init,compile-test,-pre-test-run" if="have.tests" name="-do-test-run"> <target depends="init,compile-test,-pre-test-run" if="have.tests" name="-do-test-run">
<j2seproject3:test testincludes="**/*Test.java"/> <j2seproject3:test includes="${includes}" testincludes="**/*Test.java"/>
</target> </target>
<target depends="init,compile-test,-pre-test-run,-do-test-run" if="have.tests" name="-post-test-run"> <target depends="init,compile-test,-pre-test-run,-do-test-run" if="have.tests" name="-post-test-run">
<fail if="tests.failed" unless="ignore.failing.tests">Some tests failed; see details above.</fail> <fail if="tests.failed" unless="ignore.failing.tests">Some tests failed; see details above.</fail>

View File

@ -4,5 +4,5 @@ build.xml.stylesheet.CRC32=8064a381@1.68.1.46
# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml. # This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you. # Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
nbproject/build-impl.xml.data.CRC32=7e563d6e nbproject/build-impl.xml.data.CRC32=7e563d6e
nbproject/build-impl.xml.script.CRC32=5c6dd9f7 nbproject/build-impl.xml.script.CRC32=934ae712
nbproject/build-impl.xml.stylesheet.CRC32=5a01deb7@1.68.1.46 nbproject/build-impl.xml.stylesheet.CRC32=876e7a8f@1.74.1.48

View File

@ -1,8 +1,3 @@
/**
* @author Joshua Kissoon
* @created 20140215
* @desc This server handles sending and receiving messages
*/
package kademlia.core; package kademlia.core;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
@ -23,6 +18,11 @@ import kademlia.message.MessageFactory;
import kademlia.node.Node; import kademlia.node.Node;
import kademlia.operation.Receiver; import kademlia.operation.Receiver;
/**
* @author Joshua Kissoon
* @created 20140215
* @desc This server handles sending and receiving messages
*/
public class KadServer public class KadServer
{ {

View File

@ -16,7 +16,8 @@ import kademlia.node.NodeId;
import kademlia.operation.ConnectOperation; import kademlia.operation.ConnectOperation;
import kademlia.operation.ContentLookupOperation; import kademlia.operation.ContentLookupOperation;
import kademlia.operation.Operation; import kademlia.operation.Operation;
import kademlia.operation.RefreshOperation; import kademlia.operation.BucketRefreshOperation;
import kademlia.operation.KadRefreshOperation;
import kademlia.operation.StoreOperation; import kademlia.operation.StoreOperation;
/** /**
@ -79,7 +80,7 @@ public class Kademlia
try try
{ {
/* Runs a RefreshOperation to refresh K-Buckets and stored content */ /* Runs a RefreshOperation to refresh K-Buckets and stored content */
new RefreshOperation(server, localNode).execute(); new BucketRefreshOperation(server, localNode).execute();
} }
catch (IOException e) catch (IOException e)
{ {
@ -174,6 +175,16 @@ public class Kademlia
return contentFound; return contentFound;
} }
/**
* Allow the user of the System to call refresh even out of the normal Kad refresh timing
*
* @throws java.io.IOException
*/
public void refresh() throws IOException
{
new KadRefreshOperation(server, localNode).execute();
}
/** /**
* @return String The ID of the owner of this local network * @return String The ID of the owner of this local network
*/ */

View File

@ -42,11 +42,16 @@ public class NodeId implements Streamable
new Random().nextBytes(keyBytes); new Random().nextBytes(keyBytes);
} }
/**
* Generate the NodeId from a given byte[]
*
* @param bytes
*/
public NodeId(byte[] bytes) public NodeId(byte[] bytes)
{ {
if (bytes.length != ID_LENGTH / 8) if (bytes.length != ID_LENGTH / 8)
{ {
throw new IllegalArgumentException("Specified Data need to be " + (ID_LENGTH / 8) + " characters long."); throw new IllegalArgumentException("Specified Data need to be " + (ID_LENGTH / 8) + " characters long. Data Given: '" + new String(bytes) + "'");
} }
this.keyBytes = bytes; this.keyBytes = bytes;
} }

View File

@ -1,23 +1,25 @@
package kademlia.operation; package kademlia.operation;
import java.io.IOException; import java.io.IOException;
import java.util.List;
import kademlia.core.KadServer; import kademlia.core.KadServer;
import kademlia.node.Node; import kademlia.node.Node;
import kademlia.node.NodeId;
/** /**
* At each time interval t, nodes need to refresh their K-Buckets and their Data Storage * At each time interval t, nodes need to refresh their K-Buckets
* This Operation will manage refreshing the K-Buckets and data storage * This operation takes care of refreshing this node's K-Buckets
* *
* @author Joshua Kissoon * @author Joshua Kissoon
* @created 20140224 * @created 20140224
*/ */
public class RefreshOperation implements Operation public class BucketRefreshOperation implements Operation
{ {
private final KadServer server; private final KadServer server;
private final Node localNode; private final Node localNode;
public RefreshOperation(KadServer server, Node localNode) public BucketRefreshOperation(KadServer server, Node localNode)
{ {
this.server = server; this.server = server;
this.localNode = localNode; this.localNode = localNode;
@ -26,6 +28,17 @@ public class RefreshOperation implements Operation
@Override @Override
public synchronized void execute() throws IOException 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<NodeId> refreshIds = this.localNode.getRoutingTable().getRefreshList();
/* Test whether each nodeId in this list is a different distance from our current NID */
for (NodeId nid : refreshIds)
{
System.out.println(nid.xor(localNode.getNodeId()).getFirstSetBitIndex());
}
/* @todo Do a Node Lookup operation to refresh K-Buckets */ /* @todo Do a Node Lookup operation to refresh K-Buckets */
new NodeLookupOperation(this.server, this.localNode, this.localNode.getNodeId()).execute(); new NodeLookupOperation(this.server, this.localNode, this.localNode.getNodeId()).execute();
@ -34,9 +47,5 @@ public class RefreshOperation implements Operation
* This is better than asking closest nodes for data, * This is better than asking closest nodes for data,
* since the data may not always come from the closest nodes * 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
*/
} }
} }

View File

@ -0,0 +1,19 @@
package kademlia.operation;
/**
* Refresh the data on this node by sending the data to the K-Closest nodes to the data
*
* @author Joshua Kissoon
* @since 20140306
*/
public class ContentRefreshOperation
{
public void execute()
{
/**
* @todo Delete any content on this node that this node is not one of the K-Closest nodes to
* @todo Delete any expired content
*/
}
}

View File

@ -0,0 +1,33 @@
package kademlia.operation;
import java.io.IOException;
import kademlia.core.KadServer;
import kademlia.node.Node;
/**
* An operation that handles refreshing the entire Kademlia Systems including buckets and content
*
* @author Joshua Kissoon
* @since 20140306
*/
public class KadRefreshOperation implements Operation
{
private final KadServer server;
private final Node localNode;
public KadRefreshOperation(KadServer server, Node localNode)
{
this.server = server;
this.localNode = localNode;
}
@Override
public void execute() throws IOException
{
/* Run our BucketRefreshOperation to refresh buckets */
new BucketRefreshOperation(server, localNode).execute();
/* After buckets have been refreshed, we refresh content */
}
}

View File

@ -6,6 +6,7 @@
package kademlia.routing; package kademlia.routing;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.BitSet;
import java.util.List; import java.util.List;
import kademlia.node.Node; import kademlia.node.Node;
import kademlia.node.NodeId; import kademlia.node.NodeId;
@ -73,7 +74,7 @@ public class RoutingTable
* @param target The NodeId to find contacts close to * @param target The NodeId to find contacts close to
* @param num The number of contacts to find * @param num The number of contacts to find
* *
* @return List<Contact> A List of num contacts closest to target * @return List A List of contacts closest to target
*/ */
public List<Node> findClosest(NodeId target, int num) public List<Node> findClosest(NodeId target, int num)
{ {
@ -145,7 +146,10 @@ public class RoutingTable
return closest; return closest;
} }
public List<Node> getAllNodes() /**
* @return List A List of all Nodes in this RoutingTable
*/
public List getAllNodes()
{ {
List<Node> nodes = new ArrayList<>(); List<Node> nodes = new ArrayList<>();
@ -157,6 +161,53 @@ public class RoutingTable
return nodes; 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<NodeId> getRefreshList()
{
List<NodeId> 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 temp = new BitSet(NodeId.ID_LENGTH);
/* Fill the first i parts with 1 */
for (int j = 0; j < i; j++)
{
System.out.println("Got here 1 - j: " + j);
temp.set(j);
}
/* Fill the last parts with 0 */
for (int j = i; j < NodeId.ID_LENGTH; j++)
{
System.out.println("Got here 2 - j: " + j);
temp.set(j, false);
}
/**
* 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: " + temp);
NodeId nid = this.localNode.getNodeId().xor(new NodeId(temp.toByteArray()));
System.out.println("NodeId: " + nid);
refreshList.add(nid);
}
return refreshList;
}
@Override @Override
public String toString() public String toString()
{ {

View File

@ -0,0 +1,45 @@
package kademlia.tests;
import java.io.IOException;
import java.util.List;
import kademlia.core.GetParameter;
import kademlia.core.Kademlia;
import kademlia.dht.KadContent;
import kademlia.node.NodeId;
/**
* Testing sending and receiving content between 2 Nodes on a network
*
* @author Joshua Kissoon
* @since 20140224
*/
public class RefreshOperationTest
{
public static void main(String[] args)
{
try
{
/* Setting up 2 Kad networks */
Kademlia kad1 = new Kademlia("JoshuaK", new NodeId("ASF45678947584567467"), 7574);
Kademlia kad2 = new Kademlia("Crystal", new NodeId("ASERTKJDHGVHERJHGFLK"), 7572);
kad2.connect(kad1.getNode());
/* Lets create the content and share it */
DHTContentImpl c = new DHTContentImpl(kad2.getOwnerId(), "Some Data");
kad2.put(c);
/* Lets retrieve the content */
GetParameter gp = new GetParameter(c.getKey());
gp.setType(DHTContentImpl.TYPE);
gp.setOwnerId(c.getOwnerId());
List<KadContent> conte = kad2.get(gp, 1);
kad2.refresh();
}
catch (IOException e)
{
e.printStackTrace();
}
}
}