Fixed the bug that was causing replication of content files and StorageEntries. RefreshOperation working well!!

This commit is contained in:
Joshua Kissoon 2014-03-22 15:27:22 +05:30
parent b93133337c
commit d9fdcc57fd
8 changed files with 134 additions and 44 deletions

View File

@ -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.

View File

@ -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 */
}
}
}

View File

@ -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
*/

View File

@ -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()

View File

@ -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
*

View 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);
}
}

View File

@ -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)

View File

@ -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 + "}]";