diff --git a/apps/i2psnark/java/src/net/i2p/kademlia/KBucketSet.java b/apps/i2psnark/java/src/net/i2p/kademlia/KBucketSet.java index b87a7624a67d0438984916c4ede3cc53eda6fd6f..b84cdc66cf5151e5adfac19985016dd4caace023 100644 --- a/apps/i2psnark/java/src/net/i2p/kademlia/KBucketSet.java +++ b/apps/i2psnark/java/src/net/i2p/kademlia/KBucketSet.java @@ -209,10 +209,10 @@ public class KBucketSet<T extends SimpleDataStructure> { int s1, e1, s2, e2; s1 = b0.getRangeBegin(); e2 = b0.getRangeEnd(); - if (B_FACTOR > 1 && - (s1 & (B_FACTOR - 1)) == 0 && - ((e2 + 1) & (B_FACTOR - 1)) == 0 && - e2 > s1 + B_FACTOR) { + if (B_VALUE == 1 || + ((s1 & (B_FACTOR - 1)) == 0 && + ((e2 + 1) & (B_FACTOR - 1)) == 0 && + e2 > s1 + B_FACTOR)) { // The bucket is a "whole" kbucket with a range > B_FACTOR, // so it should be split into two "whole" kbuckets each with // a range >= B_FACTOR. @@ -526,17 +526,14 @@ public class KBucketSet<T extends SimpleDataStructure> { public List<T> getExploreKeys(long age) { List<T> rv = new ArrayList(_buckets.size()); long old = _context.clock().now() - age; - int prevSize = -1; getReadLock(); try { for (KBucket b : _buckets) { int curSize = b.getKeyCount(); - // The first few buckets are all empty, we only need one - // explore key for all of them. - if ((prevSize != 0 || curSize != 0) && + // Always explore the closest bucket + if ((b.getRangeBegin() == 0) || (b.getLastChanged() < old || curSize < BUCKET_SIZE * 3 / 4)) rv.add(generateRandomKey(b)); - prevSize = curSize; } } finally { releaseReadLock(); } return rv; @@ -765,8 +762,8 @@ public class KBucketSet<T extends SimpleDataStructure> { public String toString() { StringBuilder buf = new StringBuilder(1024); buf.append("Bucket set rooted on: ").append(_us.toString()) - .append(" K= ").append(BUCKET_SIZE) - .append(" B= ").append(B_VALUE) + .append(" K=").append(BUCKET_SIZE) + .append(" B=").append(B_VALUE) .append(" with ").append(size()) .append(" keys in ").append(_buckets.size()).append(" buckets:\n"); getReadLock(); diff --git a/apps/i2psnark/java/src/org/klomp/snark/dht/DHTNodes.java b/apps/i2psnark/java/src/org/klomp/snark/dht/DHTNodes.java index ee0e8f01fde6f23e16848e95090933a96bc46085..21d394a807843452e44e4f2ff7d9ff0bdaada345 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/dht/DHTNodes.java +++ b/apps/i2psnark/java/src/org/klomp/snark/dht/DHTNodes.java @@ -89,8 +89,13 @@ class DHTNodes { * @return the old value if present, else null */ public NodeInfo putIfAbsent(NodeInfo nInfo) { - _kad.add(nInfo.getNID()); - return _nodeMap.putIfAbsent(nInfo.getNID(), nInfo); + NodeInfo rv = _nodeMap.putIfAbsent(nInfo.getNID(), nInfo); + // ensure same object in both places + if (rv != null) + _kad.add(rv.getNID()); + else + _kad.add(nInfo.getNID()); + return rv; } public NodeInfo remove(NID nid) { diff --git a/apps/i2psnark/java/src/org/klomp/snark/dht/KRPC.java b/apps/i2psnark/java/src/org/klomp/snark/dht/KRPC.java index 910841e79134e779dda97f66671ac39feb359ad5..55521a7876f081fdaf00937c1ef801aa4643c969 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/dht/KRPC.java +++ b/apps/i2psnark/java/src/org/klomp/snark/dht/KRPC.java @@ -1108,8 +1108,12 @@ public class KRPC implements I2PSessionMuxedListener, DHT { if (nInfo.equals(_myNodeInfo)) return _myNodeInfo; NodeInfo rv = _knownNodes.putIfAbsent(nInfo); - if (rv == null) + if (rv == null) { rv = nInfo; + // if we didn't know about it before, set the timestamp + // so it isn't immediately removed by the DHTNodes cleaner + rv.getNID().setLastSeen(); + } return rv; } diff --git a/apps/i2psnark/java/src/org/klomp/snark/web/I2PSnarkServlet.java b/apps/i2psnark/java/src/org/klomp/snark/web/I2PSnarkServlet.java index d0ff6b06643f0c694037eecfbdef58bf0a195155..ea5d751e554cbc2062acdf1343b72d11374c4c18 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/web/I2PSnarkServlet.java +++ b/apps/i2psnark/java/src/org/klomp/snark/web/I2PSnarkServlet.java @@ -1638,7 +1638,7 @@ public class I2PSnarkServlet extends DefaultServlet { out.write("\" ></td></tr>\n" + "<tr><td>"); - out.write(_("Enable DHT") + " (**BETA**)"); + out.write(_("Enable DHT")); out.write(": <td><input type=\"checkbox\" class=\"optbox\" name=\"useDHT\" value=\"true\" " + (useDHT ? "checked " : "") + "title=\"");