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>
</condition>
<condition property="do.archive">
<or>
<not>
<istrue value="${jar.archive.disabled}"/>
</not>
<istrue value="${not.archive.disabled}"/>
</or>
</condition>
<condition property="do.mkdist">
<and>
@ -1199,11 +1202,14 @@ is divided into following sections:
</not>
</and>
</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>
<path path="${javac.classpath}"/>
</classpath>
<fileset dir="${src.dir}" excludes="*.java,${excludes}" includes="${includes}">
<fileset dir="${src.dir}" excludes="${bug5101868workaround},${excludes}" includes="${includes}">
<filename name="**/*.java"/>
</fileset>
<fileset dir="${build.generated.sources.dir}" erroronmissingdir="false">
@ -1277,7 +1283,7 @@ is divided into following sections:
<mkdir dir="${build.test.results.dir}"/>
</target>
<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 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>

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.
# 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.script.CRC32=5c6dd9f7
nbproject/build-impl.xml.stylesheet.CRC32=5a01deb7@1.68.1.46
nbproject/build-impl.xml.script.CRC32=934ae712
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;
import java.io.ByteArrayInputStream;
@ -23,6 +18,11 @@ import kademlia.message.MessageFactory;
import kademlia.node.Node;
import kademlia.operation.Receiver;
/**
* @author Joshua Kissoon
* @created 20140215
* @desc This server handles sending and receiving messages
*/
public class KadServer
{

View File

@ -16,7 +16,8 @@ import kademlia.node.NodeId;
import kademlia.operation.ConnectOperation;
import kademlia.operation.ContentLookupOperation;
import kademlia.operation.Operation;
import kademlia.operation.RefreshOperation;
import kademlia.operation.BucketRefreshOperation;
import kademlia.operation.KadRefreshOperation;
import kademlia.operation.StoreOperation;
/**
@ -79,7 +80,7 @@ public class Kademlia
try
{
/* Runs a RefreshOperation to refresh K-Buckets and stored content */
new RefreshOperation(server, localNode).execute();
new BucketRefreshOperation(server, localNode).execute();
}
catch (IOException e)
{
@ -174,6 +175,16 @@ public class Kademlia
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
*/

View File

@ -42,11 +42,16 @@ public class NodeId implements Streamable
new Random().nextBytes(keyBytes);
}
/**
* Generate the NodeId from a given byte[]
*
* @param bytes
*/
public NodeId(byte[] bytes)
{
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;
}

View File

@ -1,23 +1,25 @@
package kademlia.operation;
import java.io.IOException;
import java.util.List;
import kademlia.core.KadServer;
import kademlia.node.Node;
import kademlia.node.NodeId;
/**
* 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
* At each time interval t, nodes need to refresh their K-Buckets
* This operation takes care of refreshing this node's K-Buckets
*
* @author Joshua Kissoon
* @created 20140224
*/
public class RefreshOperation implements Operation
public class BucketRefreshOperation implements Operation
{
private final KadServer server;
private final Node localNode;
public RefreshOperation(KadServer server, Node localNode)
public BucketRefreshOperation(KadServer server, Node localNode)
{
this.server = server;
this.localNode = localNode;
@ -26,6 +28,17 @@ public class RefreshOperation implements Operation
@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<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 */
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,
* 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;
import java.util.ArrayList;
import java.util.BitSet;
import java.util.List;
import kademlia.node.Node;
import kademlia.node.NodeId;
@ -73,7 +74,7 @@ public class RoutingTable
* @param target The NodeId to find contacts close to
* @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)
{
@ -145,7 +146,10 @@ public class RoutingTable
return closest;
}
public List<Node> getAllNodes()
/**
* @return List A List of all Nodes in this RoutingTable
*/
public List getAllNodes()
{
List<Node> nodes = new ArrayList<>();
@ -157,6 +161,53 @@ public class RoutingTable
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
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();
}
}
}