* NetDb: Tweak some logging on lease problems

* Shitlist:
      - Add shitlistForever() and isShitlistedForever(), unused for now
      - Sort the HTML output by router hash
    * config.jsp: Add another warning
    * netdb.jsp:
      - Sort the lease HTML output by dest hash, local first
      - Sort the router HTML output by router hash
This commit is contained in:
zzz
2008-06-07 17:44:13 +00:00
parent 88e26224c2
commit f3b8c73e96
4 changed files with 101 additions and 35 deletions

View File

@ -1,3 +1,13 @@
2008-06-07 zzz
* NetDb: Tweak some logging on lease problems
* Shitlist:
- Add shitlistForever() and isShitlistedForever(), unused for now
- Sort the HTML output by router hash
* config.jsp: Add another warning
* netdb.jsp:
- Sort the lease HTML output by dest hash, local first
- Sort the router HTML output by router hash
2008-06-06 zzz 2008-06-06 zzz
* LeaseSet: * LeaseSet:
- Sort the leases by expiration date in TunnelPool.locked_buildNewLeaseSet() - Sort the leases by expiration date in TunnelPool.locked_buildNewLeaseSet()

View File

@ -17,7 +17,7 @@ import net.i2p.CoreVersion;
public class RouterVersion { public class RouterVersion {
public final static String ID = "$Revision: 1.548 $ $Date: 2008-02-10 15:00:00 $"; public final static String ID = "$Revision: 1.548 $ $Date: 2008-02-10 15:00:00 $";
public final static String VERSION = "0.6.1.33"; public final static String VERSION = "0.6.1.33";
public final static long BUILD = 2003; public final static long BUILD = 2004;
public static void main(String args[]) { public static void main(String args[]) {
System.out.println("I2P Router version: " + VERSION + "-" + BUILD); System.out.println("I2P Router version: " + VERSION + "-" + BUILD);
System.out.println("Router ID: " + RouterVersion.ID); System.out.println("Router ID: " + RouterVersion.ID);

View File

@ -11,8 +11,8 @@ package net.i2p.router;
import java.io.IOException; import java.io.IOException;
import java.io.Writer; import java.io.Writer;
import java.util.*; import java.util.*;
import net.i2p.data.DataHelper;
import net.i2p.data.DataHelper;
import net.i2p.data.Hash; import net.i2p.data.Hash;
import net.i2p.router.peermanager.PeerProfile; import net.i2p.router.peermanager.PeerProfile;
import net.i2p.util.Log; import net.i2p.util.Log;
@ -38,6 +38,8 @@ public class Shitlist {
} }
public final static long SHITLIST_DURATION_MS = 40*60*1000; // 40 minute shitlist public final static long SHITLIST_DURATION_MS = 40*60*1000; // 40 minute shitlist
public final static long SHITLIST_DURATION_MAX = 60*60*1000;
public final static long SHITLIST_DURATION_FOREVER = 181l*24*60*60*1000; // will get rounded down to 180d on console
public Shitlist(RouterContext context) { public Shitlist(RouterContext context) {
_context = context; _context = context;
@ -91,6 +93,12 @@ public class Shitlist {
} }
public boolean shitlistRouter(Hash peer, String reason) { return shitlistRouter(peer, reason, null); } public boolean shitlistRouter(Hash peer, String reason) { return shitlistRouter(peer, reason, null); }
public boolean shitlistRouter(Hash peer, String reason, String transport) { public boolean shitlistRouter(Hash peer, String reason, String transport) {
return shitlistRouter(peer, reason, null, false);
}
public boolean shitlistRouterForever(Hash peer, String reason) {
return shitlistRouter(peer, reason, null, true);
}
public boolean shitlistRouter(Hash peer, String reason, String transport, boolean forever) {
if (peer == null) { if (peer == null) {
_log.error("wtf, why did we try to shitlist null?", new Exception("shitfaced")); _log.error("wtf, why did we try to shitlist null?", new Exception("shitfaced"));
return false; return false;
@ -103,18 +111,21 @@ public class Shitlist {
if (_log.shouldLog(Log.INFO)) if (_log.shouldLog(Log.INFO))
_log.info("Shitlisting router " + peer.toBase64(), new Exception("Shitlist cause: " + reason)); _log.info("Shitlisting router " + peer.toBase64(), new Exception("Shitlist cause: " + reason));
long period = SHITLIST_DURATION_MS + _context.random().nextLong(SHITLIST_DURATION_MS);
PeerProfile prof = _context.profileOrganizer().getProfile(peer);
if (prof != null) {
period = SHITLIST_DURATION_MS << prof.incrementShitlists();
period += _context.random().nextLong(period);
}
if (period > 60*60*1000)
period = 60*60*1000;
Entry e = new Entry(); Entry e = new Entry();
e.expireOn = _context.clock().now() + period; if (forever) {
e.expireOn = _context.clock().now() + SHITLIST_DURATION_FOREVER;
} else {
long period = SHITLIST_DURATION_MS + _context.random().nextLong(SHITLIST_DURATION_MS);
PeerProfile prof = _context.profileOrganizer().getProfile(peer);
if (prof != null) {
period = SHITLIST_DURATION_MS << prof.incrementShitlists();
period += _context.random().nextLong(period);
}
if (period > SHITLIST_DURATION_MAX)
period = SHITLIST_DURATION_MAX;
e.expireOn = _context.clock().now() + period;
}
e.cause = reason; e.cause = reason;
e.transports = null; e.transports = null;
if (transport != null) { if (transport != null) {
@ -123,17 +134,22 @@ public class Shitlist {
} }
synchronized (_entries) { synchronized (_entries) {
Entry old = (Entry)_entries.put(peer, e); Entry old = (Entry)_entries.get(peer);
if (old != null) { if (old != null) {
wasAlready = true; wasAlready = true;
_entries.put(peer, old); // take the oldest expiration and cause, combine transports
if (e.transports == null) { if (old.expireOn > e.expireOn) {
old.transports = null; e.expireOn = old.expireOn;
} else if (old.transports != null) { e.cause = old.cause;
old.transports.addAll(e.transports); }
if (e.transports != null) {
if (old.transports != null)
e.transports.addAll(old.transports);
else
e.transports = null;
} }
e = old;
} }
_entries.put(peer, e);
} }
if (transport == null) { if (transport == null) {
@ -222,13 +238,27 @@ public class Shitlist {
return rv; return rv;
} }
public boolean isShitlistedForever(Hash peer) {
Entry entry;
synchronized (_entries) {
entry = (Entry)_entries.get(peer);
}
return entry != null && entry.expireOn > _context.clock().now() + SHITLIST_DURATION_MAX;
}
class HashComparator implements Comparator {
public int compare(Object l, Object r) {
return ((Hash)l).toBase64().compareTo(((Hash)r).toBase64());
}
}
public void renderStatusHTML(Writer out) throws IOException { public void renderStatusHTML(Writer out) throws IOException {
StringBuffer buf = new StringBuffer(1024); StringBuffer buf = new StringBuffer(1024);
buf.append("<h2>Shitlist</h2>"); buf.append("<h2>Shitlist</h2>");
Map entries = null; Map entries = new TreeMap(new HashComparator());
synchronized (_entries) { synchronized (_entries) {
entries = new HashMap(_entries); entries.putAll(_entries);
} }
buf.append("<ul>"); buf.append("<ul>");
@ -241,7 +271,7 @@ public class Shitlist {
continue; continue;
} }
buf.append("<li><b>").append(key.toBase64()).append("</b>"); buf.append("<li><b>").append(key.toBase64()).append("</b>");
buf.append(" <a href=\"netdb.jsp#").append(key.toBase64().substring(0, 6)).append("\">(?)</a>"); buf.append(" (<a href=\"netdb.jsp#").append(key.toBase64().substring(0, 6)).append("\">netdb</a>)");
buf.append(" expiring in "); buf.append(" expiring in ");
buf.append(DataHelper.formatDuration(entry.expireOn-_context.clock().now())); buf.append(DataHelper.formatDuration(entry.expireOn-_context.clock().now()));
Set transports = entry.transports; Set transports = entry.transports;
@ -251,12 +281,16 @@ public class Shitlist {
buf.append("<br />\n"); buf.append("<br />\n");
buf.append(entry.cause); buf.append(entry.cause);
} }
// future
// buf.append(" (<a href=\"configblock.jsp?peer=").append(key.toBase64()).append("#unsh\">unshitlist now</a>)");
buf.append("</li>\n"); buf.append("</li>\n");
} }
buf.append("</ul>\n"); buf.append("</ul>\n");
buf.append("<i>Partial shitlisted peers (only blocked on some transports): "); if (partial > 0) {
buf.append(partial); buf.append("<i>Partial shitlisted peers (only blocked on some transports): ");
buf.append("</i>\n"); buf.append(partial);
buf.append("</i>\n");
}
out.write(buf.toString()); out.write(buf.toString());
out.flush(); out.flush();
} }

View File

@ -13,6 +13,7 @@ import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.Writer; import java.io.Writer;
import java.util.Collection; import java.util.Collection;
import java.util.Comparator;
import java.util.Date; import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
@ -20,6 +21,7 @@ import java.util.Iterator;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.TreeMap; import java.util.TreeMap;
import java.util.TreeSet;
import net.i2p.data.Base64; import net.i2p.data.Base64;
import net.i2p.data.DataFormatException; import net.i2p.data.DataFormatException;
@ -579,13 +581,13 @@ public class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacade {
*/ */
String validate(Hash key, LeaseSet leaseSet) { String validate(Hash key, LeaseSet leaseSet) {
if (!key.equals(leaseSet.getDestination().calculateHash())) { if (!key.equals(leaseSet.getDestination().calculateHash())) {
if (_log.shouldLog(Log.WARN)) if (_log.shouldLog(Log.ERROR))
_log.warn("Invalid store attempt! key does not match leaseSet.destination! key = " _log.error("Invalid store attempt! key does not match leaseSet.destination! key = "
+ key + ", leaseSet = " + leaseSet); + key + ", leaseSet = " + leaseSet);
return "Key does not match leaseSet.destination - " + key.toBase64(); return "Key does not match leaseSet.destination - " + key.toBase64();
} else if (!leaseSet.verifySignature()) { } else if (!leaseSet.verifySignature()) {
if (_log.shouldLog(Log.WARN)) if (_log.shouldLog(Log.ERROR))
_log.warn("Invalid leaseSet signature! leaseSet = " + leaseSet); _log.error("Invalid leaseSet signature! leaseSet = " + leaseSet);
return "Invalid leaseSet signature on " + leaseSet.getDestination().calculateHash().toBase64(); return "Invalid leaseSet signature on " + leaseSet.getDestination().calculateHash().toBase64();
} else if (leaseSet.getEarliestLeaseDate() <= _context.clock().now() - 2*Router.CLOCK_FUDGE_FACTOR) { } else if (leaseSet.getEarliestLeaseDate() <= _context.clock().now() - 2*Router.CLOCK_FUDGE_FACTOR) {
long age = _context.clock().now() - leaseSet.getEarliestLeaseDate(); long age = _context.clock().now() - leaseSet.getEarliestLeaseDate();
@ -597,8 +599,8 @@ public class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacade {
+ " expired " + DataHelper.formatDuration(age) + " ago"; + " expired " + DataHelper.formatDuration(age) + " ago";
} else if (leaseSet.getEarliestLeaseDate() > _context.clock().now() + Router.CLOCK_FUDGE_FACTOR + MAX_LEASE_FUTURE) { } else if (leaseSet.getEarliestLeaseDate() > _context.clock().now() + Router.CLOCK_FUDGE_FACTOR + MAX_LEASE_FUTURE) {
long age = leaseSet.getEarliestLeaseDate() - _context.clock().now(); long age = leaseSet.getEarliestLeaseDate() - _context.clock().now();
if (_log.shouldLog(Log.WARN)) if (_log.shouldLog(Log.ERROR))
_log.warn("LeaseSet to expire too far in the future: " _log.error("LeaseSet to expire too far in the future: "
+ leaseSet.getDestination().calculateHash().toBase64() + leaseSet.getDestination().calculateHash().toBase64()
+ " expires on " + new Date(leaseSet.getEarliestLeaseDate()), new Exception("Rejecting store")); + " expires on " + new Date(leaseSet.getEarliestLeaseDate()), new Exception("Rejecting store"));
return "Expired leaseSet for " + leaseSet.getDestination().calculateHash().toBase64() return "Expired leaseSet for " + leaseSet.getDestination().calculateHash().toBase64()
@ -924,6 +926,24 @@ public class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacade {
_context.jobQueue().addJob(new StoreJob(_context, this, key, ds, onSuccess, onFailure, sendTimeout, toIgnore)); _context.jobQueue().addJob(new StoreJob(_context, this, key, ds, onSuccess, onFailure, sendTimeout, toIgnore));
} }
class LeaseSetComparator implements Comparator {
public int compare(Object l, Object r) {
Destination dl = ((LeaseSet)l).getDestination();
Destination dr = ((LeaseSet)r).getDestination();
boolean locall = _context.clientManager().isLocal(dl);
boolean localr = _context.clientManager().isLocal(dr);
if (locall && !localr) return -1;
if (localr && !locall) return 1;
return dl.calculateHash().toBase64().compareTo(dr.calculateHash().toBase64());
}
}
class RouterInfoComparator implements Comparator {
public int compare(Object l, Object r) {
return ((RouterInfo)l).getIdentity().getHash().toBase64().compareTo(((RouterInfo)r).getIdentity().getHash().toBase64());
}
}
public void renderStatusHTML(Writer out) throws IOException { public void renderStatusHTML(Writer out) throws IOException {
StringBuffer buf = new StringBuffer(10*1024); StringBuffer buf = new StringBuffer(10*1024);
buf.append("<h2>Kademlia Network DB Contents</h2>\n"); buf.append("<h2>Kademlia Network DB Contents</h2>\n");
@ -933,7 +953,8 @@ public class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacade {
out.flush(); out.flush();
return; return;
} }
Set leases = getLeases(); Set leases = new TreeSet(new LeaseSetComparator());
leases.addAll(getLeases());
buf.append("<h3>Leases</h3>\n"); buf.append("<h3>Leases</h3>\n");
out.write(buf.toString()); out.write(buf.toString());
buf.setLength(0); buf.setLength(0);
@ -978,7 +999,6 @@ public class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacade {
} }
Hash us = _context.routerHash(); Hash us = _context.routerHash();
Set routers = getRouters();
out.write("<h3>Routers</h3>\n"); out.write("<h3>Routers</h3>\n");
RouterInfo ourInfo = _context.router().getRouterInfo(); RouterInfo ourInfo = _context.router().getRouterInfo();
@ -989,6 +1009,8 @@ public class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacade {
/* coreVersion to Map of routerVersion to Integer */ /* coreVersion to Map of routerVersion to Integer */
Map versions = new TreeMap(); Map versions = new TreeMap();
Set routers = new TreeSet(new RouterInfoComparator());
routers.addAll(getRouters());
for (Iterator iter = routers.iterator(); iter.hasNext(); ) { for (Iterator iter = routers.iterator(); iter.hasNext(); ) {
RouterInfo ri = (RouterInfo)iter.next(); RouterInfo ri = (RouterInfo)iter.next();
Hash key = ri.getIdentity().getHash(); Hash key = ri.getIdentity().getHash();
@ -1038,7 +1060,7 @@ public class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacade {
String hash = info.getIdentity().getHash().toBase64(); String hash = info.getIdentity().getHash().toBase64();
if (isUs) { if (isUs) {
buf.append("<a name=\"").append(hash.substring(0, 6)).append("\" />"); buf.append("<a name=\"").append(hash.substring(0, 6)).append("\" />");
buf.append("<a name=\"our-info\" /a><b>Our info (").append(hash).append(") : </b><br />\n"); buf.append("<a name=\"our-info\" /a><b>Our info: ").append(hash).append("</b><br />\n");
} else { } else {
buf.append("<a name=\"").append(hash.substring(0, 6)).append("\" />"); buf.append("<a name=\"").append(hash.substring(0, 6)).append("\" />");
buf.append("<b>Peer info for:</b> ").append(hash).append("<br />\n"); buf.append("<b>Peer info for:</b> ").append(hash).append("<br />\n");