diff --git a/apps/routerconsole/java/src/net/i2p/router/web/helpers/JobQueueHelper.java b/apps/routerconsole/java/src/net/i2p/router/web/helpers/JobQueueHelper.java index b5a67fcac1c6cf426b2f78fb79581544d1340743..185fdba80be6c8e1ae41b4066051c42c3a4b2cf2 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/helpers/JobQueueHelper.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/helpers/JobQueueHelper.java @@ -14,7 +14,7 @@ import net.i2p.data.DataHelper; import net.i2p.router.Job; import net.i2p.router.JobStats; import net.i2p.router.web.HelperBase; -import net.i2p.util.ObjectCounter; +import net.i2p.util.ObjectCounterUnsafe; public class JobQueueHelper extends HelperBase { @@ -79,7 +79,7 @@ public class JobQueueHelper extends HelperBase { buf.append("<h3 id=\"readyjobs\">") .append(_t("Ready/waiting jobs")).append(": ").append(readyJobs.size()) .append("</h3><ol>"); - ObjectCounter<String> counter = new ObjectCounter<String>(); + ObjectCounterUnsafe<String> counter = new ObjectCounterUnsafe<String>(); for (int i = 0; i < readyJobs.size(); i++) { Job j = readyJobs.get(i); counter.increment(j.getName()); @@ -129,7 +129,7 @@ public class JobQueueHelper extends HelperBase { } /** @since 0.9.5 */ - private void getJobCounts(StringBuilder buf, ObjectCounter<String> counter) { + private void getJobCounts(StringBuilder buf, ObjectCounterUnsafe<String> counter) { List<String> names = new ArrayList<String>(counter.objects()); if (names.size() < 4) return; @@ -232,10 +232,10 @@ public class JobQueueHelper extends HelperBase { /** @since 0.9.5 */ private static class JobCountComparator implements Comparator<String>, Serializable { - private final ObjectCounter<String> _counter; + private final ObjectCounterUnsafe<String> _counter; private final Collator coll = Collator.getInstance(); - public JobCountComparator(ObjectCounter<String> counter) { + public JobCountComparator(ObjectCounterUnsafe<String> counter) { _counter = counter; } diff --git a/apps/routerconsole/java/src/net/i2p/router/web/helpers/NetDbRenderer.java b/apps/routerconsole/java/src/net/i2p/router/web/helpers/NetDbRenderer.java index 11b2faf03ac394c0315add737f38d1c041f9efed..751c6af59a9558f54dac8d477a754bf817f9136c 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/helpers/NetDbRenderer.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/helpers/NetDbRenderer.java @@ -52,7 +52,7 @@ import net.i2p.router.web.WebAppStarter; import net.i2p.util.Addresses; import net.i2p.util.ConvertToHash; import net.i2p.util.Log; -import net.i2p.util.ObjectCounter; +import net.i2p.util.ObjectCounterUnsafe; import net.i2p.util.Translate; import net.i2p.util.VersionComparator; @@ -935,8 +935,8 @@ class NetDbRenderer { buf.setLength(0); } - ObjectCounter<String> versions = new ObjectCounter<String>(); - ObjectCounter<String> countries = new ObjectCounter<String>(); + ObjectCounterUnsafe<String> versions = new ObjectCounterUnsafe<String>(); + ObjectCounterUnsafe<String> countries = new ObjectCounterUnsafe<String>(); int[] transportCount = new int[TNAMES.length]; int skipped = 0; @@ -1137,10 +1137,10 @@ class NetDbRenderer { */ private class CountryCountComparator implements Comparator<String> { private static final long serialVersionUID = 1L; - private final ObjectCounter<String> counts; + private final ObjectCounterUnsafe<String> counts; private final Collator coll; - public CountryCountComparator(ObjectCounter<String> counts) { + public CountryCountComparator(ObjectCounterUnsafe<String> counts) { super(); this.counts = counts; coll = Collator.getInstance(new Locale(Messages.getLanguage(_context))); diff --git a/apps/routerconsole/java/src/net/i2p/router/web/helpers/SybilRenderer.java b/apps/routerconsole/java/src/net/i2p/router/web/helpers/SybilRenderer.java index d48a415f9d853148573ab815cbf3479cb02fe1ae..3461d95e82dedce30c988e2c4dad2aecc7f12087 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/helpers/SybilRenderer.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/helpers/SybilRenderer.java @@ -46,7 +46,6 @@ import net.i2p.stat.RateAverages; import net.i2p.stat.RateStat; import net.i2p.util.ConvertToHash; import net.i2p.util.Log; -import net.i2p.util.ObjectCounter; import net.i2p.util.SystemVersion; import net.i2p.util.Translate; import net.i2p.util.VersionComparator; diff --git a/core/java/src/net/i2p/util/ObjectCounterUnsafe.java b/core/java/src/net/i2p/util/ObjectCounterUnsafe.java new file mode 100644 index 0000000000000000000000000000000000000000..3e2f532cdb00306b875ccd704456fbb52571550e --- /dev/null +++ b/core/java/src/net/i2p/util/ObjectCounterUnsafe.java @@ -0,0 +1,107 @@ +package net.i2p.util; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * Count things. + * NOT thread safe, mostly for UI and Sybil. + * Dropin replacement for ObjectCounter. + * Much less object churn than ObjectCounter. + * Also provides add() and sortedObjects() + * + * @since 0.9.58 + */ +public class ObjectCounterUnsafe<K> { + private final HashMap<K, Int> map = new HashMap<K, Int>(); + + /** + * Add one. + * @return count after increment + */ + public int increment(K h) { + Int i = map.get(h); + if (i != null) { + return ++(i.c); + } + map.put(h, new Int(1)); + return 1; + } + + /** + * Add a value + * @return count after adding + */ + public int add(K h, int val) { + Int i = map.get(h); + if (i != null) { + i.c += val; + return i.c; + } + map.put(h, new Int(val)); + return val; + } + + /** + * @return current count + */ + public int count(K h) { + Int i = map.get(h); + if (i != null) + return i.c; + return 0; + } + + /** + * @return set of objects with counts > 0 + */ + public Set<K> objects() { + return map.keySet(); + } + + /** + * @return list of objects reverse sorted by count, highest to lowest + */ + public List<K> sortedObjects() { + List<K> rv = new ArrayList<K>(map.keySet()); + Collections.sort(rv, new ObjComparator()); + return rv; + } + + /** + * Start over. Reset the count for all keys to zero. + */ + public void clear() { + map.clear(); + } + + /** + * Reset the count for this key to zero + */ + public void clear(K h) { + map.remove(h); + } + + /** + * Modifiable integer + */ + private static class Int { + int c; + public Int(int i) { c = i; } + } + + /** + * reverse sort + */ + private class ObjComparator implements Comparator<K> { + public int compare(K l, K r) { + return (map.get(r).c - map.get(l).c); + } + } +} + diff --git a/router/java/src/net/i2p/router/sybil/Analysis.java b/router/java/src/net/i2p/router/sybil/Analysis.java index 074eae207f57760b23455b33f1dd0150d4d23d6c..d66c4386b204609e088fda2f513aa74f489188a3 100644 --- a/router/java/src/net/i2p/router/sybil/Analysis.java +++ b/router/java/src/net/i2p/router/sybil/Analysis.java @@ -41,7 +41,7 @@ import net.i2p.stat.RateAverages; import net.i2p.stat.RateStat; import net.i2p.util.Addresses; import net.i2p.util.Log; -import net.i2p.util.ObjectCounter; +import net.i2p.util.ObjectCounterUnsafe; import net.i2p.util.SystemVersion; import net.i2p.util.Translate; @@ -683,7 +683,7 @@ public class Analysis extends JobImpl implements RouterApp { * @since 0.9.38 split out from renderIPGroups32() */ public Map<Integer, List<RouterInfo>> calculateIPGroups32(List<RouterInfo> ris, Map<Hash, Points> points) { - ObjectCounter<Integer> oc = new ObjectCounter<Integer>(); + ObjectCounterUnsafe<Integer> oc = new ObjectCounterUnsafe<Integer>(); for (RouterInfo info : ris) { byte[] ip = getIP(info); if (ip == null) @@ -732,7 +732,7 @@ public class Analysis extends JobImpl implements RouterApp { * @since 0.9.38 split out from renderIPGroups24() */ public Map<Integer, List<RouterInfo>> calculateIPGroups24(List<RouterInfo> ris, Map<Hash, Points> points) { - ObjectCounter<Integer> oc = new ObjectCounter<Integer>(); + ObjectCounterUnsafe<Integer> oc = new ObjectCounterUnsafe<Integer>(); for (RouterInfo info : ris) { byte[] ip = getIP(info); if (ip == null) @@ -785,7 +785,7 @@ public class Analysis extends JobImpl implements RouterApp { * @since 0.9.38 split out from renderIPGroups16() */ public Map<Integer, List<RouterInfo>> calculateIPGroups16(List<RouterInfo> ris, Map<Hash, Points> points) { - ObjectCounter<Integer> oc = new ObjectCounter<Integer>(); + ObjectCounterUnsafe<Integer> oc = new ObjectCounterUnsafe<Integer>(); for (RouterInfo info : ris) { byte[] ip = getIP(info); if (ip == null) @@ -828,7 +828,7 @@ public class Analysis extends JobImpl implements RouterApp { * @since 0.9.57 */ public Map<Long, List<RouterInfo>> calculateIPGroups64(List<RouterInfo> ris, Map<Hash, Points> points) { - ObjectCounter<Long> oc = new ObjectCounter<Long>(); + ObjectCounterUnsafe<Long> oc = new ObjectCounterUnsafe<Long>(); for (RouterInfo info : ris) { byte[] ip = getIPv6(info); if (ip == null) @@ -893,7 +893,7 @@ public class Analysis extends JobImpl implements RouterApp { * @since 0.9.57 */ public Map<Long, List<RouterInfo>> calculateIPGroups48(List<RouterInfo> ris, Map<Hash, Points> points) { - ObjectCounter<Long> oc = new ObjectCounter<Long>(); + ObjectCounterUnsafe<Long> oc = new ObjectCounterUnsafe<Long>(); for (RouterInfo info : ris) { byte[] ip = getIPv6(info); if (ip == null) 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 27460c6a824e3137205b214193312c8fd82866c5..e6a13f91a9ee7d0fedce81443e48be415b18be8e 100644 --- a/router/java/src/net/i2p/router/tunnel/pool/TunnelPoolManager.java +++ b/router/java/src/net/i2p/router/tunnel/pool/TunnelPoolManager.java @@ -24,7 +24,7 @@ import net.i2p.router.TunnelPoolSettings; import net.i2p.router.tunnel.TunnelDispatcher; import net.i2p.util.I2PThread; import net.i2p.util.Log; -import net.i2p.util.ObjectCounter; +import net.i2p.util.ObjectCounterUnsafe; import net.i2p.util.SimpleTimer; /** @@ -645,7 +645,7 @@ public class TunnelPoolManager implements TunnelManagerFacade { } /** @return total number of non-fallback expl. + client tunnels */ - private int countTunnelsPerPeer(ObjectCounter<Hash> lc) { + private int countTunnelsPerPeer(ObjectCounterUnsafe<Hash> lc) { List<TunnelPool> pools = new ArrayList<TunnelPool>(); listPools(pools); int tunnelCount = 0; @@ -681,7 +681,7 @@ public class TunnelPoolManager implements TunnelManagerFacade { * @return Set of peers that should not be allowed in another tunnel */ public Set<Hash> selectPeersInTooManyTunnels() { - ObjectCounter<Hash> lc = new ObjectCounter<Hash>(); + ObjectCounterUnsafe<Hash> lc = new ObjectCounterUnsafe<Hash>(); int tunnelCount = countTunnelsPerPeer(lc); Set<Hash> rv = new HashSet<Hash>(); if (tunnelCount >= 4 && _context.router().getUptime() > 10*60*1000) {