From eee38a626dc5c139d347b3a23db837f4399c2c0b Mon Sep 17 00:00:00 2001
From: zzz <zzz@mail.i2p>
Date: Fri, 2 Nov 2012 15:58:26 +0000
Subject: [PATCH]  * i2psnark:    - Split buckets correctly    - More
 exploration fixes

---
 .../java/src/net/i2p/kademlia/KBucketSet.java | 19 ++++++++-----------
 .../src/org/klomp/snark/dht/DHTNodes.java     |  9 +++++++--
 .../java/src/org/klomp/snark/dht/KRPC.java    |  6 +++++-
 .../org/klomp/snark/web/I2PSnarkServlet.java  |  2 +-
 4 files changed, 21 insertions(+), 15 deletions(-)

diff --git a/apps/i2psnark/java/src/net/i2p/kademlia/KBucketSet.java b/apps/i2psnark/java/src/net/i2p/kademlia/KBucketSet.java
index b87a7624a6..b84cdc66cf 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 ee0e8f01fd..21d394a807 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 910841e791..55521a7876 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 d0ff6b0664..ea5d751e55 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=\"");
-- 
GitLab