mirror of
https://github.com/ChronosX88/KademliaDHT.git
synced 2024-11-24 19:22:18 +00:00
Now we use a StorageEntry class to send data accross peers
Out KadContent interface also now specifies a set of methods to force it's subclasses to do their own toByte conversions
This commit is contained in:
parent
9190b122c7
commit
3e236f4d17
@ -19,6 +19,7 @@ import kademlia.core.KadConfiguration;
|
||||
import kademlia.core.KadServer;
|
||||
import kademlia.dht.DHT;
|
||||
import kademlia.dht.KadContent;
|
||||
import kademlia.dht.StorageEntry;
|
||||
import kademlia.exceptions.RoutingException;
|
||||
import kademlia.message.MessageFactory;
|
||||
import kademlia.node.Node;
|
||||
@ -280,7 +281,7 @@ public class Kademlia
|
||||
*
|
||||
* @throws java.io.IOException
|
||||
*/
|
||||
public List<KadContent> get(GetParameter param, int numResultsReq) throws NoSuchElementException, IOException
|
||||
public List<StorageEntry> get(GetParameter param, int numResultsReq) throws NoSuchElementException, IOException
|
||||
{
|
||||
List contentFound;
|
||||
if (this.dht.contains(param))
|
||||
|
@ -19,26 +19,16 @@ public class GetParameter
|
||||
private String ownerId = null;
|
||||
private String type = null;
|
||||
|
||||
/**
|
||||
* Construct a GetParameter to search for data by NodeId
|
||||
*
|
||||
* @param key
|
||||
*/
|
||||
public GetParameter(NodeId key)
|
||||
{
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a GetParameter to search for data by NodeId and owner
|
||||
*
|
||||
* @param key
|
||||
* @param owner
|
||||
* @param type
|
||||
*/
|
||||
public GetParameter(NodeId key, String owner)
|
||||
public GetParameter(NodeId key, String type)
|
||||
{
|
||||
this(key);
|
||||
this.ownerId = owner;
|
||||
this.key = key;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -27,7 +27,7 @@ public class DHT
|
||||
{
|
||||
|
||||
private transient StorageEntryManager entriesManager;
|
||||
private transient KadSerializer<KadContent> contentSerializer = null;
|
||||
private transient KadSerializer<StorageEntry> serializer = null;
|
||||
private transient KadConfiguration config;
|
||||
|
||||
private final String ownerId;
|
||||
@ -62,14 +62,14 @@ public class DHT
|
||||
*
|
||||
* @return The new ContentSerializer
|
||||
*/
|
||||
public KadSerializer<KadContent> getContentSerializer()
|
||||
public KadSerializer<StorageEntry> getSerializer()
|
||||
{
|
||||
if (null == contentSerializer)
|
||||
if (null == serializer)
|
||||
{
|
||||
contentSerializer = new JsonSerializer<>();
|
||||
serializer = new JsonSerializer<>();
|
||||
}
|
||||
|
||||
return contentSerializer;
|
||||
return serializer;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -79,22 +79,20 @@ public class DHT
|
||||
*
|
||||
* @throws java.io.IOException
|
||||
*/
|
||||
public void store(KadContent content) throws IOException
|
||||
public void store(StorageEntry content) throws IOException
|
||||
{
|
||||
/* Keep track of this content in the entries manager */
|
||||
try
|
||||
{
|
||||
StorageEntryMetadata sEntry = this.entriesManager.put(content);
|
||||
StorageEntryMetadata sEntry = this.entriesManager.put(content.getContentMetadata());
|
||||
|
||||
/* Now we store the content locally in a file */
|
||||
String contentStorageFolder = this.getContentStorageFolderName(content.getKey());
|
||||
String contentStorageFolder = this.getContentStorageFolderName(content.getContentMetadata().getKey());
|
||||
|
||||
try (FileOutputStream fout = new FileOutputStream(contentStorageFolder + File.separator + sEntry.hashCode() + ".kct");
|
||||
DataOutputStream dout = new DataOutputStream(fout))
|
||||
{
|
||||
byte[] data = content.toBytes();
|
||||
dout.writeInt(data.length);
|
||||
dout.write(data);
|
||||
this.getSerializer().write(content, dout);
|
||||
}
|
||||
}
|
||||
catch (ContentExistException e)
|
||||
@ -103,6 +101,11 @@ public class DHT
|
||||
}
|
||||
}
|
||||
|
||||
public void store(KadContent content) throws IOException
|
||||
{
|
||||
this.store(new StorageEntry(content));
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a Content from local storage
|
||||
*
|
||||
@ -111,15 +114,11 @@ public class DHT
|
||||
*
|
||||
* @return A KadContent object
|
||||
*/
|
||||
private byte[] retrieve(NodeId key, int hashCode) throws FileNotFoundException, IOException, ClassNotFoundException
|
||||
private StorageEntry retrieve(NodeId key, int hashCode) throws FileNotFoundException, IOException, ClassNotFoundException
|
||||
{
|
||||
String folder = this.getContentStorageFolderName(key);
|
||||
DataInputStream din = new DataInputStream(new FileInputStream(folder + File.separator + hashCode + ".kct"));
|
||||
int length = din.readInt();
|
||||
|
||||
byte[] data = new byte[length];
|
||||
din.read(data);
|
||||
return data;
|
||||
return this.getSerializer().read(din);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -143,7 +142,7 @@ public class DHT
|
||||
*
|
||||
* @throws java.io.IOException
|
||||
*/
|
||||
public byte[] get(StorageEntryMetadata entry) throws IOException, NoSuchElementException
|
||||
public StorageEntry get(StorageEntryMetadata entry) throws IOException, NoSuchElementException
|
||||
{
|
||||
try
|
||||
{
|
||||
@ -172,7 +171,7 @@ public class DHT
|
||||
*
|
||||
* @throws java.io.IOException
|
||||
*/
|
||||
public byte[] get(GetParameter param) throws NoSuchElementException, IOException
|
||||
public StorageEntry get(GetParameter param) throws NoSuchElementException, IOException
|
||||
{
|
||||
/* Load a KadContent if any exist for the given criteria */
|
||||
try
|
||||
|
@ -1,11 +1,14 @@
|
||||
package kademlia.dht;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import kademlia.node.NodeId;
|
||||
|
||||
/**
|
||||
* Any piece of content that needs to be stored on the DHT
|
||||
*
|
||||
* @author Joshua Kissoon
|
||||
* @param <T>
|
||||
*
|
||||
* @since 20140224
|
||||
*/
|
||||
public interface KadContent
|
||||
@ -42,13 +45,7 @@ public interface KadContent
|
||||
*/
|
||||
public String getOwnerId();
|
||||
|
||||
public default byte[] toBytes()
|
||||
{
|
||||
return new byte[2];
|
||||
}
|
||||
|
||||
public default void fromBytes(byte[] data)
|
||||
{
|
||||
public byte[] toBytes();
|
||||
|
||||
}
|
||||
public KadContent fromBytes(byte[] data);
|
||||
}
|
||||
|
@ -8,16 +8,28 @@ package kademlia.dht;
|
||||
*/
|
||||
public class StorageEntry
|
||||
{
|
||||
private byte[] content;
|
||||
private StorageEntryMetadata metadata;
|
||||
|
||||
private final byte[] content;
|
||||
private final StorageEntryMetadata metadata;
|
||||
|
||||
public StorageEntry(KadContent content)
|
||||
{
|
||||
|
||||
this(content, new StorageEntryMetadata(content));
|
||||
}
|
||||
|
||||
public StorageEntry(KadContent content, StorageEntryMetadata metadata)
|
||||
{
|
||||
this.content = content.g
|
||||
this.content = content.toBytes();
|
||||
this.metadata = metadata;
|
||||
}
|
||||
|
||||
public byte[] getContent()
|
||||
{
|
||||
return this.content;
|
||||
}
|
||||
|
||||
public StorageEntryMetadata getContentMetadata()
|
||||
{
|
||||
return this.metadata;
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ package kademlia.message;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import kademlia.dht.KadContent;
|
||||
import kademlia.dht.StorageEntry;
|
||||
import kademlia.node.Node;
|
||||
import kademlia.serializer.JsonSerializer;
|
||||
|
||||
@ -18,7 +18,7 @@ public class ContentMessage implements Message
|
||||
|
||||
public static final byte CODE = 0x04;
|
||||
|
||||
private byte[] content;
|
||||
private StorageEntry content;
|
||||
private Node origin;
|
||||
|
||||
/**
|
||||
@ -26,7 +26,7 @@ public class ContentMessage implements Message
|
||||
* @param content The content to be stored
|
||||
*
|
||||
*/
|
||||
public ContentMessage(Node origin, byte[] content)
|
||||
public ContentMessage(Node origin, StorageEntry content)
|
||||
{
|
||||
this.content = content;
|
||||
this.origin = origin;
|
||||
@ -43,8 +43,7 @@ public class ContentMessage implements Message
|
||||
this.origin.toStream(out);
|
||||
|
||||
/* Serialize the KadContent, then send it to the stream */
|
||||
out.writeInt(content.length);
|
||||
out.write(content);
|
||||
new JsonSerializer<StorageEntry>().write(content, out);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -52,9 +51,14 @@ public class ContentMessage implements Message
|
||||
{
|
||||
this.origin = new Node(in);
|
||||
|
||||
final int length = in.readInt();
|
||||
this.content = new byte[length];
|
||||
in.read(content);
|
||||
try
|
||||
{
|
||||
this.content = new JsonSerializer<StorageEntry>().read(in);
|
||||
}
|
||||
catch (ClassNotFoundException e)
|
||||
{
|
||||
System.err.println("ClassNotFoundException when reading StorageEntry; Message: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public Node getOrigin()
|
||||
@ -62,7 +66,7 @@ public class ContentMessage implements Message
|
||||
return this.origin;
|
||||
}
|
||||
|
||||
public byte[] getContent()
|
||||
public StorageEntry getContent()
|
||||
{
|
||||
return this.content;
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import kademlia.dht.KadContent;
|
||||
import kademlia.dht.StorageEntry;
|
||||
import kademlia.node.Node;
|
||||
import kademlia.serializer.JsonSerializer;
|
||||
|
||||
@ -18,7 +19,7 @@ public class StoreContentMessage implements Message
|
||||
|
||||
public static final byte CODE = 0x08;
|
||||
|
||||
private KadContent content;
|
||||
private StorageEntry content;
|
||||
private Node origin;
|
||||
|
||||
/**
|
||||
@ -26,7 +27,7 @@ public class StoreContentMessage implements Message
|
||||
* @param content The content to be stored
|
||||
*
|
||||
*/
|
||||
public StoreContentMessage(Node origin, KadContent content)
|
||||
public StoreContentMessage(Node origin, StorageEntry content)
|
||||
{
|
||||
this.content = content;
|
||||
this.origin = origin;
|
||||
@ -43,7 +44,7 @@ public class StoreContentMessage implements Message
|
||||
this.origin.toStream(out);
|
||||
|
||||
/* Serialize the KadContent, then send it to the stream */
|
||||
new JsonSerializer<KadContent>().write(content, out);
|
||||
new JsonSerializer<StorageEntry>().write(content, out);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -52,7 +53,7 @@ public class StoreContentMessage implements Message
|
||||
this.origin = new Node(in);
|
||||
try
|
||||
{
|
||||
this.content = new JsonSerializer<KadContent>().read(in);
|
||||
this.content = new JsonSerializer<StorageEntry>().read(in);
|
||||
}
|
||||
catch (ClassNotFoundException e)
|
||||
{
|
||||
@ -65,7 +66,7 @@ public class StoreContentMessage implements Message
|
||||
return this.origin;
|
||||
}
|
||||
|
||||
public KadContent getContent()
|
||||
public StorageEntry getContent()
|
||||
{
|
||||
return this.content;
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ import java.util.TreeMap;
|
||||
import kademlia.core.GetParameter;
|
||||
import kademlia.core.KadConfiguration;
|
||||
import kademlia.core.KadServer;
|
||||
import kademlia.dht.KadContent;
|
||||
import kademlia.dht.StorageEntry;
|
||||
import kademlia.exceptions.RoutingException;
|
||||
import kademlia.exceptions.UnknownMessageException;
|
||||
import kademlia.message.ContentLookupMessage;
|
||||
@ -42,7 +42,7 @@ public class ContentLookupOperation implements Operation, Receiver
|
||||
private final KadServer server;
|
||||
private final Node localNode;
|
||||
private final GetParameter params;
|
||||
private final List<KadContent> contentFound;
|
||||
private final List<StorageEntry> contentFound;
|
||||
private final int numResultsReq;
|
||||
private final KadConfiguration config;
|
||||
|
||||
@ -250,7 +250,7 @@ public class ContentLookupOperation implements Operation, Receiver
|
||||
this.localNode.getRoutingTable().insert(msg.getOrigin());
|
||||
|
||||
/* Get the Content and check if it satisfies the required parameters */
|
||||
KadContent content = msg.getContent();
|
||||
StorageEntry content = msg.getContent();
|
||||
System.out.println("Content Received: " + content);
|
||||
|
||||
/*@todo Check if the content matches the given criteria */
|
||||
@ -313,7 +313,7 @@ public class ContentLookupOperation implements Operation, Receiver
|
||||
/**
|
||||
* @return The list of all content found during the lookup operation
|
||||
*/
|
||||
public List<KadContent> getContentFound()
|
||||
public List<StorageEntry> getContentFound()
|
||||
{
|
||||
return this.contentFound;
|
||||
}
|
||||
|
@ -2,7 +2,6 @@ package kademlia.operation;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import kademlia.core.DefaultConfiguration;
|
||||
import kademlia.core.KadConfiguration;
|
||||
import kademlia.core.KadServer;
|
||||
import kademlia.dht.DHT;
|
||||
|
@ -6,6 +6,7 @@ import kademlia.core.KadConfiguration;
|
||||
import kademlia.core.KadServer;
|
||||
import kademlia.dht.DHT;
|
||||
import kademlia.dht.KadContent;
|
||||
import kademlia.dht.StorageEntry;
|
||||
import kademlia.message.Message;
|
||||
import kademlia.message.StoreContentMessage;
|
||||
import kademlia.node.Node;
|
||||
@ -50,7 +51,7 @@ public class StoreOperation implements Operation
|
||||
List<Node> nodes = ndlo.getClosestNodes();
|
||||
|
||||
/* Create the message */
|
||||
Message msg = new StoreContentMessage(this.localNode, this.content);
|
||||
Message msg = new StoreContentMessage(this.localNode, new StorageEntry(this.content));
|
||||
|
||||
/*Store the message on all of the K-Nodes*/
|
||||
for (Node n : nodes)
|
||||
|
@ -25,7 +25,7 @@ public class AutoRefreshOperationTest
|
||||
final Kademlia kad2 = new Kademlia("Crystal", new NodeId("AJDHR678947584567464"), 4585);
|
||||
final Kademlia kad3 = new Kademlia("Shameer", new NodeId("AS84k6789KRNS45KFJ8W"), 8104);
|
||||
final Kademlia kad4 = new Kademlia("Lokesh.", new NodeId("ASF45678947A845674GG"), 8335);
|
||||
final Kademlia kad5 = new Kademlia("Chandu.", new NodeId("AS84RUD894758456dyrj"), 13345);
|
||||
final Kademlia kad5 = new Kademlia("Chandu.", new NodeId("AS84kUD894758456dyrj"), 13345);
|
||||
|
||||
/* Connecting nodes */
|
||||
System.out.println("Connecting Nodes");
|
||||
|
@ -4,7 +4,7 @@ import java.io.IOException;
|
||||
import java.util.List;
|
||||
import kademlia.core.GetParameter;
|
||||
import kademlia.Kademlia;
|
||||
import kademlia.dht.KadContent;
|
||||
import kademlia.dht.StorageEntry;
|
||||
import kademlia.node.NodeId;
|
||||
|
||||
/**
|
||||
@ -37,14 +37,15 @@ public class ContentSendingTest
|
||||
* Lets retrieve the content
|
||||
*/
|
||||
System.out.println("Retrieving Content");
|
||||
GetParameter gp = new GetParameter(c.getKey());
|
||||
GetParameter gp = new GetParameter(c.getKey(), DHTContentImpl.TYPE);
|
||||
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)
|
||||
List<StorageEntry> conte = kad2.get(gp, 4);
|
||||
for (StorageEntry cc : conte)
|
||||
{
|
||||
System.out.println("Content Found: " + cc);
|
||||
System.out.println("Content Found: " + new DHTContentImpl().fromBytes(cc.getContent()));
|
||||
System.out.println("Content Metadata: " + cc.getContentMetadata());
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
package kademlia.tests;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import kademlia.dht.KadContent;
|
||||
import kademlia.node.NodeId;
|
||||
|
||||
@ -12,18 +13,21 @@ import kademlia.node.NodeId;
|
||||
public class DHTContentImpl implements KadContent
|
||||
{
|
||||
|
||||
private final NodeId key;
|
||||
private NodeId key;
|
||||
private String data;
|
||||
private final String ownerId;
|
||||
private final long createTs, updateTs;
|
||||
|
||||
public static final String TYPE = "DHTContentImpl";
|
||||
private String ownerId;
|
||||
private long createTs, updateTs;
|
||||
|
||||
|
||||
{
|
||||
this.createTs = this.updateTs = System.currentTimeMillis() / 1000L;
|
||||
}
|
||||
|
||||
public DHTContentImpl()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public DHTContentImpl(String ownerId, String data)
|
||||
{
|
||||
this.ownerId = ownerId;
|
||||
@ -42,11 +46,6 @@ public class DHTContentImpl implements KadContent
|
||||
this.data = newData;
|
||||
}
|
||||
|
||||
public String toBytes()
|
||||
{
|
||||
return this.data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NodeId getKey()
|
||||
{
|
||||
@ -77,6 +76,22 @@ public class DHTContentImpl implements KadContent
|
||||
return this.updateTs;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public byte[] toBytes()
|
||||
{
|
||||
Gson gson = new Gson();
|
||||
return gson.toJson(this).getBytes();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DHTContentImpl fromBytes(byte[] data)
|
||||
{
|
||||
Gson gson = new Gson();
|
||||
DHTContentImpl val = gson.fromJson(new String(data), DHTContentImpl.class);
|
||||
return val;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
|
@ -4,7 +4,7 @@ import java.io.IOException;
|
||||
import java.util.List;
|
||||
import kademlia.core.GetParameter;
|
||||
import kademlia.Kademlia;
|
||||
import kademlia.dht.KadContent;
|
||||
import kademlia.dht.StorageEntry;
|
||||
import kademlia.node.NodeId;
|
||||
|
||||
/**
|
||||
@ -30,10 +30,10 @@ public class RefreshOperationTest
|
||||
kad2.put(c);
|
||||
|
||||
/* Lets retrieve the content */
|
||||
GetParameter gp = new GetParameter(c.getKey());
|
||||
GetParameter gp = new GetParameter(c.getKey(), DHTContentImpl.TYPE);
|
||||
gp.setType(DHTContentImpl.TYPE);
|
||||
gp.setOwnerId(c.getOwnerId());
|
||||
List<KadContent> conte = kad2.get(gp, 1);
|
||||
List<StorageEntry> conte = kad2.get(gp, 1);
|
||||
|
||||
kad2.refresh();
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ package kademlia.tests;
|
||||
import java.util.List;
|
||||
import kademlia.Kademlia;
|
||||
import kademlia.core.GetParameter;
|
||||
import kademlia.dht.KadContent;
|
||||
import kademlia.dht.StorageEntry;
|
||||
import kademlia.node.NodeId;
|
||||
|
||||
/**
|
||||
@ -53,11 +53,11 @@ public class SaveStateTest2
|
||||
|
||||
/* Trying to get a content stored on the restored node */
|
||||
GetParameter gp = new GetParameter(c.getKey(), kad2.getOwnerId(), c.getType());
|
||||
List<KadContent> content = kad2.get(gp, 1);
|
||||
List<StorageEntry> content = kad2.get(gp, 1);
|
||||
|
||||
if (!content.isEmpty())
|
||||
{
|
||||
DHTContentImpl cc = (DHTContentImpl) content.get(0);
|
||||
DHTContentImpl cc = new DHTContentImpl().fromBytes(content.get(0).getContent());
|
||||
System.out.println("Content received: " + cc);
|
||||
}
|
||||
else
|
||||
|
Loading…
Reference in New Issue
Block a user