mirror of
https://github.com/ChronosX88/KademliaDHT.git
synced 2024-12-23 08:11:47 +00:00
Problem with serializing the DHT also, had to create a DHT specific Serializer class
This commit is contained in:
parent
e2ca9326c9
commit
22fee9116a
@ -25,6 +25,7 @@ import kademlia.operation.Operation;
|
||||
import kademlia.operation.KadRefreshOperation;
|
||||
import kademlia.operation.StoreOperation;
|
||||
import kademlia.routing.RoutingTable;
|
||||
import kademlia.serializer.JsonDHTSerializer;
|
||||
import kademlia.serializer.JsonRoutingTableSerializer;
|
||||
import kademlia.serializer.JsonSerializer;
|
||||
|
||||
@ -42,6 +43,7 @@ import kademlia.serializer.JsonSerializer;
|
||||
* @todo If we're trying to send a message to this node, just cancel the sending process and handle the message right here
|
||||
* @todo Keep this node in it's own routing table - it helps for ContentRefresh operation - easy to check whether this node is one of the k-nodes for a content
|
||||
* @todo Move DHT.getContentStorageFolderName to the Configuration class
|
||||
* @todo Implement Kademlia.ping() operation.
|
||||
*
|
||||
*/
|
||||
public class Kademlia
|
||||
@ -152,7 +154,7 @@ public class Kademlia
|
||||
* @section Read the DHT
|
||||
*/
|
||||
din = new DataInputStream(new FileInputStream(getStateStorageFolderName(ownerId) + File.separator + "dht.kns"));
|
||||
DHT idht = new JsonSerializer<DHT>().read(din);
|
||||
DHT idht = new JsonDHTSerializer().read(din);
|
||||
System.out.println("Finished reading data.");
|
||||
return new Kademlia(ownerId, inode, ikad.getPort(), idht);
|
||||
}
|
||||
@ -319,7 +321,7 @@ public class Kademlia
|
||||
* @section Save the DHT
|
||||
*/
|
||||
dout = new DataOutputStream(new FileOutputStream(getStateStorageFolderName(this.ownerId) + File.separator + "dht.kns"));
|
||||
new JsonSerializer<DHT>().write(this.dht, dout);
|
||||
new JsonDHTSerializer().write(this.dht, dout);
|
||||
|
||||
System.out.println("FInished saving state");
|
||||
|
||||
@ -381,6 +383,11 @@ public class Kademlia
|
||||
sb.append(this.localNode.getRoutingTable());
|
||||
sb.append("\n");
|
||||
|
||||
sb.append("\n");
|
||||
sb.append("DHT: ");
|
||||
sb.append(this.dht);
|
||||
sb.append("\n");
|
||||
|
||||
sb.append("\n\n\n");
|
||||
|
||||
return sb.toString();
|
||||
|
@ -23,15 +23,27 @@ import kademlia.serializer.JsonSerializer;
|
||||
public class DHT
|
||||
{
|
||||
|
||||
private final StorageEntryManager entriesManager;
|
||||
private transient StorageEntryManager entriesManager;
|
||||
private transient final JsonSerializer<KadContent> contentSerializer;
|
||||
|
||||
|
||||
{
|
||||
entriesManager = new StorageEntryManager();
|
||||
contentSerializer = new JsonSerializer<>();
|
||||
}
|
||||
|
||||
public DHT()
|
||||
{
|
||||
this.initialize();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize this DHT to it's default state
|
||||
*/
|
||||
public final void initialize()
|
||||
{
|
||||
entriesManager = new StorageEntryManager();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle storing content locally
|
||||
*
|
||||
@ -178,4 +190,24 @@ public class DHT
|
||||
{
|
||||
return entriesManager.getAllEntries();
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to add a list of storage entries for existing content to the DHT.
|
||||
* Mainly used when retrieving StorageEntries from a saved state file.
|
||||
*
|
||||
* @param ientries The entries to add
|
||||
*/
|
||||
public void putStorageEntries(List<StorageEntry> ientries)
|
||||
{
|
||||
for (StorageEntry e : ientries)
|
||||
{
|
||||
this.entriesManager.put(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return this.entriesManager.toString();
|
||||
}
|
||||
}
|
||||
|
@ -70,12 +70,7 @@ public class StorageEntry
|
||||
}
|
||||
|
||||
/* Check that key matches */
|
||||
if ((params.getKey() != null) && (!params.getKey().equals(this.key)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return ((params.getKey() != null) && (!params.getKey().equals(this.key)));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -98,4 +93,23 @@ public class StorageEntry
|
||||
hash = 23 * hash + Objects.hashCode(this.type);
|
||||
return hash;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder("[StorageEntry: ");
|
||||
|
||||
sb.append("{Key: ");
|
||||
sb.append(this.key);
|
||||
sb.append("} ");
|
||||
sb.append("{Owner: ");
|
||||
sb.append(this.ownerId);
|
||||
sb.append("} ");
|
||||
sb.append("{Type: ");
|
||||
sb.append(this.type);
|
||||
sb.append("} ");
|
||||
sb.append("]");
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ import kademlia.node.NodeId;
|
||||
* @author Joshua Kissoon
|
||||
* @since 20140226
|
||||
*/
|
||||
public class StorageEntryManager
|
||||
class StorageEntryManager
|
||||
{
|
||||
|
||||
private final Map<NodeId, List<StorageEntry>> entries;
|
||||
@ -34,6 +34,16 @@ public class StorageEntryManager
|
||||
public void put(KadContent content)
|
||||
{
|
||||
StorageEntry entry = new StorageEntry(content);
|
||||
this.put(entry);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new entry to our storage
|
||||
*
|
||||
* @param entry The StorageEntry to store
|
||||
*/
|
||||
public void put(StorageEntry entry)
|
||||
{
|
||||
if (!this.entries.containsKey(entry.getKey()))
|
||||
{
|
||||
this.entries.put(entry.getKey(), new ArrayList<StorageEntry>());
|
||||
@ -116,4 +126,26 @@ public class StorageEntryManager
|
||||
|
||||
return entriesRet;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder("Stored Content: \n");
|
||||
for (List<StorageEntry> es : this.entries.values())
|
||||
{
|
||||
if (entries.size() < 1)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
for (StorageEntry e : es)
|
||||
{
|
||||
sb.append(e);
|
||||
sb.append("\n");
|
||||
}
|
||||
}
|
||||
|
||||
sb.append("\n");
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
@ -30,12 +30,24 @@ public class RoutingTable
|
||||
this.localNode = localNode;
|
||||
|
||||
/* Initialize all of the buckets to a specific depth */
|
||||
this.initializeBuckets();
|
||||
this.initialize();
|
||||
|
||||
/* @todo Insert the local node */
|
||||
//this.insert(localNode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the RoutingTable to it's default state
|
||||
*/
|
||||
public final void initialize()
|
||||
{
|
||||
this.buckets = new KadBucket[NodeId.ID_LENGTH];
|
||||
for (int i = 0; i < NodeId.ID_LENGTH; i++)
|
||||
{
|
||||
buckets[i] = new KadBucket(i);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new node to the routing table
|
||||
*
|
||||
@ -180,18 +192,6 @@ public class RoutingTable
|
||||
this.buckets = buckets;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the kadBuckets to be empty
|
||||
*/
|
||||
public final void initializeBuckets()
|
||||
{
|
||||
this.buckets = new KadBucket[NodeId.ID_LENGTH];
|
||||
for (int i = 0; i < NodeId.ID_LENGTH; i++)
|
||||
{
|
||||
buckets[i] = new KadBucket(i);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String toString()
|
||||
{
|
||||
|
94
src/kademlia/serializer/JsonDHTSerializer.java
Normal file
94
src/kademlia/serializer/JsonDHTSerializer.java
Normal file
@ -0,0 +1,94 @@
|
||||
package kademlia.serializer;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import com.google.gson.stream.JsonReader;
|
||||
import com.google.gson.stream.JsonWriter;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.List;
|
||||
import kademlia.dht.DHT;
|
||||
import kademlia.dht.StorageEntry;
|
||||
|
||||
/**
|
||||
* A KadSerializer that serializes DHT to JSON format
|
||||
* The generic serializer is not working for DHT
|
||||
*
|
||||
* Why a DHT specific serializer?
|
||||
* The DHT structure:
|
||||
* - DHT
|
||||
* -- StorageEntriesManager
|
||||
* --- Map<NodeId, List<StorageEntry>>
|
||||
* ---- NodeId:KeyBytes
|
||||
* ---- List<StorageEntry>
|
||||
* ----- StorageEntry: Key, OwnerId, Type, Hash
|
||||
*
|
||||
* The above structure seems to be causing some problem for Gson, especially at the Map part.
|
||||
*
|
||||
* Solution
|
||||
* - Make the StorageEntriesManager transient
|
||||
* - Simply store all StorageEntry in the serialized object
|
||||
* - When reloading, re-add all StorageEntry to the DHT
|
||||
*
|
||||
* @author Joshua Kissoon
|
||||
*
|
||||
* @since 20140310
|
||||
*/
|
||||
public class JsonDHTSerializer implements KadSerializer<DHT>
|
||||
{
|
||||
|
||||
private final Gson gson;
|
||||
private final Type storageEntriesCollectionType;
|
||||
|
||||
|
||||
{
|
||||
gson = new Gson();
|
||||
|
||||
storageEntriesCollectionType = new TypeToken<List<StorageEntry>>()
|
||||
{
|
||||
}.getType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(DHT data, DataOutputStream out) throws IOException
|
||||
{
|
||||
try (JsonWriter writer = new JsonWriter(new OutputStreamWriter(out)))
|
||||
{
|
||||
writer.beginArray();
|
||||
|
||||
/* Write the basic DHT */
|
||||
gson.toJson(data, DHT.class, writer);
|
||||
|
||||
/* Now Store the Entries */
|
||||
gson.toJson(data.getStorageEntries(), this.storageEntriesCollectionType, writer);
|
||||
|
||||
writer.endArray();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public DHT read(DataInputStream in) throws IOException, ClassNotFoundException
|
||||
{
|
||||
try (DataInputStream din = new DataInputStream(in);
|
||||
JsonReader reader = new JsonReader(new InputStreamReader(in)))
|
||||
{
|
||||
reader.beginArray();
|
||||
|
||||
/* Read the basic DHT */
|
||||
DHT dht = gson.fromJson(reader, DHT.class);
|
||||
dht.initialize();
|
||||
|
||||
/* Now get the entries and add them back to the DHT */
|
||||
List<StorageEntry> entries = gson.fromJson(reader, this.storageEntriesCollectionType);
|
||||
dht.putStorageEntries(entries);
|
||||
|
||||
reader.endArray();
|
||||
return dht;
|
||||
}
|
||||
}
|
||||
}
|
@ -36,7 +36,7 @@ import kademlia.node.Node;
|
||||
*
|
||||
* @author Joshua Kissoon
|
||||
*
|
||||
* @since 20140225
|
||||
* @since 20140310
|
||||
*/
|
||||
public class JsonRoutingTableSerializer implements KadSerializer<RoutingTable>
|
||||
{
|
||||
@ -85,7 +85,7 @@ public class JsonRoutingTableSerializer implements KadSerializer<RoutingTable>
|
||||
{
|
||||
}.getType();
|
||||
List<Node> nodes = gson.fromJson(reader, collectionType);
|
||||
tbl.initializeBuckets();
|
||||
tbl.initialize();
|
||||
|
||||
for (Node n : nodes)
|
||||
{
|
||||
|
@ -73,6 +73,6 @@ public class DHTContentImpl implements KadContent
|
||||
|
||||
public String toString()
|
||||
{
|
||||
return "DHTContentImpl[data=" + this.data + "]";
|
||||
return "DHTContentImpl[{data=" + this.data + "{ {key:"+this.key + "}]";
|
||||
}
|
||||
}
|
||||
|
@ -12,21 +12,28 @@ import kademlia.node.NodeId;
|
||||
public class SaveStateTest
|
||||
{
|
||||
|
||||
public static void main(String[] args)
|
||||
public SaveStateTest()
|
||||
{
|
||||
try
|
||||
{
|
||||
/* Setting up 2 Kad networks */
|
||||
Kademlia kad1 = new Kademlia("JoshuaK", new NodeId("ASF45678947584567467"), 7574);
|
||||
Kademlia kad2 = new Kademlia("Crystal", new NodeId("ASERTKJDHGVHERJHGFLK"), 7572);
|
||||
Kademlia kad1 = new Kademlia("JoshuaK", new NodeId("ASF45678947584567467"), 7529);
|
||||
Kademlia kad2 = new Kademlia("Crystal", new NodeId("ASERTKJDHGVHERJHGFLK"), 7532);
|
||||
|
||||
/* Connecting 2 to 1 */
|
||||
System.out.println("Connecting Kad 1 and Kad 2");
|
||||
kad1.connect(kad2.getNode());
|
||||
|
||||
|
||||
synchronized (this)
|
||||
{
|
||||
DHTContentImpl c = new DHTContentImpl(kad2.getOwnerId(), "Some Data");
|
||||
System.out.println(c);
|
||||
kad2.put(c);
|
||||
}
|
||||
|
||||
System.out.println(kad1);
|
||||
System.out.println(kad2);
|
||||
|
||||
|
||||
/* Shutting down kad1 and restarting it */
|
||||
System.out.println("\n\n\nShutting down Kad instance");
|
||||
kad1.shutdown();
|
||||
@ -40,4 +47,9 @@ public class SaveStateTest
|
||||
e.printStackTrace();;
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
new SaveStateTest();
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user