@Test public void testStorables() throws Exception { Context dht = (Context) MojitoFactory.createDHT("bootstrap"); dht.getStorableModelManager().addStorableModel(DHTValueType.TEXT, new Dht.Model()); dht.bind(new InetSocketAddress("localhost", 8080)); dht.start(); Context node = (Context) MojitoFactory.createDHT("node"); node.getStorableModelManager().addStorableModel(DHTValueType.TEXT, new Dht.Model()); node.bind(new InetSocketAddress("localhost", 8081)); node.start(); node.bootstrap(new InetSocketAddress("localhost", 8080)).get(); assertTrue(node.isBootstrapped()); DHTValueImpl value = new DHTValueImpl(DHTValueType.TEXT, Version.ZERO, "hello world".getBytes()); node.put(Keys.of("key"), value).get(); FindValueResult result = node.get(EntityKey.createEntityKey(Keys.of("key"), DHTValueType.TEXT)).get(); assertTrue(result.isSuccess()); assertEquals(1, result.getEntities().size()); assertEquals( "hello world", new String(result.getEntities().iterator().next().getValue().getValue())); node.close(); dht.close(); }
@Test public void testCreatorAddressIsCorrect() throws Exception { Context root = (Context) MojitoFactory.createDHT("bootstrap"); root.bind(new InetSocketAddress("localhost", 8081)); root.start(); Context dht = (Context) MojitoFactory.createDHT("dht"); dht.bind(new InetSocketAddress("localhost", 8080)); dht.start(); dht.bootstrap(new InetSocketAddress("localhost", 8081)).get(); assertTrue(dht.isBootstrapped()); DHTValueImpl value = new DHTValueImpl(DHTValueType.TEXT, Version.ZERO, "hello world".getBytes()); StoreResult store = dht.put(Keys.of("key"), value).get(); assertEquals(2, store.getLocations().size()); FindValueResult result = dht.get(EntityKey.createEntityKey(Keys.of("key"), DHTValueType.TEXT)).get(); assertTrue(result.isSuccess()); assertEquals(1, result.getEntities().size()); DHTValueEntity entity = result.getEntities().iterator().next(); assertEquals( InetSocketAddress.createUnresolved("localhost", 8080), entity.getCreator().getContactAddress()); assertEquals( InetSocketAddress.createUnresolved("localhost", 8081), entity.getSender().getContactAddress()); root.close(); dht.close(); }
/** * Adds the given <code>Contact</code> or updates it if it's already in our <code>RouteTable * </code> */ private synchronized void addLiveContactInfo(Contact node, DHTMessage message) { RouteTable routeTable = context.getRouteTable(); // If the Node is going to shutdown then don't bother // further than this. if (node.isShutdown()) { if (LOG.isInfoEnabled()) { LOG.info(node + " is going to shut down"); } synchronized (routeTable) { // Make sure there's an existing Contact in the RouteTable. // Otherwise don't bother! Contact existing = routeTable.get(node.getNodeID()); if (node.equals(existing)) { // Update the new Contact in the RouteTable and // mark it as shutdown // mark the existing contact as shutdown if its alive or // it will not be removed. if (existing.isAlive()) existing.shutdown(true); routeTable.add(node); node.shutdown(true); } } return; } // Ignore firewalled Nodes if (node.isFirewalled()) { if (LOG.isInfoEnabled()) { LOG.info(node + " is firewalled"); } return; } if (ContactUtils.isPrivateAddress(node)) { if (LOG.isInfoEnabled()) { LOG.info(node + " has a private address"); } return; } KUID nodeId = node.getNodeID(); if (context.isLocalNodeID(nodeId)) { // This is expected if there's a Node ID collision assert (message instanceof PingResponse) : "Expected a PingResponse but got a " + message.getClass() + " from " + message.getContact(); if (LOG.isInfoEnabled()) { LOG.info("Looks like our NodeID collides with " + node); } return; } if (StoreSettings.STORE_FORWARD_ENABLED.getValue()) { // Only do store forward if it is a new node in our routing table // (we are (re)connecting to the network) or a node that is reconnecting Contact existing = routeTable.get(nodeId); if (existing == null || existing.isDead() || existing.getInstanceID() != node.getInstanceID()) { // Store forward only if we're bootstrapped if (context.isBootstrapped()) { int k = KademliaSettings.REPLICATION_PARAMETER.getValue(); // we select the 2*k closest nodes in order to also check those values // where the local node is part of the k closest to the value but not part // of the k closest to the new joining node. Collection<Contact> nodes = routeTable.select(nodeId, 2 * k, SelectMode.ALL); // Are we one of the K nearest Nodes to the contact? if (containsNodeID(nodes, context.getLocalNodeID())) { if (LOG.isTraceEnabled()) { LOG.trace( "Node " + node + " is new or has changed his instanceID, will check for store forward!"); } forwardOrRemoveValues(node, existing, message); } } } } // Add the Node to our RouteTable or if it's // already there update its timeStamp and whatsoever routeTable.add(node); }