mirror of
https://github.com/ChronosX88/KademliaDHT.git
synced 2024-12-23 08:11:47 +00:00
Fixed the bug that was causing replication of content files and StorageEntries. RefreshOperation working well!!
This commit is contained in:
parent
b93133337c
commit
d9fdcc57fd
@ -11,7 +11,7 @@ public class Configuration
|
||||
/**
|
||||
* Interval in milliseconds between execution of RestoreOperations.
|
||||
* */
|
||||
public static long RESTORE_INTERVAL = 60 * 60 * 1000;
|
||||
public static long RESTORE_INTERVAL = 60 * 1000; // Default at 1 hour
|
||||
|
||||
/**
|
||||
* If no reply received from a node in this period (in milliseconds)
|
||||
@ -37,7 +37,7 @@ public class Configuration
|
||||
/**
|
||||
* Bucket size.
|
||||
* */
|
||||
public static int K = 5;
|
||||
public static int K = 2;
|
||||
|
||||
/**
|
||||
* Size of replacement cache.
|
||||
|
@ -11,6 +11,7 @@ import java.util.List;
|
||||
import java.util.NoSuchElementException;
|
||||
import kademlia.core.Configuration;
|
||||
import kademlia.core.GetParameter;
|
||||
import kademlia.exceptions.ContentExistException;
|
||||
import kademlia.node.NodeId;
|
||||
import kademlia.serializer.JsonSerializer;
|
||||
|
||||
@ -54,12 +55,19 @@ public class DHT
|
||||
public void store(KadContent content) throws IOException
|
||||
{
|
||||
/* Keep track of this content in the entries manager */
|
||||
this.entriesManager.put(content);
|
||||
try
|
||||
{
|
||||
StorageEntry sEntry = this.entriesManager.put(content);
|
||||
|
||||
/* Now we store the content locally in a file */
|
||||
String contentStorageFolder = this.getContentStorageFolderName(content.getKey());
|
||||
DataOutputStream dout = new DataOutputStream(new FileOutputStream(contentStorageFolder + File.separator + content.hashCode() + ".kct"));
|
||||
contentSerializer.write(content, dout);
|
||||
/* Now we store the content locally in a file */
|
||||
String contentStorageFolder = this.getContentStorageFolderName(content.getKey());
|
||||
DataOutputStream dout = new DataOutputStream(new FileOutputStream(contentStorageFolder + File.separator + sEntry.hashCode() + ".kct"));
|
||||
contentSerializer.write(content, dout);
|
||||
}
|
||||
catch (ContentExistException e)
|
||||
{
|
||||
/* Content already exist on the DHT, no need to do anything here */
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -102,7 +110,7 @@ public class DHT
|
||||
{
|
||||
try
|
||||
{
|
||||
return this.retrieve(entry.getKey(), entry.getContentHash());
|
||||
return this.retrieve(entry.getKey(), entry.hashCode());
|
||||
}
|
||||
catch (FileNotFoundException e)
|
||||
{
|
||||
@ -133,7 +141,7 @@ public class DHT
|
||||
try
|
||||
{
|
||||
StorageEntry e = this.entriesManager.get(param);
|
||||
return this.retrieve(e.getKey(), e.getContentHash());
|
||||
return this.retrieve(e.getKey(), e.hashCode());
|
||||
}
|
||||
catch (FileNotFoundException e)
|
||||
{
|
||||
@ -201,7 +209,14 @@ public class DHT
|
||||
{
|
||||
for (StorageEntry e : ientries)
|
||||
{
|
||||
this.entriesManager.put(e);
|
||||
try
|
||||
{
|
||||
this.entriesManager.put(e);
|
||||
}
|
||||
catch (ContentExistException ex)
|
||||
{
|
||||
/* Entry already exist, no need to store it again */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -29,6 +29,14 @@ public interface KadContent
|
||||
*/
|
||||
public long getCreatedTimestamp();
|
||||
|
||||
/**
|
||||
* Each content will have an update timestamp
|
||||
* This allows the DHT to keep only the latest version of a content
|
||||
*
|
||||
* @return long The timestamp of when this content was last updated
|
||||
*/
|
||||
public long getLastUpdatedTimestamp();
|
||||
|
||||
/**
|
||||
* @return The ID of the owner of this content
|
||||
*/
|
||||
|
@ -18,6 +18,7 @@ public class StorageEntry
|
||||
private final String ownerId;
|
||||
private final String type;
|
||||
private final int contentHash;
|
||||
private final long lastUpdated;
|
||||
|
||||
public StorageEntry(KadContent content)
|
||||
{
|
||||
@ -25,6 +26,7 @@ public class StorageEntry
|
||||
this.ownerId = content.getOwnerId();
|
||||
this.type = content.getType();
|
||||
this.contentHash = content.hashCode();
|
||||
this.lastUpdated = content.getLastUpdatedTimestamp();
|
||||
}
|
||||
|
||||
public NodeId getKey()
|
||||
@ -109,7 +111,7 @@ public class StorageEntry
|
||||
sb.append(this.type);
|
||||
sb.append("} ");
|
||||
sb.append("]");
|
||||
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.NoSuchElementException;
|
||||
import kademlia.core.GetParameter;
|
||||
import kademlia.exceptions.ContentExistException;
|
||||
import kademlia.node.NodeId;
|
||||
|
||||
/**
|
||||
@ -31,10 +32,9 @@ class StorageEntryManager
|
||||
*
|
||||
* @param content The content to store a reference to
|
||||
*/
|
||||
public void put(KadContent content)
|
||||
public StorageEntry put(KadContent content) throws ContentExistException
|
||||
{
|
||||
StorageEntry entry = new StorageEntry(content);
|
||||
this.put(entry);
|
||||
return this.put(new StorageEntry(content));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -42,13 +42,24 @@ class StorageEntryManager
|
||||
*
|
||||
* @param entry The StorageEntry to store
|
||||
*/
|
||||
public void put(StorageEntry entry)
|
||||
public StorageEntry put(StorageEntry entry) throws ContentExistException
|
||||
{
|
||||
if (!this.entries.containsKey(entry.getKey()))
|
||||
{
|
||||
this.entries.put(entry.getKey(), new ArrayList<StorageEntry>());
|
||||
}
|
||||
this.entries.get(entry.getKey()).add(entry);
|
||||
|
||||
/* If this entry doesn't already exist, then we add it */
|
||||
if (!this.contains(entry))
|
||||
{
|
||||
this.entries.get(entry.getKey()).add(entry);
|
||||
|
||||
return entry;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ContentExistException("Content already exists on this DHT");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -77,6 +88,27 @@ class StorageEntryManager
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a content exist in the DHT
|
||||
*/
|
||||
public boolean contains(KadContent content)
|
||||
{
|
||||
return this.contains(new StorageEntry(content));
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a StorageEntry exist on this DHT
|
||||
*/
|
||||
private boolean contains(StorageEntry entry)
|
||||
{
|
||||
if (this.entries.containsKey(entry.getKey()))
|
||||
{
|
||||
return this.entries.get(entry.getKey()).contains(entry);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if our DHT has a Content for the given criteria
|
||||
*
|
||||
|
21
src/kademlia/exceptions/ContentExistException.java
Normal file
21
src/kademlia/exceptions/ContentExistException.java
Normal file
@ -0,0 +1,21 @@
|
||||
package kademlia.exceptions;
|
||||
|
||||
/**
|
||||
* An exception used to indicate that a content already exist on the DHT
|
||||
*
|
||||
* @author Joshua Kissoon
|
||||
* @created 20140322
|
||||
*/
|
||||
public class ContentExistException extends Exception
|
||||
{
|
||||
|
||||
public ContentExistException()
|
||||
{
|
||||
super();
|
||||
}
|
||||
|
||||
public ContentExistException(String message)
|
||||
{
|
||||
super(message);
|
||||
}
|
||||
}
|
@ -1,5 +1,9 @@
|
||||
package kademlia.tests;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
import kademlia.core.Configuration;
|
||||
import kademlia.core.Kademlia;
|
||||
import kademlia.node.NodeId;
|
||||
|
||||
@ -17,31 +21,22 @@ public class AutoRefreshOperationTest
|
||||
try
|
||||
{
|
||||
/* Setting up 2 Kad networks */
|
||||
Kademlia kad1 = new Kademlia("JoshuaK", new NodeId("ASF45678947584567463"), 12049);
|
||||
Kademlia kad2 = new Kademlia("Crystal", new NodeId("ASF45678947584567464"), 4585);
|
||||
Kademlia kad3 = new Kademlia("Shameer", new NodeId("ASF45678947584567465"), 8104);
|
||||
Kademlia kad4 = new Kademlia("Lokesh", new NodeId("ASF45678947584567466"), 8335);
|
||||
Kademlia kad5 = new Kademlia("Chandu", new NodeId("ASF45678947584567467"), 13345);
|
||||
final Kademlia kad1 = new Kademlia("JoshuaK", new NodeId("ASF45678947584567463"), 12049);
|
||||
final Kademlia kad2 = new Kademlia("Crystal", new NodeId("ASF45678947584567464"), 4585);
|
||||
final Kademlia kad3 = new Kademlia("Shameer", new NodeId("ASF45678947584567465"), 8104);
|
||||
final Kademlia kad4 = new Kademlia("Lokesh", new NodeId("ASF45678947584567466"), 8335);
|
||||
final Kademlia kad5 = new Kademlia("Chandu", new NodeId("ASF45678947584567467"), 13345);
|
||||
|
||||
/* Connecting nodes */
|
||||
System.out.println("Connecting Nodes 1 & 2");
|
||||
System.out.println("Connecting Nodes");
|
||||
kad2.bootstrap(kad1.getNode());
|
||||
kad3.bootstrap(kad2.getNode());
|
||||
kad4.bootstrap(kad2.getNode());
|
||||
kad5.bootstrap(kad4.getNode());
|
||||
|
||||
System.out.println(kad1);
|
||||
System.out.println(kad2);
|
||||
System.out.println(kad3);
|
||||
System.out.println(kad4);
|
||||
System.out.println(kad5);
|
||||
|
||||
DHTContentImpl c = new DHTContentImpl(kad2.getOwnerId(), "Some Data");
|
||||
kad2.put(c);
|
||||
System.out.println("\n\n\n\nSTORING CONTENT 2\n\n\n\n");
|
||||
DHTContentImpl c2 = new DHTContentImpl(kad2.getOwnerId(), "Some other Data");
|
||||
System.out.println(c2);
|
||||
kad4.put(c2);
|
||||
DHTContentImpl c = new DHTContentImpl(kad1.getOwnerId(), "Some Data");
|
||||
kad1.putLocally(c);
|
||||
System.out.println("\nSTORING CONTENT 1 locally on " + kad1.getOwnerId() + "\n\n\n\n");
|
||||
|
||||
System.out.println(kad1);
|
||||
System.out.println(kad2);
|
||||
@ -49,14 +44,24 @@ public class AutoRefreshOperationTest
|
||||
System.out.println(kad4);
|
||||
System.out.println(kad5);
|
||||
|
||||
/* Shutting down kad1 and restarting it */
|
||||
System.out.println("\n\n\nShutting down Kad instance");
|
||||
System.out.println(kad2);
|
||||
kad1.shutdown();
|
||||
|
||||
System.out.println("\n\n\nReloading Kad instance from file");
|
||||
Kademlia kadR2 = Kademlia.loadFromFile("JoshuaK");
|
||||
System.out.println(kadR2);
|
||||
/* Print the node states every few minutes */
|
||||
Timer timer = new Timer(true);
|
||||
timer.schedule(
|
||||
new TimerTask()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
System.out.println(kad1);
|
||||
System.out.println(kad2);
|
||||
System.out.println(kad3);
|
||||
System.out.println(kad4);
|
||||
System.out.println(kad5);
|
||||
}
|
||||
},
|
||||
// Delay // Interval
|
||||
Configuration.RESTORE_INTERVAL, Configuration.RESTORE_INTERVAL
|
||||
);
|
||||
}
|
||||
|
||||
catch (Exception e)
|
||||
|
@ -15,13 +15,13 @@ public class DHTContentImpl implements KadContent
|
||||
private final NodeId key;
|
||||
private String data;
|
||||
private final String ownerId;
|
||||
private final long createTs;
|
||||
private final long createTs, updateTs;
|
||||
|
||||
public static final String TYPE = "DHTContentImpl";
|
||||
|
||||
|
||||
{
|
||||
this.createTs = System.currentTimeMillis() / 1000L;
|
||||
this.createTs = this.updateTs = System.currentTimeMillis() / 1000L;
|
||||
}
|
||||
|
||||
public DHTContentImpl(String ownerId, String data)
|
||||
@ -71,6 +71,13 @@ public class DHTContentImpl implements KadContent
|
||||
return this.createTs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLastUpdatedTimestamp()
|
||||
{
|
||||
return this.updateTs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return "DHTContentImpl[{data=" + this.data + "{ {key:" + this.key + "}]";
|
||||
|
Loading…
Reference in New Issue
Block a user