diff --git a/src/kademlia/Kademlia.java b/src/kademlia/Kademlia.java index 5cddf76..9ad3c07 100644 --- a/src/kademlia/Kademlia.java +++ b/src/kademlia/Kademlia.java @@ -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 get(GetParameter param, int numResultsReq) throws NoSuchElementException, IOException + public List get(GetParameter param, int numResultsReq) throws NoSuchElementException, IOException { List contentFound; if (this.dht.contains(param)) diff --git a/src/kademlia/core/GetParameter.java b/src/kademlia/core/GetParameter.java index edd730b..169ed49 100644 --- a/src/kademlia/core/GetParameter.java +++ b/src/kademlia/core/GetParameter.java @@ -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; } /** diff --git a/src/kademlia/dht/DHT.java b/src/kademlia/dht/DHT.java index 404ad76..8e2ef51 100644 --- a/src/kademlia/dht/DHT.java +++ b/src/kademlia/dht/DHT.java @@ -27,7 +27,7 @@ public class DHT { private transient StorageEntryManager entriesManager; - private transient KadSerializer contentSerializer = null; + private transient KadSerializer serializer = null; private transient KadConfiguration config; private final String ownerId; @@ -62,14 +62,14 @@ public class DHT * * @return The new ContentSerializer */ - public KadSerializer getContentSerializer() + public KadSerializer 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 diff --git a/src/kademlia/dht/KadContent.java b/src/kademlia/dht/KadContent.java index 2fd3715..3033fba 100644 --- a/src/kademlia/dht/KadContent.java +++ b/src/kademlia/dht/KadContent.java @@ -1,16 +1,19 @@ 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 + * * @since 20140224 */ public interface KadContent { - + /** * @return NodeId The DHT key for this content */ @@ -42,13 +45,7 @@ public interface KadContent */ public String getOwnerId(); - public default byte[] toBytes() - { - return new byte[2]; - } + public byte[] toBytes(); - public default void fromBytes(byte[] data) - { - - } + public KadContent fromBytes(byte[] data); } diff --git a/src/kademlia/dht/StorageEntry.java b/src/kademlia/dht/StorageEntry.java index fb748d0..eb69b1c 100644 --- a/src/kademlia/dht/StorageEntry.java +++ b/src/kademlia/dht/StorageEntry.java @@ -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; } } diff --git a/src/kademlia/message/ContentMessage.java b/src/kademlia/message/ContentMessage.java index 7e117e2..8da6a20 100644 --- a/src/kademlia/message/ContentMessage.java +++ b/src/kademlia/message/ContentMessage.java @@ -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().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().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; } diff --git a/src/kademlia/message/StoreContentMessage.java b/src/kademlia/message/StoreContentMessage.java index 4d67542..6ffba1b 100644 --- a/src/kademlia/message/StoreContentMessage.java +++ b/src/kademlia/message/StoreContentMessage.java @@ -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().write(content, out); + new JsonSerializer().write(content, out); } @Override @@ -52,7 +53,7 @@ public class StoreContentMessage implements Message this.origin = new Node(in); try { - this.content = new JsonSerializer().read(in); + this.content = new JsonSerializer().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; } diff --git a/src/kademlia/operation/ContentLookupOperation.java b/src/kademlia/operation/ContentLookupOperation.java index fcb2cb3..312d360 100644 --- a/src/kademlia/operation/ContentLookupOperation.java +++ b/src/kademlia/operation/ContentLookupOperation.java @@ -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 contentFound; + private final List 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 getContentFound() + public List getContentFound() { return this.contentFound; } diff --git a/src/kademlia/operation/ContentRefreshOperation.java b/src/kademlia/operation/ContentRefreshOperation.java index 1818a93..052fdad 100644 --- a/src/kademlia/operation/ContentRefreshOperation.java +++ b/src/kademlia/operation/ContentRefreshOperation.java @@ -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; diff --git a/src/kademlia/operation/StoreOperation.java b/src/kademlia/operation/StoreOperation.java index f914c2f..d80bfb2 100644 --- a/src/kademlia/operation/StoreOperation.java +++ b/src/kademlia/operation/StoreOperation.java @@ -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 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) diff --git a/src/kademlia/tests/AutoRefreshOperationTest.java b/src/kademlia/tests/AutoRefreshOperationTest.java index c209f77..d1d4b0d 100644 --- a/src/kademlia/tests/AutoRefreshOperationTest.java +++ b/src/kademlia/tests/AutoRefreshOperationTest.java @@ -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"); diff --git a/src/kademlia/tests/ContentSendingTest.java b/src/kademlia/tests/ContentSendingTest.java index 1eb3761..0230b54 100644 --- a/src/kademlia/tests/ContentSendingTest.java +++ b/src/kademlia/tests/ContentSendingTest.java @@ -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 conte = kad2.get(gp, 1); - for (KadContent cc : conte) + List 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()); } } diff --git a/src/kademlia/tests/DHTContentImpl.java b/src/kademlia/tests/DHTContentImpl.java index 6b1864b..0ef3b60 100644 --- a/src/kademlia/tests/DHTContentImpl.java +++ b/src/kademlia/tests/DHTContentImpl.java @@ -1,5 +1,6 @@ package kademlia.tests; +import com.google.gson.Gson; import kademlia.dht.KadContent; import kademlia.node.NodeId; @@ -12,17 +13,20 @@ 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) { @@ -42,11 +46,6 @@ public class DHTContentImpl implements KadContent this.data = newData; } - public String toBytes() - { - return this.data; - } - @Override public NodeId getKey() { @@ -76,6 +75,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() diff --git a/src/kademlia/tests/RefreshOperationTest.java b/src/kademlia/tests/RefreshOperationTest.java index 160e4b5..2c04fca 100644 --- a/src/kademlia/tests/RefreshOperationTest.java +++ b/src/kademlia/tests/RefreshOperationTest.java @@ -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 conte = kad2.get(gp, 1); + List conte = kad2.get(gp, 1); kad2.refresh(); } diff --git a/src/kademlia/tests/SaveStateTest2.java b/src/kademlia/tests/SaveStateTest2.java index f01e52a..20c379b 100644 --- a/src/kademlia/tests/SaveStateTest2.java +++ b/src/kademlia/tests/SaveStateTest2.java @@ -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 content = kad2.get(gp, 1); + List 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