From 9f4439583dc084de7876c79291fbc332f762bcc9 Mon Sep 17 00:00:00 2001 From: jrandom <jrandom> Date: Fri, 23 Jul 2004 17:36:29 +0000 Subject: [PATCH] expose some data points for the new console, and cleaned up some html new piece of data exposed and maintained is a list of router contexts - shown as a singleton off RouterContext - allowing an app in the same JVM to find the routers (and chose between which one they want) --- router/java/src/net/i2p/router/Router.java | 1 + .../src/net/i2p/router/RouterContext.java | 14 ++++ router/java/src/net/i2p/router/Shitlist.java | 6 ++ .../net/i2p/router/TunnelManagerFacade.java | 4 + .../KademliaNetworkDatabaseFacade.java | 76 ++++++++++++------- .../router/peermanager/ProfileOrganizer.java | 44 ++++++++--- .../PoolingTunnelManagerFacade.java | 6 ++ 7 files changed, 114 insertions(+), 37 deletions(-) diff --git a/router/java/src/net/i2p/router/Router.java b/router/java/src/net/i2p/router/Router.java index f2724759f3..56f3c3b19d 100644 --- a/router/java/src/net/i2p/router/Router.java +++ b/router/java/src/net/i2p/router/Router.java @@ -491,6 +491,7 @@ public class Router { try { _context.messageRegistry().shutdown(); } catch (Throwable t) { _log.log(Log.CRIT, "Error shutting down the message registry", t); } try { _context.messageValidator().shutdown(); } catch (Throwable t) { _log.log(Log.CRIT, "Error shutting down the message validator", t); } try { _sessionKeyPersistenceHelper.shutdown(); } catch (Throwable t) { _log.log(Log.CRIT, "Error shutting down the session key manager", t); } + _context.listContexts().remove(_context); dumpStats(); _log.log(Log.CRIT, "Shutdown complete", new Exception("Shutdown")); try { _context.logManager().shutdown(); } catch (Throwable t) { } diff --git a/router/java/src/net/i2p/router/RouterContext.java b/router/java/src/net/i2p/router/RouterContext.java index c0152a7951..62e739fffb 100644 --- a/router/java/src/net/i2p/router/RouterContext.java +++ b/router/java/src/net/i2p/router/RouterContext.java @@ -1,5 +1,7 @@ package net.i2p.router; +import java.util.ArrayList; +import java.util.List; import java.util.Properties; import net.i2p.I2PAppContext; @@ -57,11 +59,14 @@ public class RouterContext extends I2PAppContext { private Calculator _reliabilityCalc; private Calculator _capacityCalc; + private static List _contexts = new ArrayList(1); + public RouterContext(Router router) { this(router, null); } public RouterContext(Router router, Properties envProps) { super(envProps); _router = router; initAll(); + _contexts.add(this); } private void initAll() { _clientManagerFacade = new ClientManagerFacadeImpl(this); @@ -94,6 +99,15 @@ public class RouterContext extends I2PAppContext { _capacityCalc = new CapacityCalculator(this); } + /** + * Retrieve the list of router contexts currently instantiated in this JVM. + * This will always contain only one item (except when a simulation per the + * MultiRouter is going on), and the list should only be modified when a new + * context is created or a router is shut down. + * + */ + public static List listContexts() { return _contexts; } + /** what router is this context working for? */ public Router router() { return _router; } /** convenience method for querying the router's ident */ diff --git a/router/java/src/net/i2p/router/Shitlist.java b/router/java/src/net/i2p/router/Shitlist.java index 64922a82ec..7730b1ef7d 100644 --- a/router/java/src/net/i2p/router/Shitlist.java +++ b/router/java/src/net/i2p/router/Shitlist.java @@ -38,6 +38,12 @@ public class Shitlist { _shitlist = new HashMap(100); } + public int getRouterCount() { + synchronized (_shitlist) { + return _shitlist.size(); + } + } + public boolean shitlistRouter(Hash peer) { if (peer == null) return false; if (_context.routerHash().equals(peer)) { diff --git a/router/java/src/net/i2p/router/TunnelManagerFacade.java b/router/java/src/net/i2p/router/TunnelManagerFacade.java index bd91bdeaab..5448b83385 100644 --- a/router/java/src/net/i2p/router/TunnelManagerFacade.java +++ b/router/java/src/net/i2p/router/TunnelManagerFacade.java @@ -63,4 +63,8 @@ public interface TunnelManagerFacade extends Service { /** how many tunnels are we participating in? */ public int getParticipatingCount(); + /** how many free inbound tunnels do we have available? */ + public int getFreeTunnelCount(); + /** how many outbound tunnels do we have available? */ + public int getOutboundTunnelCount(); } diff --git a/router/java/src/net/i2p/router/networkdb/kademlia/KademliaNetworkDatabaseFacade.java b/router/java/src/net/i2p/router/networkdb/kademlia/KademliaNetworkDatabaseFacade.java index 6ce250a6d1..ca2b02c58c 100644 --- a/router/java/src/net/i2p/router/networkdb/kademlia/KademliaNetworkDatabaseFacade.java +++ b/router/java/src/net/i2p/router/networkdb/kademlia/KademliaNetworkDatabaseFacade.java @@ -21,10 +21,12 @@ import java.util.Map; import java.util.Set; import net.i2p.data.DataFormatException; +import net.i2p.data.DataHelper; import net.i2p.data.DataStructure; import net.i2p.data.Hash; import net.i2p.data.Lease; import net.i2p.data.LeaseSet; +import net.i2p.data.RouterAddress; import net.i2p.data.RouterInfo; import net.i2p.data.i2np.DatabaseLookupMessage; import net.i2p.data.i2np.DatabaseSearchReplyMessage; @@ -616,51 +618,73 @@ public class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacade { } Set leases = getLeases(); buf.append("<h3>Leases</h3>\n"); - buf.append("<table border=\"1\">\n"); out.write(buf.toString().getBytes()); buf.setLength(0); + long now = _context.clock().now(); for (Iterator iter = leases.iterator(); iter.hasNext(); ) { LeaseSet ls = (LeaseSet)iter.next(); Hash key = ls.getDestination().calculateHash(); - buf.append("<tr><td valign=\"top\" align=\"left\"><b>").append(key.toBase64()).append("</b></td>"); - - if (getLastSent(key).longValue() > 0) - buf.append("<td valign=\"top\" align=\"left\"><b>Last sent successfully:</b> ").append(new Date(getLastSent(key).longValue())).append("</td></tr>"); - else - buf.append("<td valign=\"top\" align=\"left\"><b>Last sent successfully:</b> never</td></tr>"); - buf.append("<tr><td valign=\"top\" align=\"left\" colspan=\"2\"><pre>\n").append(ls.toString()).append("</pre></td></tr>\n"); + buf.append("<b>LeaseSet: ").append(key.toBase64()).append("</b><br />\n"); + long exp = ls.getEarliestLeaseDate()-now; + buf.append("Earliest expiration date in: <i>").append(DataHelper.formatDuration(exp)).append("</i><br />\n"); + for (int i = 0; i < ls.getLeaseCount(); i++) { + buf.append("Lease ").append(i).append(": gateway <i>"); + buf.append(ls.getLease(i).getRouterIdentity().getHash().toBase64().substring(0,6)); + buf.append("</i> tunnelId <i>").append(ls.getLease(i).getTunnelId().getTunnelId()).append("</i><br />\n"); + } + buf.append("<hr />\n"); out.write(buf.toString().getBytes()); buf.setLength(0); } - buf.append("</table>\n"); Hash us = _context.routerHash(); Set routers = getRouters(); - buf.append("<h3>Routers</h3>\n"); - buf.append("<table border=\"1\">\n"); + out.write("<h3>Routers</h3>\n".getBytes()); + + RouterInfo ourInfo = _context.router().getRouterInfo(); + renderRouterInfo(buf, ourInfo, true); out.write(buf.toString().getBytes()); buf.setLength(0); - for (Iterator iter = routers.iterator(); iter.hasNext(); ) { RouterInfo ri = (RouterInfo)iter.next(); Hash key = ri.getIdentity().getHash(); boolean isUs = key.equals(us); - if (isUs) { - buf.append("<tr><td valign=\"top\" align=\"left\"><font color=\"red\"><b>").append(key.toBase64()).append("</b></font></td>"); - buf.append("<td valign=\"top\" align=\"left\" colspan=\"2\"><b>Last sent successfully:</b> ").append(new Date(getLastSent(key).longValue())).append("</td></tr>"); - } else { - buf.append("<tr><td valign=\"top\" align=\"left\"><a name=\"").append(key.toBase64().substring(0,32)).append("\"><b>").append(key.toBase64()).append("</b></a></td>"); - if (getLastSent(key).longValue() > 0) - buf.append("<td valign=\"top\" align=\"left\"><b>Last sent successfully:</b> ").append(new Date(getLastSent(key).longValue())).append("</td>"); - else - buf.append("<td valign=\"top\" align=\"left\"><b>Last sent successfully:</b> never</td>"); - buf.append("<td valign=\"top\" align=\"left\"><a href=\"/profile/").append(key.toBase64().substring(0, 32)).append("\">Profile</a></td></tr>"); + if (!isUs) { + renderRouterInfo(buf, ri, false); + out.write(buf.toString().getBytes()); + buf.setLength(0); } - buf.append("<tr><td valign=\"top\" align=\"left\" colspan=\"3\"><pre>\n").append(ri.toString()).append("</pre></td></tr>\n"); - out.write(buf.toString().getBytes()); - buf.setLength(0); } - out.write("</table>\n".getBytes()); + } + private void renderRouterInfo(StringBuffer buf, RouterInfo info, boolean isUs) { + if (isUs) { + buf.append("<b>Our info: </b><br />\n"); + } else { + String hash = info.getIdentity().getHash().toBase64(); + buf.append("<a name=\"").append(hash.substring(0, 6)).append("\" />"); + buf.append("<b>Peer info for:</b> ").append(hash).append("<br />\n"); + } + + long age = _context.clock().now() - info.getPublished(); + buf.append("Published: <i>").append(DataHelper.formatDuration(age)).append(" ago</i><br />\n"); + buf.append("Address(es): <i>"); + for (Iterator iter = info.getAddresses().iterator(); iter.hasNext(); ) { + RouterAddress addr = (RouterAddress)iter.next(); + buf.append(addr.getTransportStyle()).append(": "); + for (Iterator optIter = addr.getOptions().keySet().iterator(); optIter.hasNext(); ) { + String name = (String)optIter.next(); + String val = addr.getOptions().getProperty(name); + buf.append('[').append(name).append('=').append(val).append("] "); + } + } + buf.append("</i><br />\n"); + buf.append("Stats: <br /><i><code>\n"); + for (Iterator iter = info.getOptions().keySet().iterator(); iter.hasNext(); ) { + String key = (String)iter.next(); + String val = info.getOptions().getProperty(key); + buf.append(key).append(" = ").append(val).append("<br />\n"); + } + buf.append("</code></i><hr />\n"); } } diff --git a/router/java/src/net/i2p/router/peermanager/ProfileOrganizer.java b/router/java/src/net/i2p/router/peermanager/ProfileOrganizer.java index ab81c600da..f27f052f1f 100644 --- a/router/java/src/net/i2p/router/peermanager/ProfileOrganizer.java +++ b/router/java/src/net/i2p/router/peermanager/ProfileOrganizer.java @@ -167,6 +167,31 @@ public class ProfileOrganizer { public int countNotFailingPeers() { synchronized (_reorganizeLock) { return _notFailingPeers.size(); } } public int countFailingPeers() { synchronized (_reorganizeLock) { return _failingPeers.size(); } } + public int countActivePeers() { + synchronized (_reorganizeLock) { + int activePeers = 0; + + long hideBefore = _context.clock().now() - 6*60*60*1000; + + for (Iterator iter = _failingPeers.values().iterator(); iter.hasNext(); ) { + PeerProfile profile = (PeerProfile)iter.next(); + if (profile.getLastSendSuccessful() >= hideBefore) + activePeers++; + else if (profile.getLastHeardFrom() >= hideBefore) + activePeers++; + } + for (Iterator iter = _notFailingPeers.values().iterator(); iter.hasNext(); ) { + PeerProfile profile = (PeerProfile)iter.next(); + if (profile.getLastSendSuccessful() >= hideBefore) + activePeers++; + else if (profile.getLastHeardFrom() >= hideBefore) + activePeers++; + } + + return activePeers; + } + } + public boolean isFast(Hash peer) { synchronized (_reorganizeLock) { return _fastPeers.containsKey(peer); } } public boolean isHighCapacity(Hash peer) { synchronized (_reorganizeLock) { return _highCapacityPeers.containsKey(peer); } } public boolean isWellIntegrated(Hash peer) { synchronized (_reorganizeLock) { return _wellIntegratedPeers.containsKey(peer); } } @@ -628,14 +653,13 @@ public class ProfileOrganizer { buf.append("<h2>Peer Profiles</h2>\n"); buf.append("<table border=\"1\">"); buf.append("<tr>"); - buf.append("<td><b>Peer</b> (").append(order.size()).append(", hiding ").append(peers.size()-order.size()).append(" inactive ones)</td>"); + buf.append("<td><b>Peer</b> (").append(order.size()).append(", hiding ").append(peers.size()-order.size()).append(")</td>"); buf.append("<td><b>Groups</b></td>"); buf.append("<td><b>Speed</b></td>"); buf.append("<td><b>Capacity</b></td>"); buf.append("<td><b>Integration</b></td>"); buf.append("<td><b>Failing?</b></td>"); - buf.append("<td><b>Reliability (deprecated)</b></td>"); - buf.append("<td><b>Profile data</b></td>"); + //buf.append("<td><b>Profile data</b></td>"); buf.append("</tr>"); for (Iterator iter = order.keySet().iterator(); iter.hasNext();) { String name = (String)iter.next(); @@ -645,10 +669,10 @@ public class ProfileOrganizer { buf.append("<tr>"); buf.append("<td><code>"); if (prof.getIsFailing()) { - buf.append("<font color=\"red\">--").append(peer.toBase64()).append("</font>"); + buf.append("<font color=\"red\">--").append(peer.toBase64().substring(0,6)).append("</font>"); } else { if (prof.getIsActive()) { - buf.append("<font color=\"blue\">++").append(peer.toBase64()).append("</font>"); + buf.append("<font color=\"blue\">++").append(peer.toBase64().substring(0,6)).append("</font>"); } else { buf.append("__").append(peer.toBase64()); } @@ -678,20 +702,19 @@ public class ProfileOrganizer { } switch (tier) { - case 1: buf.append("Fast+High Capacity"); break; + case 1: buf.append("Fast"); break; case 2: buf.append("High Capacity"); break; case 3: buf.append("Not Failing"); break; default: buf.append("Failing"); break; } - if (isIntegrated) buf.append(", Well integrated"); + if (isIntegrated) buf.append(", Integrated"); buf.append("<td align=\"right\">").append(num(prof.getSpeedValue())).append("</td>"); buf.append("<td align=\"right\">").append(num(prof.getCapacityValue())).append("</td>"); buf.append("<td align=\"right\">").append(num(prof.getIntegrationValue())).append("</td>"); buf.append("<td align=\"right\">").append(prof.getIsFailing()).append("</td>"); - buf.append("<td align=\"right\">").append(num(prof.getReliabilityValue())).append("</td>"); - buf.append("<td><a href=\"/profile/").append(prof.getPeer().toBase64().substring(0, 32)).append("\">profile.txt</a> "); - buf.append(" <a href=\"#").append(prof.getPeer().toBase64().substring(0, 32)).append("\">netDb</a></td>"); + //buf.append("<td><a href=\"/profile/").append(prof.getPeer().toBase64().substring(0, 32)).append("\">profile.txt</a> "); + //buf.append(" <a href=\"#").append(prof.getPeer().toBase64().substring(0, 32)).append("\">netDb</a></td>"); buf.append("</tr>"); } buf.append("</table>"); @@ -700,7 +723,6 @@ public class ProfileOrganizer { buf.append("<li><b>capacity</b>: how many tunnels can we ask them to join in an hour?</li>"); buf.append("<li><b>integration</b>: how many new peers have they told us about lately?</li>"); buf.append("<li><b>failing?</b>: is the peer currently swamped (and if possible we should avoid nagging them)?</li>"); - buf.append("<li><b>reliability</b>: no sound semantics... just a random kludge of a value.</li>"); buf.append("</ul></i>"); buf.append("Red peers prefixed with '--' means the peer is failing, and blue peers prefixed "); buf.append("with '++' means we've sent or received a message from them "); diff --git a/router/java/src/net/i2p/router/tunnelmanager/PoolingTunnelManagerFacade.java b/router/java/src/net/i2p/router/tunnelmanager/PoolingTunnelManagerFacade.java index 851a19656a..f4539b7400 100644 --- a/router/java/src/net/i2p/router/tunnelmanager/PoolingTunnelManagerFacade.java +++ b/router/java/src/net/i2p/router/tunnelmanager/PoolingTunnelManagerFacade.java @@ -212,6 +212,12 @@ public class PoolingTunnelManagerFacade implements TunnelManagerFacade { public int getParticipatingCount() { return _pool.getParticipatingTunnelCount(); } + public int getFreeTunnelCount() { + return _pool.getFreeTunnelCount(); + } + public int getOutboundTunnelCount() { + return _pool.getOutboundTunnelCount(); + } /** * Aint she pretty? -- GitLab