Pluck of revision 45a25185236e38606e761060427ee8fa60144a8c from branch i2p.i2p.zzz.test
--------------------------------------------------------------------------------------- * netdb.jsp: Add country chart at bottom, clean up version chart
This commit is contained in:
42
core/java/src/net/i2p/util/ObjectCounter.java
Normal file
42
core/java/src/net/i2p/util/ObjectCounter.java
Normal file
@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -63,6 +63,7 @@ public abstract class CommSystemFacade implements Service {
|
|||||||
public byte[] getIP(Hash dest) { return null; }
|
public byte[] getIP(Hash dest) { return null; }
|
||||||
public void queueLookup(byte[] ip) {}
|
public void queueLookup(byte[] ip) {}
|
||||||
public String getCountry(Hash peer) { return null; }
|
public String getCountry(Hash peer) { return null; }
|
||||||
|
public String getCountryName(String code) { return code; }
|
||||||
public String renderPeerHTML(Hash peer) { return null; }
|
public String renderPeerHTML(Hash peer) { return null; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -10,12 +10,15 @@ package net.i2p.router.networkdb.kademlia;
|
|||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.Writer;
|
import java.io.Writer;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.Comparator;
|
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;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
@ -42,6 +45,7 @@ import net.i2p.router.networkdb.DatabaseStoreMessageHandler;
|
|||||||
import net.i2p.router.networkdb.PublishLocalRouterInfoJob;
|
import net.i2p.router.networkdb.PublishLocalRouterInfoJob;
|
||||||
import net.i2p.router.peermanager.PeerProfile;
|
import net.i2p.router.peermanager.PeerProfile;
|
||||||
import net.i2p.util.Log;
|
import net.i2p.util.Log;
|
||||||
|
import net.i2p.util.ObjectCounter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Kademlia based version of the network database
|
* Kademlia based version of the network database
|
||||||
@ -999,8 +1003,8 @@ public class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacade {
|
|||||||
out.write(buf.toString());
|
out.write(buf.toString());
|
||||||
buf.setLength(0);
|
buf.setLength(0);
|
||||||
|
|
||||||
/* coreVersion to Map of routerVersion to Integer */
|
ObjectCounter<String> versions = new ObjectCounter();
|
||||||
Map versions = new TreeMap();
|
ObjectCounter<String> countries = new ObjectCounter();
|
||||||
|
|
||||||
Set routers = new TreeSet(new RouterInfoComparator());
|
Set routers = new TreeSet(new RouterInfoComparator());
|
||||||
routers.addAll(getRouters());
|
routers.addAll(getRouters());
|
||||||
@ -1012,40 +1016,47 @@ public class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacade {
|
|||||||
renderRouterInfo(buf, ri, false, full);
|
renderRouterInfo(buf, ri, false, full);
|
||||||
out.write(buf.toString());
|
out.write(buf.toString());
|
||||||
buf.setLength(0);
|
buf.setLength(0);
|
||||||
String coreVersion = ri.getOption("coreVersion");
|
|
||||||
String routerVersion = ri.getOption("router.version");
|
String routerVersion = ri.getOption("router.version");
|
||||||
if ( (coreVersion != null) && (routerVersion != null) ) {
|
if (routerVersion != null)
|
||||||
Map routerVersions = (Map)versions.get(coreVersion);
|
versions.increment(routerVersion);
|
||||||
if (routerVersions == null) {
|
String country = _context.commSystem().getCountry(key);
|
||||||
routerVersions = new TreeMap();
|
if(country != null)
|
||||||
versions.put(coreVersion, routerVersions);
|
countries.increment(country);
|
||||||
}
|
|
||||||
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 (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("<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");
|
buf.append("<tr><th>Version</th><th>Count</th></tr>\n");
|
||||||
for (Iterator iter = versions.entrySet().iterator(); iter.hasNext(); ) {
|
for (String routerVersion : versionList) {
|
||||||
Map.Entry entry = (Map.Entry)iter.next();
|
int num = versions.count(routerVersion);
|
||||||
String coreVersion = (String)entry.getKey();
|
buf.append("<tr><td>").append(DataHelper.stripHTML(routerVersion));
|
||||||
Map routerVersions = (Map)entry.getValue();
|
buf.append("</td><td align=\"right\">").append(num).append("</td></tr>\n");
|
||||||
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("</table>\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.write(buf.toString());
|
||||||
out.flush();
|
out.flush();
|
||||||
}
|
}
|
||||||
|
@ -435,6 +435,16 @@ public class CommSystemFacadeImpl extends CommSystemFacade {
|
|||||||
return props.getProperty("host");
|
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 */
|
/** Provide a consistent "look" for displaying router IDs in the console */
|
||||||
public String renderPeerHTML(Hash peer) {
|
public String renderPeerHTML(Hash peer) {
|
||||||
String h = peer.toBase64().substring(0, 4);
|
String h = peer.toBase64().substring(0, 4);
|
||||||
@ -442,11 +452,7 @@ public class CommSystemFacadeImpl extends CommSystemFacade {
|
|||||||
String c = getCountry(peer);
|
String c = getCountry(peer);
|
||||||
if (c != null) {
|
if (c != null) {
|
||||||
buf.append("<img alt=\"").append(c.toUpperCase()).append("\" title=\"");
|
buf.append("<img alt=\"").append(c.toUpperCase()).append("\" title=\"");
|
||||||
String n = _geoIP.fullName(c);
|
buf.append(getCountryName(c));
|
||||||
if (n != null)
|
|
||||||
buf.append(n);
|
|
||||||
else
|
|
||||||
buf.append(c);
|
|
||||||
buf.append("\" src=\"/flags.jsp?c=").append(c).append("\"> ");
|
buf.append("\" src=\"/flags.jsp?c=").append(c).append("\"> ");
|
||||||
}
|
}
|
||||||
buf.append("<tt><font size=\"+1\">");
|
buf.append("<tt><font size=\"+1\">");
|
||||||
|
@ -29,6 +29,7 @@ import net.i2p.router.tunnel.HopConfig;
|
|||||||
import net.i2p.stat.RateStat;
|
import net.i2p.stat.RateStat;
|
||||||
import net.i2p.util.I2PThread;
|
import net.i2p.util.I2PThread;
|
||||||
import net.i2p.util.Log;
|
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 {
|
private void renderPeers(Writer out) throws IOException {
|
||||||
// count up the peers in the local pools
|
// count up the peers in the local pools
|
||||||
HashCounter lc = new HashCounter();
|
ObjectCounter<Hash> lc = new ObjectCounter();
|
||||||
int tunnelCount = countTunnelsPerPeer(lc);
|
int tunnelCount = countTunnelsPerPeer(lc);
|
||||||
|
|
||||||
// count up the peers in the participating tunnels
|
// count up the peers in the participating tunnels
|
||||||
HashCounter pc = new HashCounter();
|
ObjectCounter<Hash> pc = new ObjectCounter();
|
||||||
int partCount = countParticipatingPerPeer(pc);
|
int partCount = countParticipatingPerPeer(pc);
|
||||||
|
|
||||||
Set<Hash> peers = new HashSet(lc.hashes());
|
Set<Hash> peers = new HashSet(lc.objects());
|
||||||
peers.addAll(pc.hashes());
|
peers.addAll(pc.objects());
|
||||||
List<Hash> peerList = new ArrayList(peers);
|
List<Hash> peerList = new ArrayList(peers);
|
||||||
Collections.sort(peerList, new HashComparator());
|
Collections.sort(peerList, new HashComparator());
|
||||||
|
|
||||||
@ -625,7 +626,7 @@ public class TunnelPoolManager implements TunnelManagerFacade {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** @return total number of non-fallback expl. + client tunnels */
|
/** @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();
|
List<TunnelPool> pools = new ArrayList();
|
||||||
listPools(pools);
|
listPools(pools);
|
||||||
int tunnelCount = 0;
|
int tunnelCount = 0;
|
||||||
@ -661,12 +662,12 @@ public class TunnelPoolManager implements TunnelManagerFacade {
|
|||||||
* @return Set of peers that should not be allowed in another tunnel
|
* @return Set of peers that should not be allowed in another tunnel
|
||||||
*/
|
*/
|
||||||
public Set<Hash> selectPeersInTooManyTunnels() {
|
public Set<Hash> selectPeersInTooManyTunnels() {
|
||||||
HashCounter lc = new HashCounter();
|
ObjectCounter<Hash> lc = new ObjectCounter();
|
||||||
int tunnelCount = countTunnelsPerPeer(lc);
|
int tunnelCount = countTunnelsPerPeer(lc);
|
||||||
Set<Hash> rv = new HashSet();
|
Set<Hash> rv = new HashSet();
|
||||||
if (tunnelCount >= 4 && _context.router().getUptime() > 10*60*1000) {
|
if (tunnelCount >= 4 && _context.router().getUptime() > 10*60*1000) {
|
||||||
int max = _context.getProperty("router.maxTunnelPercentage", DEFAULT_MAX_PCT_TUNNELS);
|
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)
|
if (lc.count(h) > 0 && (lc.count(h) + 1) * 100 / (tunnelCount + 1) > max)
|
||||||
rv.add(h);
|
rv.add(h);
|
||||||
}
|
}
|
||||||
@ -675,7 +676,7 @@ public class TunnelPoolManager implements TunnelManagerFacade {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** @return total number of part. tunnels */
|
/** @return total number of part. tunnels */
|
||||||
private int countParticipatingPerPeer(HashCounter pc) {
|
private int countParticipatingPerPeer(ObjectCounter<Hash> pc) {
|
||||||
List<HopConfig> participating = _context.tunnelDispatcher().listParticipatingTunnels();
|
List<HopConfig> participating = _context.tunnelDispatcher().listParticipatingTunnels();
|
||||||
for (HopConfig cfg : participating) {
|
for (HopConfig cfg : participating) {
|
||||||
Hash from = cfg.getReceiveFrom();
|
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) {
|
private String getCapacity(Hash peer) {
|
||||||
RouterInfo info = _context.netDb().lookupRouterInfoLocally(peer);
|
RouterInfo info = _context.netDb().lookupRouterInfoLocally(peer);
|
||||||
if (info != null) {
|
if (info != null) {
|
||||||
|
Reference in New Issue
Block a user