Content Store, Retrieve and DHT File and Table management working well

Got a few Todos now to finish off
This commit is contained in:
Joshua Kissoon 2014-02-26 21:35:37 +05:30
parent a12e075cec
commit e4726b93f8
22 changed files with 158 additions and 110 deletions

View File

@ -21,7 +21,7 @@ public class Configuration
/** /**
* Maximum number of milliseconds for performing an operation. * Maximum number of milliseconds for performing an operation.
* */ * */
public static long OPERATION_TIMEOUT = 10000; public static long OPERATION_TIMEOUT = 3000;
/** /**
* Maximum number of concurrent messages in transit. * Maximum number of concurrent messages in transit.

View File

@ -41,13 +41,29 @@ public class GetParameter
return this.key; return this.key;
} }
public void setOwnerId(String ownerId)
{
this.ownerId = ownerId;
}
public String getOwnerId() public String getOwnerId()
{ {
return this.ownerId; return this.ownerId;
} }
public void setType(String type)
{
this.type = type;
}
public String getType() public String getType()
{ {
return this.type; return this.type;
} }
@Override
public String toString()
{
return "GetParameter - [Key: " + key + "][Owner: " + this.ownerId + "][Type: " + this.type + "]";
}
} }

View File

@ -170,12 +170,13 @@ public class KadServer
Message msg = messageFactory.createMessage(messCode, din); Message msg = messageFactory.createMessage(messCode, din);
din.close(); din.close();
System.out.println(this.localNode.getNodeId() + " Message Received: " + msg); System.out.println(this.localNode.getNodeId() + " Message Received: [Comm: " + comm + "] " + msg);
/* Get a receiver for this message */ /* Get a receiver for this message */
Receiver receiver; Receiver receiver;
if (this.receivers.containsKey(comm)) if (this.receivers.containsKey(comm))
{ {
System.out.println("Receiver found");
/* If there is a reciever in the receivers to handle this */ /* If there is a reciever in the receivers to handle this */
synchronized (this) synchronized (this)
{ {

View File

@ -2,6 +2,7 @@ package kademlia.core;
import java.io.IOException; import java.io.IOException;
import java.net.InetAddress; import java.net.InetAddress;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.NoSuchElementException; import java.util.NoSuchElementException;
import java.util.Timer; import java.util.Timer;
@ -153,18 +154,24 @@ public class Kademlia
*/ */
public List<KadContent> get(GetParameter param, int numResultsReq) throws NoSuchElementException, IOException public List<KadContent> get(GetParameter param, int numResultsReq) throws NoSuchElementException, IOException
{ {
List contentFound;
if (this.dht.contains(param)) if (this.dht.contains(param))
{ {
/* If the content exist in our own DHT, then return it. */ /* If the content exist in our own DHT, then return it. */
return this.dht.get(param); System.out.println("Found content locally");
contentFound = new ArrayList<>();
contentFound.add(this.dht.get(param));
} }
else else
{ {
/* Seems like it doesn't exist in our DHT, get it from other Nodes */ /* Seems like it doesn't exist in our DHT, get it from other Nodes */
System.out.println("Looking for content on foreign nodes");
ContentLookupOperation clo = new ContentLookupOperation(server, localNode, param, numResultsReq); ContentLookupOperation clo = new ContentLookupOperation(server, localNode, param, numResultsReq);
clo.execute(); clo.execute();
return clo.getContentFound(); contentFound = clo.getContentFound();
} }
return contentFound;
} }
/** /**

View File

@ -7,8 +7,6 @@ import java.io.FileInputStream;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.NoSuchElementException; import java.util.NoSuchElementException;
import kademlia.core.Configuration; import kademlia.core.Configuration;
import kademlia.core.GetParameter; import kademlia.core.GetParameter;
@ -25,10 +23,12 @@ public class DHT
{ {
private final StorageEntryManager entriesManager; private final StorageEntryManager entriesManager;
private final JsonSerializer<KadContent> contentSerializer;
{ {
entriesManager = new StorageEntryManager(); entriesManager = new StorageEntryManager();
contentSerializer = new JsonSerializer<>();
} }
/** /**
@ -46,7 +46,7 @@ public class DHT
/* Now we store the content locally in a file */ /* Now we store the content locally in a file */
String contentStorageFolder = this.getContentStorageFolderName(content.getKey()); String contentStorageFolder = this.getContentStorageFolderName(content.getKey());
DataOutputStream dout = new DataOutputStream(new FileOutputStream(contentStorageFolder + File.separator + content.hashCode() + ".kct")); DataOutputStream dout = new DataOutputStream(new FileOutputStream(contentStorageFolder + File.separator + content.hashCode() + ".kct"));
new JsonSerializer().write(content, dout); contentSerializer.write(content, dout);
} }
/** /**
@ -61,7 +61,7 @@ public class DHT
{ {
String folder = this.getContentStorageFolderName(key); String folder = this.getContentStorageFolderName(key);
DataInputStream in = new DataInputStream(new FileInputStream(folder + File.separator + hashCode + ".kct")); DataInputStream in = new DataInputStream(new FileInputStream(folder + File.separator + hashCode + ".kct"));
return new JsonSerializer().read(in); return contentSerializer.read(in);
} }
/** /**
@ -86,17 +86,14 @@ public class DHT
* *
* @throws java.io.IOException * @throws java.io.IOException
*/ */
public List<KadContent> get(GetParameter param) throws NoSuchElementException, IOException public KadContent get(GetParameter param) throws NoSuchElementException, IOException
{ {
/* Load all KadContent for the entries if any exist */ /* Load a KadContent if any exist for the given criteria */
List<KadContent> values = new ArrayList<>();
try try
{ {
for (StorageEntry e : this.entriesManager.get(param)) StorageEntry e = this.entriesManager.get(param);
{ return this.retrieve(e.getKey(), e.getContentHash());
values.add(this.retrieve(e.getKey(), e.getContentHash()));
}
} }
catch (FileNotFoundException e) catch (FileNotFoundException e)
{ {
@ -107,14 +104,10 @@ public class DHT
System.err.println("The class for some content was not found."); System.err.println("The class for some content was not found.");
} }
if (values.isEmpty()) /* If we got here, means we got no entries */
{
throw new NoSuchElementException(); throw new NoSuchElementException();
} }
return values;
}
/** /**
* Get the name of the folder for which a content should be stored * Get the name of the folder for which a content should be stored
* *

View File

@ -38,7 +38,6 @@ public class StorageEntryManager
{ {
this.entries.put(entry.getKey(), new ArrayList<StorageEntry>()); this.entries.put(entry.getKey(), new ArrayList<StorageEntry>());
} }
this.entries.get(entry.getKey()).add(entry); this.entries.get(entry.getKey()).add(entry);
} }
@ -77,31 +76,23 @@ public class StorageEntryManager
* *
* @return List of content for the specific search parameters * @return List of content for the specific search parameters
*/ */
public List<StorageEntry> get(GetParameter param) throws NoSuchElementException public StorageEntry get(GetParameter param) throws NoSuchElementException
{ {
if (this.entries.containsKey(param.getKey())) if (this.entries.containsKey(param.getKey()))
{ {
/* Content with this key exist, check if any match the rest of the search criteria */ /* Content with this key exist, check if any match the rest of the search criteria */
List<StorageEntry> results = new ArrayList<>();
for (StorageEntry e : this.entries.get(param.getKey())) for (StorageEntry e : this.entries.get(param.getKey()))
{ {
/* If any entry satisfies the given parameters, return true */ /* If any entry satisfies the given parameters, return true */
if (e.satisfiesParameters(param)) if (e.satisfiesParameters(param))
{ {
results.add(e); return e;
} }
} }
if (results.size() > 0) /* If we got here, means we didn't find any entry */
{
return results;
}
else
{
throw new NoSuchElementException(); throw new NoSuchElementException();
} }
}
else else
{ {
throw new NoSuchElementException("No content exist for the given parameters"); throw new NoSuchElementException("No content exist for the given parameters");

View File

@ -5,9 +5,7 @@
*/ */
package kademlia.message; package kademlia.message;
import java.io.DataInput;
import java.io.DataInputStream; import java.io.DataInputStream;
import java.io.DataOutput;
import java.io.DataOutputStream; import java.io.DataOutputStream;
import java.io.IOException; import java.io.IOException;
import kademlia.node.Node; import kademlia.node.Node;

View File

@ -5,9 +5,7 @@
*/ */
package kademlia.message; package kademlia.message;
import java.io.DataInput;
import java.io.DataInputStream; import java.io.DataInputStream;
import java.io.DataOutput;
import java.io.DataOutputStream; import java.io.DataOutputStream;
import java.io.IOException; import java.io.IOException;
import kademlia.node.Node; import kademlia.node.Node;

View File

@ -1,10 +1,13 @@
package kademlia.message; package kademlia.message;
import com.google.gson.JsonSerializationContext;
import java.io.DataInputStream; import java.io.DataInputStream;
import java.io.DataOutputStream; import java.io.DataOutputStream;
import java.io.IOException; import java.io.IOException;
import kademlia.core.GetParameter; import kademlia.core.GetParameter;
import kademlia.dht.KadContent;
import kademlia.node.Node; import kademlia.node.Node;
import kademlia.serializer.JsonSerializer;
/** /**
* Messages used to send to another node requesting content * Messages used to send to another node requesting content
@ -15,7 +18,7 @@ import kademlia.node.Node;
public class ContentLookupMessage implements Message public class ContentLookupMessage implements Message
{ {
public static final byte CODE = 0x47; public static final byte CODE = 0x03;
private Node origin; private Node origin;
private GetParameter params; private GetParameter params;
@ -49,12 +52,25 @@ public class ContentLookupMessage implements Message
public void toStream(DataOutputStream out) throws IOException public void toStream(DataOutputStream out) throws IOException
{ {
this.origin.toStream(out); this.origin.toStream(out);
/* Write the params to the stream */
new JsonSerializer<GetParameter>().write(this.params, out);
} }
@Override @Override
public final void fromStream(DataInputStream in) throws IOException public final void fromStream(DataInputStream in) throws IOException
{ {
this.origin = new Node(in); this.origin = new Node(in);
/* Read the params from the stream */
try
{
this.params = new JsonSerializer<GetParameter>().read(in);
}
catch (ClassNotFoundException e)
{
e.printStackTrace();
}
} }
@Override @Override

View File

@ -31,12 +31,14 @@ public class ContentLookupReceiver implements Receiver
public void receive(Message incoming, int comm) throws IOException public void receive(Message incoming, int comm) throws IOException
{ {
ContentLookupMessage msg = (ContentLookupMessage) incoming; ContentLookupMessage msg = (ContentLookupMessage) incoming;
this.localNode.getRoutingTable().insert(msg.getOrigin());
/* Check if we can have this data */ /* Check if we can have this data */
if (this.dht.contains(msg.getParameters())) if (this.dht.contains(msg.getParameters()))
{ {
/* Return a ContentMessage with the required data */ /* Return a ContentMessage with the required data */
ContentMessage cMsg = new ContentMessage(localNode, this.dht.get(msg.getParameters())); ContentMessage cMsg = new ContentMessage(localNode, this.dht.get(msg.getParameters()));
server.reply(msg.getOrigin(), cMsg, comm);
} }
else else
{ {

View File

@ -16,7 +16,7 @@ import kademlia.serializer.JsonSerializer;
public class ContentMessage implements Message public class ContentMessage implements Message
{ {
public static final byte CODE = 0x56; public static final byte CODE = 0x04;
private KadContent content; private KadContent content;
private Node origin; private Node origin;
@ -43,17 +43,17 @@ public class ContentMessage implements Message
this.origin.toStream(out); this.origin.toStream(out);
/* Serialize the KadContent, then send it to the stream */ /* Serialize the KadContent, then send it to the stream */
JsonSerializer serializer = new JsonSerializer(); new JsonSerializer<KadContent>().write(content, out);
serializer.write(content, out);
} }
@Override @Override
public final void fromStream(DataInputStream in) throws IOException public final void fromStream(DataInputStream in) throws IOException
{ {
this.origin = new Node(in); this.origin = new Node(in);
try try
{ {
this.content = new JsonSerializer().read(in); this.content = new JsonSerializer<KadContent>().read(in);
} }
catch (ClassNotFoundException e) catch (ClassNotFoundException e)
{ {
@ -80,6 +80,6 @@ public class ContentMessage implements Message
@Override @Override
public String toString() public String toString()
{ {
return "StoreMessage[origin=" + origin + ",content=" + content + "]"; return "ContentMessage[origin=" + origin + ",content=" + content + "]";
} }
} }

View File

@ -29,20 +29,24 @@ public class MessageFactory
{ {
switch (code) switch (code)
{ {
case SimpleMessage.CODE:
return new SimpleMessage(in);
case ConnectMessage.CODE:
return new ConnectMessage(in);
case AcknowledgeMessage.CODE: case AcknowledgeMessage.CODE:
return new AcknowledgeMessage(in); return new AcknowledgeMessage(in);
case NodeReplyMessage.CODE: case ConnectMessage.CODE:
return new NodeReplyMessage(in); return new ConnectMessage(in);
case ContentMessage.CODE:
return new ContentMessage(in);
case ContentLookupMessage.CODE:
return new ContentLookupMessage(in);
case NodeLookupMessage.CODE: case NodeLookupMessage.CODE:
return new NodeLookupMessage(in); return new NodeLookupMessage(in);
case NodeReplyMessage.CODE:
return new NodeReplyMessage(in);
case SimpleMessage.CODE:
return new SimpleMessage(in);
case StoreContentMessage.CODE: case StoreContentMessage.CODE:
return new StoreContentMessage(in); return new StoreContentMessage(in);
default: default:
System.out.println("No Message handler found for message. Code: " + code); System.out.println(this.localNode + " - No Message handler found for message. Code: " + code);
return new SimpleMessage(in); return new SimpleMessage(in);
} }
@ -52,17 +56,19 @@ public class MessageFactory
{ {
switch (code) switch (code)
{ {
default:
case SimpleMessage.CODE:
return new SimpleReceiver();
case ConnectMessage.CODE: case ConnectMessage.CODE:
return new ConnectReceiver(server, this.localNode); return new ConnectReceiver(server, this.localNode);
case NodeLookupMessage.CODE:
return new NodeLookupReceiver(server, this.localNode);
case StoreContentMessage.CODE:
return new StoreContentReceiver(server, this.localNode, this.dht);
case ContentLookupMessage.CODE: case ContentLookupMessage.CODE:
return new ContentLookupReceiver(server, localNode, dht); return new ContentLookupReceiver(server, localNode, dht);
case NodeLookupMessage.CODE:
return new NodeLookupReceiver(server, this.localNode);
case SimpleMessage.CODE:
return new SimpleReceiver();
case StoreContentMessage.CODE:
return new StoreContentReceiver(server, this.localNode, this.dht);
default:
System.out.println("No reveiver found for message. Code: " + code);
return new SimpleReceiver();
} }
} }
} }

View File

@ -5,9 +5,7 @@
*/ */
package kademlia.message; package kademlia.message;
import java.io.DataInput;
import java.io.DataInputStream; import java.io.DataInputStream;
import java.io.DataOutput;
import java.io.DataOutputStream; import java.io.DataOutputStream;
import java.io.IOException; import java.io.IOException;
import kademlia.node.Node; import kademlia.node.Node;
@ -19,7 +17,7 @@ public class NodeLookupMessage implements Message
private Node origin; private Node origin;
private NodeId lookupId; private NodeId lookupId;
public static final byte CODE = 0x03; public static final byte CODE = 0x05;
/** /**
* A new NodeLookupMessage to find nodes * A new NodeLookupMessage to find nodes

View File

@ -16,7 +16,7 @@ public class NodeReplyMessage implements Message
{ {
private Node origin; private Node origin;
public static final byte CODE = 0x04; public static final byte CODE = 0x06;
private List<Node> nodes; private List<Node> nodes;
public NodeReplyMessage(Node origin, List<Node> nodes) public NodeReplyMessage(Node origin, List<Node> nodes)

View File

@ -5,9 +5,7 @@
*/ */
package kademlia.message; package kademlia.message;
import java.io.DataInput;
import java.io.DataInputStream; import java.io.DataInputStream;
import java.io.DataOutput;
import java.io.DataOutputStream; import java.io.DataOutputStream;
import java.io.IOException; import java.io.IOException;
@ -15,7 +13,7 @@ public class SimpleMessage implements Message
{ {
/* Message constants */ /* Message constants */
public static final byte CODE = 0x05; public static final byte CODE = 0x07;
private String content; private String content;

View File

@ -16,7 +16,7 @@ import kademlia.serializer.JsonSerializer;
public class StoreContentMessage implements Message public class StoreContentMessage implements Message
{ {
public static final byte CODE = 0x55; public static final byte CODE = 0x08;
private KadContent content; private KadContent content;
private Node origin; private Node origin;
@ -43,8 +43,7 @@ public class StoreContentMessage implements Message
this.origin.toStream(out); this.origin.toStream(out);
/* Serialize the KadContent, then send it to the stream */ /* Serialize the KadContent, then send it to the stream */
JsonSerializer serializer = new JsonSerializer(); new JsonSerializer<KadContent>().write(content, out);
serializer.write(content, out);
} }
@Override @Override
@ -53,7 +52,7 @@ public class StoreContentMessage implements Message
this.origin = new Node(in); this.origin = new Node(in);
try try
{ {
this.content = new JsonSerializer().read(in); this.content = new JsonSerializer<KadContent>().read(in);
} }
catch (ClassNotFoundException e) catch (ClassNotFoundException e)
{ {
@ -80,6 +79,6 @@ public class StoreContentMessage implements Message
@Override @Override
public String toString() public String toString()
{ {
return "StoreMessage[origin=" + origin + ",content=" + content + "]"; return "StoreContentMessage[origin=" + origin + ",content=" + content + "]";
} }
} }

View File

@ -105,12 +105,21 @@ public class ContentLookupOperation implements Operation, Receiver
if (!this.askNodesorFinish()) if (!this.askNodesorFinish())
{ {
/* If we haven't finished as yet, wait a while */ /* If we haven't finished as yet, wait a while */
/**
* @todo Get rid of this wait here!
* We should run this until there are no nodes left to ask from the K closest nodes
* and only pause for short intervals in between
*
* @todo Do the same for the NodeLookupOperation
*/
wait(Configuration.OPERATION_TIMEOUT); wait(Configuration.OPERATION_TIMEOUT);
/* If we still haven't received any responses by then, do a routing timeout */ /* If we still haven't received any responses by then, do a routing timeout */
if (error) if (error)
{ {
throw new RoutingException("Lookup Timeout."); /* Lets not throw any exception */
//throw new RoutingException("Content Lookup Operation Timeout.");
} }
} }
} }
@ -132,16 +141,9 @@ public class ContentLookupOperation implements Operation, Receiver
/* If this node is not in the list, add the node */ /* If this node is not in the list, add the node */
if (!nodes.containsKey(o)) if (!nodes.containsKey(o))
{ {
System.out.println("Adding node " + o.getNodeId());
nodes.put(o, UNASKED); nodes.put(o, UNASKED);
} }
} }
System.out.println(this.localNode.getNodeId() + " Nodes List: ");
for (Node o : this.nodes.keySet())
{
System.out.println(o.getNodeId() + " hash: " + o.hashCode());
}
} }
/** /**
@ -230,6 +232,11 @@ public class ContentLookupOperation implements Operation, Receiver
@Override @Override
public synchronized void receive(Message incoming, int comm) throws IOException, RoutingException public synchronized void receive(Message incoming, int comm) throws IOException, RoutingException
{ {
if (!this.isRunning)
{
return;
}
if (incoming instanceof ContentMessage) if (incoming instanceof ContentMessage)
{ {
/* The reply received is a content message with the required content, take it in */ /* The reply received is a content message with the required content, take it in */
@ -240,6 +247,7 @@ public class ContentLookupOperation implements Operation, Receiver
/* Get the Content and check if it satisfies the required parameters */ /* Get the Content and check if it satisfies the required parameters */
KadContent content = msg.getContent(); KadContent content = msg.getContent();
System.out.println("Content Received: " + content);
/*@todo Check if the content matches the given criteria */ /*@todo Check if the content matches the given criteria */
this.contentFound.add(content); this.contentFound.add(content);
@ -247,6 +255,8 @@ public class ContentLookupOperation implements Operation, Receiver
if (this.contentFound.size() == this.numResultsReq) if (this.contentFound.size() == this.numResultsReq)
{ {
/* We've got all the content required, let's stop the loopup operation */ /* We've got all the content required, let's stop the loopup operation */
System.out.println("We good");
this.isRunning = false;
} }
} }
else else

View File

@ -128,16 +128,16 @@ public class NodeLookupOperation implements Operation, Receiver
/* If this node is not in the list, add the node */ /* If this node is not in the list, add the node */
if (!nodes.containsKey(o)) if (!nodes.containsKey(o))
{ {
System.out.println("Adding node " + o.getNodeId()); //System.out.println("Adding node " + o.getNodeId());
nodes.put(o, UNASKED); nodes.put(o, UNASKED);
} }
} }
System.out.println(this.localNode.getNodeId() + " Nodes List: "); // System.out.println(this.localNode.getNodeId() + " Nodes List: ");
for (Node o : this.nodes.keySet()) // for (Node o : this.nodes.keySet())
{ // {
System.out.println(o.getNodeId() + " hash: " + o.hashCode()); // System.out.println(o.getNodeId() + " hash: " + o.hashCode());
} // }
} }
/** /**
@ -161,10 +161,10 @@ public class NodeLookupOperation implements Operation, Receiver
/* Get unqueried nodes among the K closest seen that have not FAILED */ /* Get unqueried nodes among the K closest seen that have not FAILED */
List<Node> unasked = this.closestNodesNotFailed(UNASKED); List<Node> unasked = this.closestNodesNotFailed(UNASKED);
for (Node nn : unasked) // for (Node nn : unasked)
{ // {
System.out.println(nn.getNodeId()); // System.out.println(nn.getNodeId());
} // }
if (unasked.isEmpty() && this.messagesTransiting.isEmpty()) if (unasked.isEmpty() && this.messagesTransiting.isEmpty())
{ {

View File

@ -4,22 +4,21 @@ import com.google.gson.Gson;
import com.google.gson.stream.JsonReader; import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonWriter; import com.google.gson.stream.JsonWriter;
import java.io.DataInputStream; import java.io.DataInputStream;
import java.io.DataOutput;
import java.io.DataOutputStream; import java.io.DataOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter; import java.io.OutputStreamWriter;
import kademlia.dht.KadContent;
/** /**
* A KadContentSerializer that serializes content to JSON format * A KadContentSerializer that serializes content to JSON format
* *
* @param <T> The type of content to serialize
*
* @author Joshua Kissoon * @author Joshua Kissoon
*
* @since 20140225 * @since 20140225
*/ */
public class JsonSerializer implements KadContentSerializer public class JsonSerializer<T> implements KadContentSerializer<T>
{ {
private final Gson gson; private final Gson gson;
@ -30,17 +29,17 @@ public class JsonSerializer implements KadContentSerializer
} }
@Override @Override
public void write(KadContent content, DataOutputStream out) throws IOException public void write(T data, DataOutputStream out) throws IOException
{ {
try (JsonWriter writer = new JsonWriter(new OutputStreamWriter(out))) try (JsonWriter writer = new JsonWriter(new OutputStreamWriter(out)))
{ {
writer.beginArray(); writer.beginArray();
/* Store the content type */ /* Store the content type */
gson.toJson(content.getClass().getName(), String.class, writer); gson.toJson(data.getClass().getName(), String.class, writer);
/* Now Store the content */ /* Now Store the content */
gson.toJson(content, content.getClass(), writer); gson.toJson(data, data.getClass(), writer);
writer.endArray(); writer.endArray();
} }
@ -48,7 +47,7 @@ public class JsonSerializer implements KadContentSerializer
} }
@Override @Override
public KadContent read(DataInputStream in) throws IOException, ClassNotFoundException public T read(DataInputStream in) throws IOException, ClassNotFoundException
{ {
try (DataInputStream din = new DataInputStream(in); try (DataInputStream din = new DataInputStream(in);
JsonReader reader = new JsonReader(new InputStreamReader(in))) JsonReader reader = new JsonReader(new InputStreamReader(in)))

View File

@ -3,9 +3,6 @@ package kademlia.serializer;
import java.io.DataInputStream; import java.io.DataInputStream;
import java.io.DataOutputStream; import java.io.DataOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import kademlia.dht.KadContent;
/** /**
* A Serializer is used to transform data to and from a specified form. * A Serializer is used to transform data to and from a specified form.
@ -13,30 +10,32 @@ import kademlia.dht.KadContent;
* Here we define the structure of any Serializer used in Kademlia * Here we define the structure of any Serializer used in Kademlia
* *
* @author Joshua Kissoon * @author Joshua Kissoon
* @param <T> The type of content being serialized
*
* @since 20140225 * @since 20140225
*/ */
public interface KadContentSerializer public interface KadContentSerializer<T>
{ {
/** /**
* Write a KadContent to a DataOutput stream * Write a KadContent to a DataOutput stream
* *
* @param content The content to write * @param data The data to write
* @param out The output Stream to write to * @param out The output Stream to write to
* *
* @throws java.io.IOException * @throws java.io.IOException
*/ */
public void write(KadContent content, DataOutputStream out) throws IOException; public void write(T data, DataOutputStream out) throws IOException;
/** /**
* Read a KadContent from a DataInput Stream * Read data of type T from a DataInput Stream
* *
* @param in The InputStream to read the data from * @param in The InputStream to read the data from
* *
* @return KadContent * @return T Data of type T
* *
* @throws java.io.IOException * @throws java.io.IOException
* @throws java.lang.ClassNotFoundException * @throws java.lang.ClassNotFoundException
*/ */
public KadContent read(DataInputStream in) throws IOException, ClassNotFoundException; public T read(DataInputStream in) throws IOException, ClassNotFoundException;
} }

View File

@ -1,7 +1,10 @@
package kademlia.tests; package kademlia.tests;
import java.io.IOException; import java.io.IOException;
import java.util.List;
import kademlia.core.GetParameter;
import kademlia.core.Kademlia; import kademlia.core.Kademlia;
import kademlia.dht.KadContent;
import kademlia.node.NodeId; import kademlia.node.NodeId;
/** /**
@ -30,6 +33,20 @@ public class ContentSendingTest
DHTContentImpl c = new DHTContentImpl(kad2.getOwnerId(), "Some Data"); DHTContentImpl c = new DHTContentImpl(kad2.getOwnerId(), "Some Data");
kad2.put(c); kad2.put(c);
/**
* Lets retrieve the content
*/
System.out.println("Retrieving Content");
GetParameter gp = new GetParameter(c.getKey());
gp.setType(DHTContentImpl.TYPE);
gp.setOwnerId(c.getOwnerId());
System.out.println("Get Parameter: " + gp);
List<KadContent> conte = kad2.get(gp, 1);
for (KadContent cc : conte)
{
System.out.println("Content Found: " + cc);
}
} }
catch (IOException e) catch (IOException e)
{ {

View File

@ -17,7 +17,7 @@ public class DHTContentImpl implements KadContent
private final String ownerId; private final String ownerId;
private final long createTs; private final long createTs;
private static final String type = "DHTContentImpl"; public static final String TYPE = "DHTContentImpl";
{ {
@ -56,7 +56,7 @@ public class DHTContentImpl implements KadContent
@Override @Override
public String getType() public String getType()
{ {
return type; return TYPE;
} }
@Override @Override