anchor.diff:  -define(MIN_CACHE_SECONDS_DEFAULT, 300).
   -define(MAX_CACHE_SIZE, 10000).
   
  +-type lhttpc_dns_counts() :: { SuccessCount :: non_neg_integer()
  +                             , FailureCount :: non_neg_integer()
  +                             , FailuresSinceLastSuccessCount :: non_neg_integer()
  +                             , SuccessTime :: erlang:timestamp() | 'undefined' }.
   
   -spec lookup(Host::string()) -> tuple() | 'undefined' | string().
   lookup (Host) ->
  -  %% Attempt cache lookup.
  -  {WantRefresh, CachedIPAddrs, Now} =
  +  %% Attempt cache lookup.  Each row in the lhttpc_dns ets table has a tuple
  +  %% of the form:
  +  %%
  +  %% { Hostname
  +  %% , IPAddrTuple: tuple of one or more IP address tuples, or 'undefined'.
  +  %% , CacheExpireTime: timestamp() when cache line expires.
  +  %% , {SuccessCount, FailureCount, FailuresSinceLastSuccessCount, LastSuccessTime}
  +  %% }
  +  {WantRefresh, CachedIPAddrs, Now, CachedCounts} =
       try ets:lookup(?MODULE, Host) of
  -      [] ->                                     % Not in cache.
  -        {true, undefined, lhttpc_dns:os_timestamp()};
  -      [{_, IPAddrs0, Expiration}] ->            % Cached but maybe stale.
  +      [] ->                                             % Not in cache.
  +        {true, undefined, lhttpc_dns:os_timestamp(), undefined};
  +      [{_, IPAddrs0, Expiration, CachedCounts0}] ->     % Cached, maybe stale.
           Now0 = lhttpc_dns:os_timestamp(),
  -        {Now0 >= Expiration, IPAddrs0, Now0}
  +        {Now0 >= Expiration, IPAddrs0, Now0, CachedCounts0}
       catch
         error:badarg ->
  -        {fallback, undefined, undefined}
  +        {fallback, undefined, undefined, undefined}
       end,
   
     case WantRefresh of
  
positive.code:                 lists:foldl(fun (Answer, {IPAddrAcc, MinTTL}) ->
                                  [ IPAddr, TTL ] = inet_dns:rr(Answer, [ data, ttl ]),
                                  %% Cache a successful lookup for an additional
                                  %% 2 seconds.
                                  {[ IPAddr | IPAddrAcc ], min(MinTTL, TTL + ?SUCCESS_CACHE_EXTRA_SECONDS)}
                              end, {[], ?MAX_CACHE_SECONDS}, Answers),
                {list_to_tuple(IPAddrs), max(TTL, min_cache_seconds())}
  
negative.code:       choose_addr(CachedIPAddrs);
      true ->
        %% Cached lookup failed.  Perform lookup and cache results.
        {{IPAddrs, TTL}, Counts} =
          case lhttpc_dns:lookup_uncached(Host) of
            FailureLookup = {undefined, _} ->
              %% If the lookup fails but we have a stale cached result, keep it.
              UpdatedFailureLookup =
                case CachedIPAddrs of
                  undefined -> FailureLookup;
                  _         -> {CachedIPAddrs, min_cache_seconds()}
                end,
              {UpdatedFailureLookup, count_failure(CachedCounts)};
            SuccessLookup ->
              {SuccessLookup, count_success(CachedCounts, Now)}
          end,
        ets_insert_bounded(?MODULE, {Host, IPAddrs, timestamp_add_seconds(Now, TTL), Counts}),
        choose_addr(IPAddrs)
    end.
  
  