java.lang.Object
net.i2p.router.peermanager.DBHistory

public class DBHistoryextends Object
History of NetDb related activities (lookups, replies, stores, etc).

Tracks per-peer database interaction counters and timestamps: - Successful/failed lookups - Unprompted store messages (new vs known peers) - Lookup reply quality (new/invalid/duplicate peers) - Store verification success/failure

All counters use AtomicLong and timestamps use volatile for thread-safe access from NetDB message handlers and transport threads.

Combined responsiveness rate. getFailedLookupRate() is a single rate covering both lookups and stores: every resolved lookup and every verified store adds 0, every failed lookup and every failed store verification adds 1. The persisted key stays "dbHistory.failedLookupRate" for profile compatibility, so the name understates what the rate covers. Read the rate as "fraction of NetDb requests this peer failed to answer".

  • Field Details

    • _log

      private final Log _log
      Logger for the network database statistics.
    • _context

      private final RouterContext _context
      The router context.
    • _successfulLookups

      private final AtomicLong _successfulLookups
      Lookups that found a result.
    • _failedLookups

      private final AtomicLong _failedLookups
      Lookups that found nothing.
    • _failedLookupRate

      private final RateStat _failedLookupRate
      Rate of the failed lookups.
    • _invalidReplyRate

      private final RateStat _invalidReplyRate
      Rate of the invalid replies.
    • _lastLookupSuccessful

      private volatile long _lastLookupSuccessful
      When the last successful lookup happened.
    • _lastLookupFailed

      private volatile long _lastLookupFailed
      When the last failed lookup happened.
    • _lastStoreSuccessful

      private volatile long _lastStoreSuccessful
      When the last successful store happened.
    • _lastStoreFailed

      private volatile long _lastStoreFailed
      When the last failed store happened.
    • _unpromptedDbStoreNew

      private final AtomicLong _unpromptedDbStoreNew
      Unprompted stores of new profiles.
    • _unpromptedDbStoreOld

      private final AtomicLong _unpromptedDbStoreOld
      Unprompted stores of old profiles.
    • _lastCoalesce

      private volatile long _lastCoalesce
      When the profiles were last coalesced.
    • DECAY_INTERVAL_MS

      private static final long DECAY_INTERVAL_MS
      How often the lookup and store counters decay, as a whole interval.

      Eight hours, matching TunnelHistory.DECAY_INTERVAL_MS. At fifteen minutes a peer forgot its own record faster than it could accumulate one, so a good history decayed as fast as a bad one.

      See Also:
    • DECAY_NUMERATOR

      private static final long DECAY_NUMERATOR
      Numerator of the decay factor applied per hour.
      See Also:
    • DECAY_DENOMINATOR

      private static final long DECAY_DENOMINATOR
      Denominator of the decay factor applied per hour.
      See Also:
    • NL

      private static final String NL
      The platform line separator.
    • HR

      private static final String HR
      The comment header line of the stats file.
      See Also:
  • Constructor Details

    • DBHistory

      public DBHistory(RouterContext context, String statGroup)
      Creates the lookup and invalid-reply rate statistics for one peer.
      Parameters:
      context - the router context the rates and clock are taken from
      statGroup - the grouping applied to the two RateStats created here
  • Method Details

    • getSuccessfulLookups

      public long getSuccessfulLookups()
      How many times we have sent them a db lookup and received the value back from them.
      Returns:
      the number of NetDb lookups this peer has answered
    • getFailedLookups

      public long getFailedLookups()
      How many times we have sent them a db lookup and not received the value or a lookup reply.
      Returns:
      the number of NetDb lookups this peer has not answered
    • getLastLookupSuccessful

      public long getLastLookupSuccessful()
      Time of the last successful lookup, not persisted until 0.9.24.
      Returns:
      the last lookup successful
    • getLastLookupFailed

      public long getLastLookupFailed()
      Time of the last failed lookup, not persisted until 0.9.24.
      Returns:
      the last lookup failed
    • getLastStoreSuccessful

      public long getLastStoreSuccessful()
      Time of the last successful store, not persisted until 0.9.24.
      Returns:
      the last store successful
    • getLastStoreFailed

      public long getLastStoreFailed()
      Time of the last failed store, not persisted until 0.9.24.
      Returns:
      the last store failed
    • getUnpromptedDbStoreNew

      public long getUnpromptedDbStoreNew()
      How many times have they sent us data we didn't ask for and that we've never seen?
      Returns:
      the count of unprompted stores carrying data we had never seen before
    • getUnpromptedDbStoreOld

      public long getUnpromptedDbStoreOld()
      How many times have they sent us data we didn't ask for but that we have seen?
      Returns:
      the count of unprompted stores carrying data we had seen before
    • getFailedLookupRate

      public RateStat getFailedLookupRate()
      How often this peer failed to answer a NetDb request, in 10 minute and 1 hour periods.

      Despite the name, the rate covers stores as well as lookups: a resolved lookup and a verified store both add 0, a failed lookup and a failed store verification both add 1. Read it as "fraction of NetDb requests this peer failed to answer". Lookup and store outcomes are also tracked separately by getLastLookupSuccessful(), getLastLookupFailed(), getLastStoreSuccessful() and getLastStoreFailed().

      Returns:
      the combined lookup and store failure rate
    • getInvalidReplyRate

      public RateStat getInvalidReplyRate()
      Rate at which the peer sends us invalid reply data, to be investigated.
      Returns:
      the rate at which this peer sends invalid reply data
    • lookupSuccessful

      public void lookupSuccessful()
      Note that the peer was not only able to respond to the lookup, but sent us the data we wanted!

      Also feeds the combined failure rate with a success (0).

    • lookupFailed

      public void lookupFailed()
      Note that the peer failed to respond to the db lookup in any way

      Also feeds the combined failure rate with a failure (1).

    • storeSuccessful

      public void storeSuccessful()
      Note that we successfully stored to a floodfill peer and verified the result by asking another floodfill peer

      Also feeds the combined failure rate with a success (0), and the network-wide "peer.failedLookupRate" statistic with a success (0).

    • storeFailed

      public void storeFailed()
      Note that floodfill verify failed

      Also feeds the combined failure rate with a failure (1). The network-wide "peer.failedLookupRate" statistic is deliberately not fed here, so a store failure is counted against this peer but only dilutes rather than inflates the network-wide average.

    • lookupReply

      public void lookupReply(int newPeers, int oldPeers, int invalid, int duplicate)
      Receive a lookup reply from the peer, where they gave us the specified info.
      Parameters:
      newPeers - number of peers we have never seen before
      oldPeers - number of peers we have seen before
      invalid - number of peers that are invalid / out of date / otherwise b0rked
      duplicate - number of peers we asked them not to give us (though they're allowed to send us themselves if they don't know anyone else)
    • unpromptedStoreReceived

      public void unpromptedStoreReceived(boolean wasNew)
      Note that the peer sent us a data point without us asking for it.
      Parameters:
      wasNew - whether we already knew about this data point or not
    • setSuccessfulLookups

      public void setSuccessfulLookups(long num)
      The count of successful lookups.
      Parameters:
      num - the count to store
    • setFailedLookups

      public void setFailedLookups(long num)
      The count of failed lookups.
      Parameters:
      num - the count to store
    • setUnpromptedDbStoreNew

      public void setUnpromptedDbStoreNew(long num)
      The count of unrequested db stores of data we have never seen.
      Parameters:
      num - the count to store
    • setUnpromptedDbStoreOld

      public void setUnpromptedDbStoreOld(long num)
      The count of unrequested db stores of data we have seen before.
      Parameters:
      num - the count to store
    • decayLifetimeCounters

      public void decayLifetimeCounters(long now)
      Apply the lookup and store counter decay if its interval has elapsed.

      Does not coalesce the RateStats, which stay on the caller's own cadence. See the method of the same name on TunnelHistory for why that separation matters.

      Parameters:
      now - current time in ms
    • coalesceStats

      public void coalesceStats()
      Coalesce the rate statistics and decay the lookup and store counters.

      Mirrors TunnelHistory.coalesceStats(): the RateStats are folded unconditionally, and the lifetime counters only once decayLifetimeCounters(long) finds its interval has elapsed.

    • decayCounter

      private void decayCounter(AtomicLong counter, String name)
      Apply decay to a counter. 3/4 per 8 h = ~1% after 128 hours.
      Parameters:
      counter - the lifetime counter to decay in place
      name - the counter's name, used only in the debug log
    • store

      public void store(OutputStream out) throws IOException
      Write out the data from the profile to the stream including comments.
      Parameters:
      out - the stream the profile is written to
      Throws:
      IOException - if out cannot be written
    • store

      public void store(OutputStream out, boolean addComments) throws IOException
      Write out the data from the profile to the stream.
      Parameters:
      out - the stream the profile is written to
      addComments - add comment lines to the output
      Throws:
      IOException - if out cannot be written
    • add

      private static void add(StringBuilder buf, boolean addComments, String name, long val, String description)
      Appends one named statistic to the buffer.
      Parameters:
      buf - the buffer to append to
      addComments - true to write the value as a comment
      name - the name of the statistic
      val - the value to write
      description - the description of the statistic
    • load

      public void load(Properties props)
      Load the DB history from the given properties.
      Parameters:
      props - the persisted properties naming the dbHistory.* counters
    • getLong

      private static final long getLong(Properties props, String key)
      Reads one long property from the saved stats.
      Parameters:
      props - the properties read from the file
      key - the property name to read
      Returns:
      the value, 0 if missing or invalid