mirror of
https://github.com/ChronosX88/KademliaDHT.git
synced 2024-11-22 02:02:21 +00:00
Setup Content Updating
- Didn't do this before, but now it's setup: content will be updated on the DHT if a StoreContentMessage is sent with a newer version of the content GetParameter - Updated the GetParameter so that it can be constructed from a KadContent object or a StorageEntryMetadata object - Move it to the DHT package Others - Added a few methods to StorageEntryMetadata, StorageEntryManager& DHT to simplify conversions between KadContent, GetParameter & StorageEntryMetadata Tests - Written a test to check content updating
This commit is contained in:
parent
cc1d03ba81
commit
2dde2a75e0
@ -14,7 +14,7 @@ import java.util.NoSuchElementException;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
import kademlia.core.DefaultConfiguration;
|
||||
import kademlia.core.GetParameter;
|
||||
import kademlia.dht.GetParameter;
|
||||
import kademlia.core.KadConfiguration;
|
||||
import kademlia.core.KadServer;
|
||||
import kademlia.dht.DHT;
|
||||
|
@ -9,7 +9,6 @@ import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.NoSuchElementException;
|
||||
import kademlia.core.GetParameter;
|
||||
import kademlia.core.KadConfiguration;
|
||||
import kademlia.exceptions.ContentExistException;
|
||||
import kademlia.exceptions.ContentNotFoundException;
|
||||
@ -77,13 +76,43 @@ public class DHT
|
||||
*
|
||||
* @param content The DHT content to store
|
||||
*
|
||||
* @return boolean true if we stored the content, false if the content already exists and is up to date
|
||||
*
|
||||
* @throws java.io.IOException
|
||||
*/
|
||||
public void store(StorageEntry content) throws IOException
|
||||
public boolean store(StorageEntry content) throws IOException
|
||||
{
|
||||
/* Keep track of this content in the entries manager */
|
||||
/* Lets check if we have this content and it's the updated version */
|
||||
if (this.entriesManager.contains(content.getContentMetadata()))
|
||||
{
|
||||
StorageEntryMetadata current = this.entriesManager.get(content.getContentMetadata());
|
||||
if (current.getLastUpdatedTimestamp() >= content.getContentMetadata().getLastUpdatedTimestamp())
|
||||
{
|
||||
/* We have the current content, no need to update it! just leave this method now */
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We have this content, but not the latest version, lets delete it so the new version will be added below */
|
||||
try
|
||||
{
|
||||
this.remove(content.getContentMetadata());
|
||||
}
|
||||
catch (ContentNotFoundException ex)
|
||||
{
|
||||
/* @todo Log an error here */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If we got here means we don't have this content, or we need to update the content
|
||||
* If we need to update the content, the code above would've already deleted it, so we just need to re-add it
|
||||
*/
|
||||
try
|
||||
{
|
||||
System.out.println("Adding new content.");
|
||||
/* Keep track of this content in the entries manager */
|
||||
StorageEntryMetadata sEntry = this.entriesManager.put(content.getContentMetadata());
|
||||
|
||||
/* Now we store the content locally in a file */
|
||||
@ -94,16 +123,19 @@ public class DHT
|
||||
{
|
||||
this.getSerializer().write(content, dout);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
catch (ContentExistException e)
|
||||
{
|
||||
/* Content already exist on the DHT, no need to do anything here */
|
||||
/* @todo Content already exist on the DHT, log an error here */
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void store(KadContent content) throws IOException
|
||||
public boolean store(KadContent content) throws IOException
|
||||
{
|
||||
this.store(new StorageEntry(content));
|
||||
return this.store(new StorageEntry(content));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,4 +1,4 @@
|
||||
package kademlia.core;
|
||||
package kademlia.dht;
|
||||
|
||||
import kademlia.node.NodeId;
|
||||
|
||||
@ -35,15 +35,55 @@ public class GetParameter
|
||||
* Construct a GetParameter to search for data by NodeId, owner, type
|
||||
*
|
||||
* @param key
|
||||
* @param owner
|
||||
* @param type
|
||||
* @param owner
|
||||
*/
|
||||
public GetParameter(NodeId key, String owner, String type)
|
||||
public GetParameter(NodeId key, String type, String owner)
|
||||
{
|
||||
this(key, owner);
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct our get parameter from a Content
|
||||
*
|
||||
* @param c
|
||||
*/
|
||||
public GetParameter(KadContent c)
|
||||
{
|
||||
this.key = c.getKey();
|
||||
|
||||
if (c.getType() != null)
|
||||
{
|
||||
this.type = c.getType();
|
||||
}
|
||||
|
||||
if (c.getOwnerId() != null)
|
||||
{
|
||||
this.ownerId = c.getOwnerId();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct our get parameter from a StorageEntryMeta data
|
||||
*
|
||||
* @param md
|
||||
*/
|
||||
public GetParameter(StorageEntryMetadata md)
|
||||
{
|
||||
this.key = md.getKey();
|
||||
|
||||
if (md.getType() != null)
|
||||
{
|
||||
this.type = md.getType();
|
||||
}
|
||||
|
||||
if (md.getOwnerId() != null)
|
||||
{
|
||||
this.ownerId = md.getOwnerId();
|
||||
}
|
||||
}
|
||||
|
||||
public NodeId getKey()
|
||||
{
|
||||
return this.key;
|
@ -5,7 +5,6 @@ import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.NoSuchElementException;
|
||||
import kademlia.core.GetParameter;
|
||||
import kademlia.exceptions.ContentExistException;
|
||||
import kademlia.exceptions.ContentNotFoundException;
|
||||
import kademlia.node.NodeId;
|
||||
@ -76,7 +75,6 @@ class StorageEntryManager
|
||||
{
|
||||
if (this.entries.containsKey(param.getKey()))
|
||||
{
|
||||
System.out.println("Does contain the key");
|
||||
/* Content with this key exist, check if any match the rest of the search criteria */
|
||||
for (StorageEntryMetadata e : this.entries.get(param.getKey()))
|
||||
{
|
||||
@ -89,7 +87,6 @@ class StorageEntryManager
|
||||
}
|
||||
else
|
||||
{
|
||||
System.out.println("Does not contain the key");
|
||||
System.out.println(this);
|
||||
}
|
||||
return false;
|
||||
@ -100,20 +97,15 @@ class StorageEntryManager
|
||||
*/
|
||||
public boolean contains(KadContent content)
|
||||
{
|
||||
return this.contains(new StorageEntryMetadata(content));
|
||||
return this.contains(new GetParameter(content));
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a StorageEntry exist on this DHT
|
||||
*/
|
||||
private boolean contains(StorageEntryMetadata entry)
|
||||
public boolean contains(StorageEntryMetadata entry)
|
||||
{
|
||||
if (this.entries.containsKey(entry.getKey()))
|
||||
{
|
||||
return this.entries.get(entry.getKey()).contains(entry);
|
||||
}
|
||||
|
||||
return false;
|
||||
return this.contains(new GetParameter(entry));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -148,6 +140,11 @@ class StorageEntryManager
|
||||
}
|
||||
}
|
||||
|
||||
public StorageEntryMetadata get(StorageEntryMetadata md)
|
||||
{
|
||||
return this.get(new GetParameter(md));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return A list of all storage entries
|
||||
*/
|
||||
|
@ -1,7 +1,6 @@
|
||||
package kademlia.dht;
|
||||
|
||||
import java.util.Objects;
|
||||
import kademlia.core.GetParameter;
|
||||
import kademlia.node.NodeId;
|
||||
|
||||
/**
|
||||
@ -18,7 +17,7 @@ public class StorageEntryMetadata
|
||||
private final String ownerId;
|
||||
private final String type;
|
||||
private final int contentHash;
|
||||
private final long lastUpdated;
|
||||
private final long updatedTs;
|
||||
|
||||
public StorageEntryMetadata(KadContent content)
|
||||
{
|
||||
@ -26,7 +25,7 @@ public class StorageEntryMetadata
|
||||
this.ownerId = content.getOwnerId();
|
||||
this.type = content.getType();
|
||||
this.contentHash = content.hashCode();
|
||||
this.lastUpdated = content.getLastUpdatedTimestamp();
|
||||
this.updatedTs = content.getLastUpdatedTimestamp();
|
||||
}
|
||||
|
||||
public NodeId getKey()
|
||||
@ -49,6 +48,11 @@ public class StorageEntryMetadata
|
||||
return this.contentHash;
|
||||
}
|
||||
|
||||
public long getLastUpdatedTimestamp()
|
||||
{
|
||||
return this.updatedTs;
|
||||
}
|
||||
|
||||
/**
|
||||
* When a node is looking for content, he sends the search criteria in a GetParameter object
|
||||
* Here we take this GetParameter object and check if this StorageEntry satisfies the given parameters
|
||||
|
@ -3,7 +3,7 @@ package kademlia.message;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import kademlia.core.GetParameter;
|
||||
import kademlia.dht.GetParameter;
|
||||
import kademlia.node.Node;
|
||||
import kademlia.serializer.JsonSerializer;
|
||||
|
||||
|
@ -9,7 +9,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.SortedMap;
|
||||
import java.util.TreeMap;
|
||||
import kademlia.core.GetParameter;
|
||||
import kademlia.dht.GetParameter;
|
||||
import kademlia.core.KadConfiguration;
|
||||
import kademlia.core.KadServer;
|
||||
import kademlia.dht.StorageEntry;
|
||||
|
@ -2,7 +2,7 @@ package kademlia.tests;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import kademlia.core.GetParameter;
|
||||
import kademlia.dht.GetParameter;
|
||||
import kademlia.Kademlia;
|
||||
import kademlia.dht.StorageEntry;
|
||||
import kademlia.node.NodeId;
|
||||
|
64
src/kademlia/tests/ContentUpdatingTest.java
Normal file
64
src/kademlia/tests/ContentUpdatingTest.java
Normal file
@ -0,0 +1,64 @@
|
||||
package kademlia.tests;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import kademlia.dht.GetParameter;
|
||||
import kademlia.Kademlia;
|
||||
import kademlia.dht.StorageEntry;
|
||||
import kademlia.node.NodeId;
|
||||
|
||||
/**
|
||||
* Testing sending and receiving content between 2 Nodes on a network
|
||||
*
|
||||
* @author Joshua Kissoon
|
||||
* @since 20140224
|
||||
*/
|
||||
public class ContentUpdatingTest
|
||||
{
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
try
|
||||
{
|
||||
/* Setting up 2 Kad networks */
|
||||
Kademlia kad1 = new Kademlia("JoshuaK", new NodeId("ASF45678947584567467"), 7574);
|
||||
System.out.println("Created Node Kad 1: " + kad1.getNode().getNodeId());
|
||||
Kademlia kad2 = new Kademlia("Crystal", new NodeId("ASERTKJDHGVHERJHGFLK"), 7572);
|
||||
System.out.println("Created Node Kad 2: " + kad2.getNode().getNodeId());
|
||||
kad2.bootstrap(kad1.getNode());
|
||||
|
||||
/* Lets create the content and share it */
|
||||
DHTContentImpl c = new DHTContentImpl(kad2.getOwnerId(), "Some Data");
|
||||
kad2.put(c);
|
||||
|
||||
/* Lets retrieve the content */
|
||||
System.out.println("Retrieving Content");
|
||||
GetParameter gp = new GetParameter(c.getKey(), DHTContentImpl.TYPE, c.getOwnerId());
|
||||
System.out.println("Get Parameter: " + gp);
|
||||
List<StorageEntry> conte = kad2.get(gp, 4);
|
||||
for (StorageEntry cc : conte)
|
||||
{
|
||||
System.out.println("Content Found: " + new DHTContentImpl().fromBytes(cc.getContent()));
|
||||
System.out.println("Content Metadata: " + cc.getContentMetadata());
|
||||
}
|
||||
|
||||
/* Lets update the content and put it again */
|
||||
c.setData("Some New Data");
|
||||
kad2.put(c);
|
||||
|
||||
/* Lets retrieve the content */
|
||||
System.out.println("Retrieving Content Again");
|
||||
conte = kad2.get(gp, 4);
|
||||
for (StorageEntry cc : conte)
|
||||
{
|
||||
System.out.println("Content Found: " + new DHTContentImpl().fromBytes(cc.getContent()));
|
||||
System.out.println("Content Metadata: " + cc.getContentMetadata());
|
||||
}
|
||||
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
@ -18,7 +18,8 @@ public class DHTContentImpl implements KadContent
|
||||
private NodeId key;
|
||||
private String data;
|
||||
private String ownerId;
|
||||
private long createTs, updateTs;
|
||||
private final long createTs;
|
||||
private long updateTs;
|
||||
|
||||
|
||||
{
|
||||
@ -46,6 +47,7 @@ public class DHTContentImpl implements KadContent
|
||||
public void setData(String newData)
|
||||
{
|
||||
this.data = newData;
|
||||
this.setUpdated();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -66,6 +68,14 @@ public class DHTContentImpl implements KadContent
|
||||
return this.ownerId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the content as updated
|
||||
*/
|
||||
public void setUpdated()
|
||||
{
|
||||
this.updateTs = System.currentTimeMillis() / 1000L;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getCreatedTimestamp()
|
||||
{
|
||||
|
@ -2,7 +2,7 @@ package kademlia.tests;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import kademlia.core.GetParameter;
|
||||
import kademlia.dht.GetParameter;
|
||||
import kademlia.Kademlia;
|
||||
import kademlia.dht.StorageEntry;
|
||||
import kademlia.node.NodeId;
|
||||
|
@ -2,7 +2,7 @@ package kademlia.tests;
|
||||
|
||||
import java.util.List;
|
||||
import kademlia.Kademlia;
|
||||
import kademlia.core.GetParameter;
|
||||
import kademlia.dht.GetParameter;
|
||||
import kademlia.dht.StorageEntry;
|
||||
import kademlia.node.NodeId;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user