From 978de733514afb5cb463e017f3fd78112e293f29 Mon Sep 17 00:00:00 2001 From: zzz <zzz@mail.i2p> Date: Tue, 16 Jun 2009 18:01:43 +0000 Subject: [PATCH] * netdb.jsp: Add country chart at bottom, clean up version chart --- core/java/src/net/i2p/util/ObjectCounter.java | 42 ++++++++++++ .../src/net/i2p/router/CommSystemFacade.java | 1 + .../KademliaNetworkDatabaseFacade.java | 67 +++++++++++-------- .../transport/CommSystemFacadeImpl.java | 16 +++-- .../router/tunnel/pool/TunnelPoolManager.java | 38 +++-------- 5 files changed, 102 insertions(+), 62 deletions(-) create mode 100644 core/java/src/net/i2p/util/ObjectCounter.java diff --git a/core/java/src/net/i2p/util/ObjectCounter.java b/core/java/src/net/i2p/util/ObjectCounter.java new file mode 100644 index 0000000000..19c92ae666 --- /dev/null +++ b/core/java/src/net/i2p/util/ObjectCounter.java @@ -0,0 +1,42 @@ +package net.i2p.util; + +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; + +/** + * Count things. + * + * @author zzz + */ +public class ObjectCounter<K> { + private ConcurrentHashMap<K, Integer> _map; + public ObjectCounter() { + _map = new ConcurrentHashMap(); + } + /** + * Add one. + * Not perfectly concurrent, new AtomicInteger(1) would be better, + * at the cost of some object churn. + */ + public void increment(K h) { + Integer i = _map.putIfAbsent(h, Integer.valueOf(1)); + if (i != null) + _map.put(h, Integer.valueOf(i.intValue() + 1)); + } + /** + * @return current count + */ + public int count(K h) { + Integer i = _map.get(h); + if (i != null) + return i.intValue(); + return 0; + } + /** + * @return set of objects with counts > 0 + */ + public Set<K> objects() { + return _map.keySet(); + } +} + diff --git a/router/java/src/net/i2p/router/CommSystemFacade.java b/router/java/src/net/i2p/router/CommSystemFacade.java index 2e85a7eb5f..4fe9147ace 100644 --- a/router/java/src/net/i2p/router/CommSystemFacade.java +++ b/router/java/src/net/i2p/router/CommSystemFacade.java @@ -62,6 +62,7 @@ public abstract class CommSystemFacade implements Service { public byte[] getIP(Hash dest) { return null; } public void queueLookup(byte[] ip) {} public String getCountry(Hash peer) { return null; } + public String getCountryName(String code) { return code; } public String renderPeerHTML(Hash peer) { return null; } /** 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 ae5dd9d803..e61a585541 100644 --- a/router/java/src/net/i2p/router/networkdb/kademlia/KademliaNetworkDatabaseFacade.java +++ b/router/java/src/net/i2p/router/networkdb/kademlia/KademliaNetworkDatabaseFacade.java @@ -10,12 +10,15 @@ package net.i2p.router.networkdb.kademlia; import java.io.IOException; import java.io.Writer; +import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.Comparator; import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; +import java.util.List; import java.util.Map; import java.util.Properties; import java.util.Set; @@ -42,6 +45,7 @@ import net.i2p.router.networkdb.DatabaseStoreMessageHandler; import net.i2p.router.networkdb.PublishLocalRouterInfoJob; import net.i2p.router.peermanager.PeerProfile; import net.i2p.util.Log; +import net.i2p.util.ObjectCounter; /** * Kademlia based version of the network database @@ -1011,8 +1015,8 @@ public class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacade { out.write(buf.toString()); buf.setLength(0); - /* coreVersion to Map of routerVersion to Integer */ - Map versions = new TreeMap(); + ObjectCounter<String> versions = new ObjectCounter(); + ObjectCounter<String> countries = new ObjectCounter(); Set routers = new TreeSet(new RouterInfoComparator()); routers.addAll(getRouters()); @@ -1024,40 +1028,47 @@ public class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacade { renderRouterInfo(buf, ri, false, full); out.write(buf.toString()); buf.setLength(0); - String coreVersion = ri.getOption("coreVersion"); String routerVersion = ri.getOption("router.version"); - if ( (coreVersion != null) && (routerVersion != null) ) { - Map routerVersions = (Map)versions.get(coreVersion); - if (routerVersions == null) { - routerVersions = new TreeMap(); - versions.put(coreVersion, routerVersions); - } - Integer val = (Integer)routerVersions.get(routerVersion); - if (val == null) - routerVersions.put(routerVersion, Integer.valueOf(1)); - else - routerVersions.put(routerVersion, Integer.valueOf(val.intValue() + 1)); - } + if (routerVersion != null) + versions.increment(routerVersion); + String country = _context.commSystem().getCountry(key); + if(country != null) + countries.increment(country); } } - if (versions.size() > 0) { + buf.append("<table border=\"0\" cellspacing=\"30\"><tr><td valign=\"top\">"); + List<String> versionList = new ArrayList(versions.objects()); + if (versionList.size() > 0) { + Collections.sort(versionList, Collections.reverseOrder()); buf.append("<table border=\"1\">\n"); - buf.append("<tr><td><b>Core version</b></td><td><b>Router version</b></td><td><b>Number</b></td></tr>\n"); - for (Iterator iter = versions.entrySet().iterator(); iter.hasNext(); ) { - Map.Entry entry = (Map.Entry)iter.next(); - String coreVersion = (String)entry.getKey(); - Map routerVersions = (Map)entry.getValue(); - for (Iterator routerIter = routerVersions.keySet().iterator(); routerIter.hasNext(); ) { - String routerVersion = (String)routerIter.next(); - Integer num = (Integer)routerVersions.get(routerVersion); - buf.append("<tr><td>").append(DataHelper.stripHTML(coreVersion)); - buf.append("</td><td>").append(DataHelper.stripHTML(routerVersion)); - buf.append("</td><td>").append(num.intValue()).append("</td></tr>\n"); - } + buf.append("<tr><th>Version</th><th>Count</th></tr>\n"); + for (String routerVersion : versionList) { + int num = versions.count(routerVersion); + buf.append("<tr><td>").append(DataHelper.stripHTML(routerVersion)); + buf.append("</td><td align=\"right\">").append(num).append("</td></tr>\n"); + } + buf.append("</table>\n"); + } + buf.append("</td><td valign=\"top\">"); + out.write(buf.toString()); + buf.setLength(0); + + List<String> countryList = new ArrayList(countries.objects()); + if (countryList.size() > 0) { + Collections.sort(countryList); + buf.append("<table border=\"1\">\n"); + buf.append("<tr><th>Country</th><th>Count</th></tr>\n"); + for (String country : countryList) { + int num = countries.count(country); + buf.append("<tr><td><img alt=\"").append(country.toUpperCase()).append("\""); + buf.append(" src=\"/flags.jsp?c=").append(country).append("\"> "); + buf.append(_context.commSystem().getCountryName(country)); + buf.append("</td><td align=\"right\">").append(num).append("</td></tr>\n"); } buf.append("</table>\n"); } + buf.append("</td></tr></table>"); out.write(buf.toString()); out.flush(); } diff --git a/router/java/src/net/i2p/router/transport/CommSystemFacadeImpl.java b/router/java/src/net/i2p/router/transport/CommSystemFacadeImpl.java index a798e0c18d..04d4f8d23b 100644 --- a/router/java/src/net/i2p/router/transport/CommSystemFacadeImpl.java +++ b/router/java/src/net/i2p/router/transport/CommSystemFacadeImpl.java @@ -433,6 +433,16 @@ public class CommSystemFacadeImpl extends CommSystemFacade { return props.getProperty("host"); } + /** full name for a country code, or the code if we don't know the name */ + public String getCountryName(String c) { + if (_geoIP == null) + return c; + String n = _geoIP.fullName(c); + if (n == null) + return c; + return n; + } + /** Provide a consistent "look" for displaying router IDs in the console */ public String renderPeerHTML(Hash peer) { String h = peer.toBase64().substring(0, 4); @@ -440,11 +450,7 @@ public class CommSystemFacadeImpl extends CommSystemFacade { String c = getCountry(peer); if (c != null) { buf.append("<img alt=\"").append(c.toUpperCase()).append("\" title=\""); - String n = _geoIP.fullName(c); - if (n != null) - buf.append(n); - else - buf.append(c); + buf.append(getCountryName(c)); buf.append("\" src=\"/flags.jsp?c=").append(c).append("\"> "); } buf.append("<tt><font size=\"+1\">"); diff --git a/router/java/src/net/i2p/router/tunnel/pool/TunnelPoolManager.java b/router/java/src/net/i2p/router/tunnel/pool/TunnelPoolManager.java index 9845a72f34..7293b6a1ef 100644 --- a/router/java/src/net/i2p/router/tunnel/pool/TunnelPoolManager.java +++ b/router/java/src/net/i2p/router/tunnel/pool/TunnelPoolManager.java @@ -29,6 +29,7 @@ import net.i2p.router.tunnel.HopConfig; import net.i2p.stat.RateStat; import net.i2p.util.I2PThread; import net.i2p.util.Log; +import net.i2p.util.ObjectCounter; /** * @@ -588,15 +589,15 @@ public class TunnelPoolManager implements TunnelManagerFacade { private void renderPeers(Writer out) throws IOException { // count up the peers in the local pools - HashCounter lc = new HashCounter(); + ObjectCounter<Hash> lc = new ObjectCounter(); int tunnelCount = countTunnelsPerPeer(lc); // count up the peers in the participating tunnels - HashCounter pc = new HashCounter(); + ObjectCounter<Hash> pc = new ObjectCounter(); int partCount = countParticipatingPerPeer(pc); - Set<Hash> peers = new HashSet(lc.hashes()); - peers.addAll(pc.hashes()); + Set<Hash> peers = new HashSet(lc.objects()); + peers.addAll(pc.objects()); List<Hash> peerList = new ArrayList(peers); Collections.sort(peerList, new HashComparator()); @@ -625,7 +626,7 @@ public class TunnelPoolManager implements TunnelManagerFacade { } /** @return total number of non-fallback expl. + client tunnels */ - private int countTunnelsPerPeer(HashCounter lc) { + private int countTunnelsPerPeer(ObjectCounter<Hash> lc) { List<TunnelPool> pools = new ArrayList(); listPools(pools); int tunnelCount = 0; @@ -661,12 +662,12 @@ public class TunnelPoolManager implements TunnelManagerFacade { * @return Set of peers that should not be allowed in another tunnel */ public Set<Hash> selectPeersInTooManyTunnels() { - HashCounter lc = new HashCounter(); + ObjectCounter<Hash> lc = new ObjectCounter(); int tunnelCount = countTunnelsPerPeer(lc); Set<Hash> rv = new HashSet(); if (tunnelCount >= 4 && _context.router().getUptime() > 10*60*1000) { int max = _context.getProperty("router.maxTunnelPercentage", DEFAULT_MAX_PCT_TUNNELS); - for (Hash h : lc.hashes()) { + for (Hash h : lc.objects()) { if (lc.count(h) > 0 && (lc.count(h) + 1) * 100 / (tunnelCount + 1) > max) rv.add(h); } @@ -675,7 +676,7 @@ public class TunnelPoolManager implements TunnelManagerFacade { } /** @return total number of part. tunnels */ - private int countParticipatingPerPeer(HashCounter pc) { + private int countParticipatingPerPeer(ObjectCounter<Hash> pc) { List<HopConfig> participating = _context.tunnelDispatcher().listParticipatingTunnels(); for (HopConfig cfg : participating) { Hash from = cfg.getReceiveFrom(); @@ -694,27 +695,6 @@ public class TunnelPoolManager implements TunnelManagerFacade { } } - private static class HashCounter { - private ConcurrentHashMap<Hash, Integer> _map; - public HashCounter() { - _map = new ConcurrentHashMap(); - } - public void increment(Hash h) { - Integer i = _map.putIfAbsent(h, Integer.valueOf(1)); - if (i != null) - _map.put(h, Integer.valueOf(i.intValue() + 1)); - } - public int count(Hash h) { - Integer i = _map.get(h); - if (i != null) - return i.intValue(); - return 0; - } - public Set<Hash> hashes() { - return _map.keySet(); - } - } - private String getCapacity(Hash peer) { RouterInfo info = _context.netDb().lookupRouterInfoLocally(peer); if (info != null) { -- GitLab