diff --git a/src/kademlia/core/Kademlia.java b/src/kademlia/core/Kademlia.java index c21df31..16ee161 100644 --- a/src/kademlia/core/Kademlia.java +++ b/src/kademlia/core/Kademlia.java @@ -16,7 +16,6 @@ import kademlia.node.NodeId; import kademlia.operation.ConnectOperation; import kademlia.operation.ContentLookupOperation; import kademlia.operation.Operation; -import kademlia.operation.BucketRefreshOperation; import kademlia.operation.KadRefreshOperation; import kademlia.operation.StoreOperation; @@ -137,9 +136,11 @@ public class Kademlia */ public int put(KadContent content) throws IOException { - new StoreOperation(server, localNode, content).execute(); - /*@todo Return how many nodes the content was stored on */ - return 10; + StoreOperation sop = new StoreOperation(server, localNode, content); + sop.execute(); + + /* Return how many nodes the content was stored on */ + return sop.numNodesStoredAt(); } /** diff --git a/src/kademlia/dht/DHT.java b/src/kademlia/dht/DHT.java index 300cc74..4a31e2c 100644 --- a/src/kademlia/dht/DHT.java +++ b/src/kademlia/dht/DHT.java @@ -77,6 +77,34 @@ public class DHT return this.entriesManager.contains(param); } + /** + * Retrieve and create a KadContent object given the StorageEntry object + * + * @param entry The StorageEntry used to retrieve this content + * + * @return KadContent The content object + * + * @throws java.io.IOException + */ + public KadContent get(StorageEntry entry) throws IOException, NoSuchElementException + { + try + { + return this.retrieve(entry.getKey(), entry.getContentHash()); + } + catch (FileNotFoundException e) + { + System.err.println("Error while loading file for content. Message: " + e.getMessage()); + } + catch (ClassNotFoundException e) + { + System.err.println("The class for some content was not found. Message: " + e.getMessage()); + } + + /* If we got here, means we got no entries */ + throw new NoSuchElementException(); + } + /** * Get the StorageEntry for the content if any exist, * retrieve the KadContent from the storage system and return it @@ -94,15 +122,14 @@ public class DHT { StorageEntry e = this.entriesManager.get(param); return this.retrieve(e.getKey(), e.getContentHash()); - } catch (FileNotFoundException e) { - System.err.println("Error while loading file for content."); + System.err.println("Error while loading file for content. Message: " + e.getMessage()); } catch (ClassNotFoundException e) { - System.err.println("The class for some content was not found."); + System.err.println("The class for some content was not found. Message: " + e.getMessage()); } /* If we got here, means we got no entries */ diff --git a/src/kademlia/operation/ContentRefreshOperation.java b/src/kademlia/operation/ContentRefreshOperation.java index cc2b0a5..0ee79dd 100644 --- a/src/kademlia/operation/ContentRefreshOperation.java +++ b/src/kademlia/operation/ContentRefreshOperation.java @@ -1,7 +1,14 @@ package kademlia.operation; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import kademlia.core.Configuration; import kademlia.core.KadServer; import kademlia.dht.DHT; +import kademlia.dht.StorageEntry; +import kademlia.message.Message; +import kademlia.message.StoreContentMessage; import kademlia.node.Node; /** @@ -29,14 +36,44 @@ public class ContentRefreshOperation implements Operation * Also delete the content if this node is no longer one of the K closest nodes * * We assume that our RoutingTable is updated, and we can get the K closest nodes from that table + * + * @throws java.io.IOException */ @Override - public void execute() + public void execute() throws IOException { - - /** - * @todo Delete any content on this node that this node is not one of the K-Closest nodes to - */ + /* Get a list of all storage entries for content */ + List entries = this.dht.getStorageEntries(); + + /* For each storage entry, distribute it */ + for (StorageEntry e : entries) + { + /** + * @todo - Paper improvement 1 - + * Check last update time of this entry and + * only distribute it if it has been last updated > 1 hour ago + */ + /* Get the K closest nodes to this entries */ + List closestNodes = this.localNode.getRoutingTable().findClosest(e.getKey(), Configuration.K); + + /* Create the message */ + Message msg = new StoreContentMessage(this.localNode, dht.get(e)); + + /*Store the message on all of the K-Nodes*/ + for (Node n : closestNodes) + { + /*We don't need to again store the content locally, it's already here*/ + if (!n.equals(this.localNode)) + { + /* Send a contentstore operation to the K-Closest nodes */ + this.server.sendMessage(n, msg, null); + } + } + + /** + * @todo Delete any content on this node that this node is not one of the K-Closest nodes to + */ + } } } diff --git a/src/kademlia/operation/StoreOperation.java b/src/kademlia/operation/StoreOperation.java index 21896be..3ce9af4 100644 --- a/src/kademlia/operation/StoreOperation.java +++ b/src/kademlia/operation/StoreOperation.java @@ -51,12 +51,25 @@ public class StoreOperation implements Operation { if (n.equals(this.localNode)) { - /* Store the content locally */ + /* @todo Store the content locally */ } else { + /** + * @todo Create a receiver that recieves a store acknowledgement message to count how many nodes a content have been stored at + */ this.server.sendMessage(n, msg, null); } } } + + /** + * @return The number of nodes that have stored this content + * + * @todo Implement this method + */ + public int numNodesStoredAt() + { + return 1; + } } diff --git a/src/kademlia/routing/RoutingTable.java b/src/kademlia/routing/RoutingTable.java index 07c8ed9..069f6d1 100644 --- a/src/kademlia/routing/RoutingTable.java +++ b/src/kademlia/routing/RoutingTable.java @@ -6,7 +6,6 @@ package kademlia.routing; import java.util.ArrayList; -import java.util.BitSet; import java.util.List; import kademlia.node.Node; import kademlia.node.NodeId;