diff --git a/apps/i2psnark/java/src/org/klomp/snark/TrackerClient.java b/apps/i2psnark/java/src/org/klomp/snark/TrackerClient.java
index 878b1831ce..466cccd09a 100644
--- a/apps/i2psnark/java/src/org/klomp/snark/TrackerClient.java
+++ b/apps/i2psnark/java/src/org/klomp/snark/TrackerClient.java
@@ -275,8 +275,11 @@ public class TrackerClient extends I2PThread
tr.stop = true;
}
}
- if (++tr.consecutiveFails == MAX_CONSEC_FAILS && tr.interval < LONG_SLEEP)
- tr.interval = LONG_SLEEP; // slow down
+ if (++tr.consecutiveFails == MAX_CONSEC_FAILS) {
+ tr.seenPeers = 0;
+ if (tr.interval < LONG_SLEEP)
+ tr.interval = LONG_SLEEP; // slow down
+ }
}
}
if ((!tr.stop) && maxSeenPeers < tr.seenPeers)
diff --git a/checklist.txt b/checklist.txt
index ad277e24fb..66b52a659c 100644
--- a/checklist.txt
+++ b/checklist.txt
@@ -14,6 +14,10 @@ Change revision in:
router/java/src/net/i2p/router/RouterVersion.java
core/java/src/net/i2p/CoreVersion.java
+Review the complete diff from the last release:
+ mtn diff -r t:i2p-0.6.1.(xx-1) > out.diff
+ vi out.diff
+
Build and tag:
ant pkg
mtn ci
diff --git a/core/java/src/net/i2p/client/naming/HostsTxtNamingService.java b/core/java/src/net/i2p/client/naming/HostsTxtNamingService.java
index 696fe1479b..c07c1a7711 100644
--- a/core/java/src/net/i2p/client/naming/HostsTxtNamingService.java
+++ b/core/java/src/net/i2p/client/naming/HostsTxtNamingService.java
@@ -9,8 +9,10 @@ package net.i2p.client.naming;
import java.io.File;
import java.util.ArrayList;
+import java.util.Iterator;
import java.util.List;
import java.util.Properties;
+import java.util.Set;
import java.util.StringTokenizer;
import net.i2p.I2PAppContext;
@@ -87,6 +89,28 @@ public class HostsTxtNamingService extends NamingService {
}
public String reverseLookup(Destination dest) {
+ String destkey = dest.toBase64();
+ List filenames = getFilenames();
+ for (int i = 0; i < filenames.size(); i++) {
+ String hostsfile = (String)filenames.get(i);
+ Properties hosts = new Properties();
+ try {
+ File f = new File(hostsfile);
+ if ( (f.exists()) && (f.canRead()) ) {
+ DataHelper.loadProps(hosts, f, true);
+ Set keyset = hosts.keySet();
+ Iterator iter = keyset.iterator();
+ while (iter.hasNext()) {
+ String host = (String)iter.next();
+ String key = hosts.getProperty(host);
+ if (destkey.equals(key))
+ return host;
+ }
+ }
+ } catch (Exception ioe) {
+ _log.error("Error loading hosts file " + hostsfile, ioe);
+ }
+ }
return null;
}
}
diff --git a/history.txt b/history.txt
index 748a712369..f87795944e 100644
--- a/history.txt
+++ b/history.txt
@@ -1,3 +1,14 @@
+2008-03-30 zzz
+ * ExploratoryPeerSelector: Try NonFailing even more
+ * HostsTxtNamingService: Add reverse lookup support
+ * Outbound message: Minor cleanup
+ * i2psnark TrackerCLient: Minor cleanup
+ * checklist.txt: Minor edit
+ * hosts.txt: Add perv.i2p, false.i2p, mtn.i2p2.i2p
+ * i2ptunnel.config: Change CVS client to mtn
+ * netdb.jsp: Show leaseSet destinations using reverse lookup
+ * profiles.jsp: First cut at showing floodfill data
+
2008-03-27 zzz
* Send messages for the same destination to the same inbound
lease to reduce out-of-order delivery.
@@ -16,6 +27,7 @@
- Don't have eepget retry announces
- Slow down tracker contacts if they've failed for a while
- Add some debug support showing connections (?p=2)
+ * hosts.txt: Add nickyb.i2p, tracker.welterde.i2p
2008-03-22 zzz
* NewsFetcher: Fix bug causing fetch every 10m
diff --git a/hosts.txt b/hosts.txt
index 440d94c7e4..23dd1dbb94 100644
--- a/hosts.txt
+++ b/hosts.txt
@@ -302,3 +302,6 @@ www.i2p2.i2p=-KR6qyfPWXoN~F3UzzYSMIsaRy4udcRkHu2Dx9syXSzUQXQdi2Af1TV2UMH3PpPuNu-
i2p-projekt.i2p=8ZAW~KzGFMUEj0pdchy6GQOOZbuzbqpWtiApEj8LHy2~O~58XKxRrA43cA23a9oDpNZDqWhRWEtehSnX5NoCwJcXWWdO1ksKEUim6cQLP-VpQyuZTIIqwSADwgoe6ikxZG0NGvy5FijgxF4EW9zg39nhUNKRejYNHhOBZKIX38qYyXoB8XCVJybKg89aMMPsCT884F0CLBKbHeYhpYGmhE4YW~aV21c5pebivvxeJPWuTBAOmYxAIgJE3fFU-fucQn9YyGUFa8F3t-0Vco-9qVNSEWfgrdXOdKT6orr3sfssiKo3ybRWdTpxycZ6wB4qHWgTSU5A-gOA3ACTCMZBsASN3W5cz6GRZCspQ0HNu~R~nJ8V06Mmw~iVYOu5lDvipmG6-dJky6XRxCedczxMM1GWFoieQ8Ysfuxq-j8keEtaYmyUQme6TcviCEvQsxyVirr~dTC-F8aZ~y2AlG5IJz5KD02nO6TRkI2fgjHhv9OZ9nskh-I2jxAzFP6Is1kyAAAA
nickyb.i2p=9On6d3cZ27JjwYCtyJJbowe054d5tFnfMjv4PHsYs-EQn4Y4mk2zRixatvuAyXz2MmRfXG-NAUfhKr0KCxRNZbvHmlckYfT-WBzwwpiMAl0wDFY~Pl8cqXuhfikSG5WrqdPfDNNIBuuznS0dqaczf~OyVaoEOpvuP3qV6wKqbSSLpjOwwAaQPHjlRtNIW8-EtUZp-I0LT45HSoowp~6b7zYmpIyoATvIP~sT0g0MTrczWhbVTUZnEkZeLhOR0Duw1-IRXI2KHPbA24wLO9LdpKKUXed05RTz0QklW5ROgR6TYv7aXFufX8kC0-DaKvQ5JKG~h8lcoHvm1RCzNqVE-2aiZnO2xH08H-iCWoLNJE-Td2kT-Tsc~3QdQcnEUcL5BF-VT~QYRld2--9r0gfGl-yDrJZrlrihHGr5J7ImahelNn9PpkVp6eIyABRmJHf2iicrk3CtjeG1j9OgTSwaNmEpUpn4aN7Kx0zNLdH7z6uTgCGD9Kmh1MFYrsoNlTp4AAAA
tracker.welterde.i2p=BGKmlDOoH3RzFbPRfRpZV2FjpVj8~3moFftw5-dZfDf2070TOe8Tf2~DAVeaM6ZRLdmFEt~9wyFL8YMLMoLoiwGEH6IGW6rc45tstN68KsBDWZqkTohV1q9XFgK9JnCwE~Oi89xLBHsLMTHOabowWM6dkC8nI6QqJC2JODqLPIRfOVrDdkjLwtCrsckzLybNdFmgfoqF05UITDyczPsFVaHtpF1sRggOVmdvCM66otyonlzNcJbn59PA-R808vUrCPMGU~O9Wys0i-NoqtIbtWfOKnjCRFMNw5ex4n9m5Sxm9e20UkpKG6qzEuvKZWi8vTLe1NW~CBrj~vG7I3Ok4wybUFflBFOaBabxYJLlx4xTE1zJIVxlsekmAjckB4v-cQwulFeikR4LxPQ6mCQknW2HZ4JQIq6hL9AMabxjOlYnzh7kjOfRGkck8YgeozcyTvcDUcUsOuSTk06L4kdrv8h2Cozjbloi5zl6KTbj5ZTciKCxi73Pn9grICn-HQqEAAAA
+perv.i2p=HazSt3kSqVjpMO9Ol9HPjXCfzTLurOPjSeN47UxMLLs4lm5SJJHP-p3vA4sTfxrR3z7Cqq5Nd0t1gog~bV0PCbnKNsTiF~pSPBIFXOPVe5RuX7keDRJ-Mp5-quPIe2FFNEOz7HNkbuz6aHYN74T5Cs2VcMDEvL9Wz~oxV7FPSijD1qs1hi~f3byvSvswRkt4w7A10iJvunq43r1jOi6JwS~lAChP1q7t16sfhtWp4XEaEvfES0bIbnTsRv-aDVy0Kp4zYYPuZstit-S8GHkS7ceDRHSoid1O6V1WgogeDoTRzfxfHqQb5db5xWt4DXmnQbb7xysXub-2S3mbog-WnoawDRM5ZJDItCDuMsg0edIn5RJYkANh0Qox-JMVUZdU8tcx--DX9gONJ4cm4a-MLxY9dme~Zq4hqJJRNRvrRcA11ZuLH-ZN3aTXL70Yod-YyNPcechGrpugKEU38g5sDyj77pX~IrdaTVTFpJE6zlClRatTnl4Enhr4pQ7gWFpcAAAA
+false.i2p=V5EeX1UrVanCQhE9q-Nj5UFRyQiH6b~lSO7qe8hgxGZkymrpHFZ5j5D9rVOjsogokon1bZF5NPlPdzI~d4Ap7UyqBR~90vhFxsIKednRZLdf46JgjYTZq~ct-Bi3sdpBXdg04L8i4dStE4jkdvl6NF96MfQKdt6mtYFeaXb0XhPx~04NECG5~y~mTYcMjcvrftt5uulLbT6TcGmJ0KV5Xu2UVnkN3zOaQEObIIDZT4wkz9jOqaiJzMHNJqWc4GU4ocIfwxeMkSn9qvA0Q1AXuM~z11~wgHYLVEFoN5k0O4aB8b1r1WtpZTojZ9ADThW89q~AcD981nIYnRp59cmyqBdN7X-71cBrKC7QfnCRJpbwoVrn7kePw1dCu6Bobnd4~a74abxjFeCxVzQxSTbkey6f~wJXE2JPAqfsM1EKXsdqUZQJOP0ngQu16srSpqMSxkqHzlr3US~Vn9EgMcHuDCkdctwo7stwn0UQ34sSF9sLhtmlHIGqatDhfmYEGmSiAAAA
+mtn.i2p2.i2p=G6VmsrLYbdcxBq585OUcQn7wbwC7J5jfXDWWL6lPBw5iq68VxqxibraiPwwF6NM2aHV8BkqyCKYSL9fUuYWoeUc1zL~2l1DX2x~LfyItGJKDIUGImWQivXF1w7EGYMhjq4UCmPKTsnl4G86oKW8PGaaF8mzjjUKW1R7G7941my~mnbeTrhjlLgaMK-tauVodgTPIYkxfMJaq3zWuirztuUgDcXXIbkpzaA2Iben0VqbjbMJisj4fFh0EvqNkYAG54YBc26~W6SPWyBgZilXvFlcizF90Q5NkIGMMHXTq46qEYHkpQC3CoaH6PMNVDetDPmFc3QXmc68cNcj~VPh4XVsn3qiKhXuRdXggEC3RoTcxqaeassfIG5xhRdnJzGSVhYUE3At~8wI-AuRV~AglV1Q-AZTWT~9VxBzcxfI1PpfzeA-5z5T4542bh1e-RM9tzXEx5ErPCt6M~zJ2~4-tz-aBsZEhBkn0iDi8pazshg6lTl1~hCnueZBxYICqPrlBAAAA
diff --git a/installer/resources/i2ptunnel.config b/installer/resources/i2ptunnel.config
index eff3ae7485..2cbe84b502 100644
--- a/installer/resources/i2ptunnel.config
+++ b/installer/resources/i2ptunnel.config
@@ -29,14 +29,14 @@ tunnel.1.option.i2p.streaming.connectDelay=1000
tunnel.1.option.i2p.streaming.maxWindowSize=1
tunnel.1.startOnLoad=true
-# I2P's cvs server
-tunnel.2.name=cvs.i2p
-tunnel.2.description=I2P CVS pserver
+# I2P's mtn server
+tunnel.2.name=mtn.i2p2.i2p
+tunnel.2.description=I2P Monotone Server
tunnel.2.type=client
tunnel.2.sharedClient=true
tunnel.2.interface=127.0.0.1
-tunnel.2.listenPort=2401
-tunnel.2.targetDestination=cvs.i2p
+tunnel.2.listenPort=8998
+tunnel.2.targetDestination=mtn.i2p2.i2p
tunnel.2.i2cpHost=127.0.0.1
tunnel.2.i2cpPort=7654
tunnel.2.option.inbound.nickname=shared clients
diff --git a/router/java/src/net/i2p/router/RouterVersion.java b/router/java/src/net/i2p/router/RouterVersion.java
index 750dae67cd..54461d6815 100644
--- a/router/java/src/net/i2p/router/RouterVersion.java
+++ b/router/java/src/net/i2p/router/RouterVersion.java
@@ -17,7 +17,7 @@ import net.i2p.CoreVersion;
public class RouterVersion {
public final static String ID = "$Revision: 1.548 $ $Date: 2008-02-10 15:00:00 $";
public final static String VERSION = "0.6.1.32";
- public final static long BUILD = 13;
+ public final static long BUILD = 14;
public static void main(String args[]) {
System.out.println("I2P Router version: " + VERSION + "-" + BUILD);
System.out.println("Router ID: " + RouterVersion.ID);
diff --git a/router/java/src/net/i2p/router/message/OutboundClientMessageOneShotJob.java b/router/java/src/net/i2p/router/message/OutboundClientMessageOneShotJob.java
index d4c599e257..f250c784b9 100644
--- a/router/java/src/net/i2p/router/message/OutboundClientMessageOneShotJob.java
+++ b/router/java/src/net/i2p/router/message/OutboundClientMessageOneShotJob.java
@@ -228,6 +228,9 @@ public class OutboundClientMessageOneShotJob extends JobImpl {
* simultaneously talking to the same dest is probably rare enough
* to not bother separating out.
*
+ * We're going to use the lease until it expires, not even looking for a newer lease.
+ * So if the inbound tunnel fails and the dest publishes a new lease, we won't know about it.
+ *
* If not found,
* fetch the next lease that we should try sending through, randomly chosen
* from within the sorted leaseSet (NOT sorted by # of failures through each
@@ -244,8 +247,9 @@ public class OutboundClientMessageOneShotJob extends JobImpl {
return false;
}
long now = getContext().clock().now();
-
+
// Use the same lease if it's still good
+ // Even if _leaseSet changed, _leaseSet.getEncryptionKey() didn't...
synchronized (_leaseCache) {
if (now - _cleanTime > 5*60*1000) { // clean out periodically
cleanLeaseCache(_leaseCache);
@@ -254,12 +258,12 @@ public class OutboundClientMessageOneShotJob extends JobImpl {
_lease = (Lease) _leaseCache.get(_to);
if (_lease != null) {
if (!_lease.isExpired()) {
- if (_log.shouldLog(Log.WARN))
- _log.warn("Found in cache - lease for dest " + _to.calculateHash().toBase64());
+ if (_log.shouldLog(Log.INFO))
+ _log.info("Found in cache - lease for " + _toString);
return true;
} else {
if (_log.shouldLog(Log.WARN))
- _log.warn("Expired from cache - lease for dest " + _to.calculateHash().toBase64());
+ _log.warn("Expired from cache - lease for " + _toString);
_leaseCache.remove(_to);
}
}
@@ -288,6 +292,7 @@ public class OutboundClientMessageOneShotJob extends JobImpl {
// sort are randomly ordered)
Collections.shuffle(leases);
+/****
if (false) {
// ordered by lease number of failures
TreeMap orderedLeases = new TreeMap();
@@ -303,13 +308,14 @@ public class OutboundClientMessageOneShotJob extends JobImpl {
_lease = (Lease)orderedLeases.get(orderedLeases.firstKey());
} else {
+****/
_lease = (Lease)leases.get(0);
- }
+// }
synchronized (_leaseCache) {
_leaseCache.put(_to, _lease);
}
if (_log.shouldLog(Log.WARN))
- _log.warn("Added to cache - lease for dest " + _to.calculateHash().toBase64());
+ _log.warn("Added to cache - lease for " + _toString);
return true;
}
@@ -538,7 +544,7 @@ public class OutboundClientMessageOneShotJob extends JobImpl {
if (getContext().tunnelManager().isValidTunnel(_from.calculateHash(), tunnel)) {
if (!getContext().commSystem().isBacklogged(tunnel.getPeer(1))) {
if (_log.shouldLog(Log.WARN))
- _log.warn("Switching back to tunnel " + tunnel + " for dest " + to.calculateHash().toBase64());
+ _log.warn("Switching back to tunnel " + tunnel + " for " + _toString);
_backloggedTunnelCache.remove(to);
_tunnelCache.put(to, tunnel);
return tunnel;
@@ -554,7 +560,7 @@ public class OutboundClientMessageOneShotJob extends JobImpl {
return tunnel;
// backlogged
if (_log.shouldLog(Log.WARN))
- _log.warn("Switching from backlogged " + tunnel + " for dest " + to.calculateHash().toBase64());
+ _log.warn("Switching from backlogged " + tunnel + " for " + _toString);
_backloggedTunnelCache.put(to, tunnel);
} // else no longer valid
_tunnelCache.remove(to);
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 a9d93691bc..c4a57965fd 100644
--- a/router/java/src/net/i2p/router/networkdb/kademlia/KademliaNetworkDatabaseFacade.java
+++ b/router/java/src/net/i2p/router/networkdb/kademlia/KademliaNetworkDatabaseFacade.java
@@ -21,9 +21,11 @@ import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
+import net.i2p.data.Base64;
import net.i2p.data.DataFormatException;
import net.i2p.data.DataHelper;
import net.i2p.data.DataStructure;
+import net.i2p.data.Destination;
import net.i2p.data.Hash;
import net.i2p.data.Lease;
import net.i2p.data.LeaseSet;
@@ -39,6 +41,7 @@ import net.i2p.router.networkdb.DatabaseLookupMessageHandler;
import net.i2p.router.networkdb.DatabaseStoreMessageHandler;
import net.i2p.router.networkdb.PublishLocalRouterInfoJob;
import net.i2p.router.peermanager.PeerProfile;
+import net.i2p.router.TunnelPoolSettings;
import net.i2p.util.Log;
/**
@@ -934,8 +937,28 @@ public class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacade {
long now = _context.clock().now();
for (Iterator iter = leases.iterator(); iter.hasNext(); ) {
LeaseSet ls = (LeaseSet)iter.next();
- Hash key = ls.getDestination().calculateHash();
- buf.append("LeaseSet: ").append(key.toBase64()).append("
\n");
+ Destination dest = ls.getDestination();
+ Hash key = dest.calculateHash();
+ buf.append("LeaseSet: ").append(key.toBase64());
+ if (_context.clientManager().isLocal(dest)) {
+ buf.append(" (Local ");
+ if (! _context.clientManager().shouldPublishLeaseSet(key))
+ buf.append("Unpublished ");
+ buf.append("Destination ");
+ TunnelPoolSettings in = _context.tunnelManager().getInboundSettings(key);
+ if (in != null && in.getDestinationNickname() != null)
+ buf.append(in.getDestinationNickname());
+ else
+ buf.append(dest.toBase64().substring(0, 6));
+ } else {
+ buf.append(" (Destination ");
+ String host = _context.namingService().reverseLookup(dest);
+ if (host != null)
+ buf.append(host);
+ else
+ buf.append(dest.toBase64().substring(0, 6));
+ }
+ buf.append(")
\n");
long exp = ls.getEarliestLeaseDate()-now;
if (exp > 0)
buf.append("Earliest expiration date in: ").append(DataHelper.formatDuration(exp)).append("
\n");
diff --git a/router/java/src/net/i2p/router/peermanager/ProfileOrganizerRenderer.java b/router/java/src/net/i2p/router/peermanager/ProfileOrganizerRenderer.java
index bbceb5c7c0..80ba9e7be4 100644
--- a/router/java/src/net/i2p/router/peermanager/ProfileOrganizerRenderer.java
+++ b/router/java/src/net/i2p/router/peermanager/ProfileOrganizerRenderer.java
@@ -3,6 +3,8 @@ package net.i2p.router.peermanager;
import java.io.IOException;
import java.io.Writer;
+import java.lang.Math;
+
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
@@ -12,9 +14,13 @@ import java.util.Locale;
import java.util.Set;
import java.util.TreeSet;
+import net.i2p.data.DataHelper;
import net.i2p.data.Hash;
import net.i2p.data.RouterInfo;
import net.i2p.router.RouterContext;
+import net.i2p.router.peermanager.DBHistory;
+import net.i2p.stat.Rate;
+import net.i2p.stat.RateStat;
/**
* Helper class to refactor the HTML rendering from out of the ProfileOrganizer
@@ -33,13 +39,22 @@ class ProfileOrganizerRenderer {
public void renderStatusHTML(Writer out) throws IOException {
Set peers = _organizer.selectAllPeers();
- long hideBefore = _context.clock().now() - 3*60*60*1000;
+ long now = _context.clock().now();
+ long hideBefore = now - 3*60*60*1000;
TreeSet order = new TreeSet(_comparator);
+ TreeSet integratedPeers = new TreeSet(_comparator);
for (Iterator iter = peers.iterator(); iter.hasNext();) {
Hash peer = (Hash)iter.next();
if (_organizer.getUs().equals(peer)) continue;
PeerProfile prof = _organizer.getProfile(peer);
+ if (_organizer.isWellIntegrated(peer)) {
+ integratedPeers.add(prof);
+ } else {
+ RouterInfo info = _context.netDb().lookupRouterInfoLocally(peer);
+ if (info != null && info.getCapabilities().indexOf("f") >= 0)
+ integratedPeers.add(prof);
+ }
if (prof.getLastSendSuccessful() <= hideBefore) continue;
order.add(prof);
}
@@ -127,6 +142,75 @@ class ProfileOrganizerRenderer {
buf.append("");
}
buf.append("");
+
+ buf.append("
Peer | "); + buf.append("Caps | "); + buf.append("Integ. Value | "); + buf.append("Last Heard About | "); + buf.append("Last Heard From | "); + buf.append("Last Successful Send | "); + buf.append("Last Failed Send | "); + buf.append("10m Resp. Time | "); + buf.append("1h Resp. Time | "); + buf.append("1d Resp. Time | "); + buf.append("Successful Lookups | "); + buf.append("Failed Lookups | "); + buf.append("New Stores | "); + buf.append("Old Stores | "); + buf.append("1m Fail Rate | "); + buf.append("1h Fail Rate | "); + buf.append("1d Fail Rate | "); + buf.append("|
");
+ if (prof.getIsFailing()) {
+ buf.append("-- ").append(peer.toBase64().substring(0,6)).append("");
+ } else {
+ if (prof.getIsActive()) {
+ buf.append("++ ").append(peer.toBase64().substring(0,6)).append("");
+ } else {
+ buf.append(" ").append(peer.toBase64().substring(0,6));
+ }
+ }
+ RouterInfo info = _context.netDb().lookupRouterInfoLocally(peer);
+ if (info != null)
+ buf.append(" | ");
+ buf.append("").append(num(prof.getIntegrationValue())).append(" | "); + long time; + time = now - prof.getLastHeardAbout(); + buf.append("").append(DataHelper.formatDuration(time)).append(" | "); + time = now - prof.getLastHeardFrom(); + buf.append("").append(DataHelper.formatDuration(time)).append(" | "); + time = now - prof.getLastSendSuccessful(); + buf.append("").append(DataHelper.formatDuration(time)).append(" | "); + time = now - prof.getLastSendFailed(); + buf.append("").append(DataHelper.formatDuration(time)).append(" | "); + buf.append("").append(avg(prof, 10*60*1000l)).append(" | "); + buf.append("").append(avg(prof, 60*60*1000l)).append(" | "); + buf.append("").append(avg(prof, 24*60*60*1000l)).append(" | "); + DBHistory dbh = prof.getDBHistory(); + if (dbh != null) { + buf.append("").append(dbh.getSuccessfulLookups()).append(" | "); + buf.append("").append(dbh.getFailedLookups()).append(" | "); + buf.append("").append(dbh.getUnpromptedDbStoreNew()).append(" | "); + buf.append("").append(dbh.getUnpromptedDbStoreOld()).append(" | "); + buf.append("").append(davg(dbh, 60*1000l)).append(" | "); + buf.append("").append(davg(dbh, 60*60*1000l)).append(" | "); + buf.append("").append(davg(dbh, 24*60*60*1000l)).append(" | "); + } + } + buf.append("
Definitions:");
buf.append("