anchor.diff:      TM = times(),
       case alloc_entry(Db, CacheDb, TM) of
   	true ->
  -	    cache_rr(Db, CacheDb, RR#dns_rr{tm = TM, cnt = TM});
  +	    cache_rr(CacheDb, RR#dns_rr{tm = TM, cnt = TM});
   	_ ->
   	    false
       end.
   
  -cache_rr(_Db, Cache, RR) ->
  -    %% delete possible old entry
  -    ets:match_delete(Cache, RR#dns_rr{cnt = '_', tm = '_', ttl = '_',
  -				      bm = '_', func = '_'}),
  -    ets:insert(Cache, RR).
  +cache_rr(Cache, RR) ->
  +    ets:insert(Cache, {cache_key(RR), RR}).
   
   times() ->
       erlang:monotonic_time(second).
       %% erlang:convert_time_unit(erlang:monotonic_time() - erlang:system_info(start_time),
       %%     		     native, second).
   
  -%% lookup and remove old entries
  -
  -do_lookup_rr(Domain, Class, Type) ->
  -    match_rr(#dns_rr{domain = tolower(Domain), class = Class,type = Type,
  -		     cnt = '_', tm = '_', ttl = '_',
  -		     bm = '_', func = '_', data = '_'}).
  -
  -match_rr(RR) ->
  -    filter_rr(ets:match_object(inet_cache, RR), times()).
  -
  -
  -%% filter old resource records and update access count
  -
  -filter_rr([RR | RRs], Time) when RR#dns_rr.ttl =:= 0 -> %% at least once
  -    ets:match_delete(inet_cache, RR),
  -    [RR | filter_rr(RRs, Time)];
  -filter_rr([RR | RRs], Time) when RR#dns_rr.tm + RR#dns_rr.ttl < Time ->
  -    ets:match_delete(inet_cache, RR),
  -    filter_rr(RRs, Time);
  -filter_rr([RR | RRs], Time) ->
  -    ets:match_delete(inet_cache, RR),
  -    ets:insert(inet_cache, RR#dns_rr { cnt = Time }),
  -    [RR | filter_rr(RRs, Time)];
  -filter_rr([], _Time) ->  [].
  +%% match and remove old entries
  +
  +match_rr({_, _, _} = Key) ->
  +    Time = times(),
  +    case ets:lookup(inet_cache, Key) of
  +	[{_,RR}] when RR#dns_rr.ttl =:= 0 -> %% at least once
  +	    ets:delete(inet_cache, Key),
  +	    [RR];
  +	[{_,RR}] when RR#dns_rr.tm + RR#dns_rr.ttl < Time ->
  +	    ets:delete(inet_cache, Key),
  +	    [];
  +	[{_,RR}] ->
  +        %% This may fail if cache pruning removes this entry
  +        %% at the same time we are updating it, so ignore the result.
  +	    _ = ets:update_element(inet_cache, Key, {2, RR#dns_rr{cnt = Time}}),
  +	    [RR];
  +	[] ->
  +	    []
  +    end.
  +
  +cache_key(#dns_rr{domain = Domain, class = Class, type = Type}) ->
  +    {Domain, Class, Type}.
   
   %% Lower case the domain name before storage.
   %%
  
positive.code: 	    {reply, ok, State};
  
  	clear_cache ->
  	    ets:match_delete(State#state.cache, '_'),
  	    {reply, ok, State};
  
  	reset ->
  
negative.code: do_refresh_cache('$end_of_table', _, _, OldestT) ->
      OldestT;
  do_refresh_cache(Key, CacheDb, Now, OldestT) ->
      Next = ets:next(CacheDb, Key),
      OldT =
          case ets:lookup(CacheDb, Key) of
  	    [{_,RR}] when RR#dns_rr.tm + RR#dns_rr.ttl < Now ->
  		ets:delete(CacheDb, Key),
  		OldestT;
  	     [{_,#dns_rr{cnt = C}}] when C < OldestT ->
  		C;
  	     _ ->
  		OldestT
  	end,
      do_refresh_cache(Next, CacheDb, Now, OldT).
  
  %% -------------------------------------------------------------------
  