anchor.diff:  
   %% Delete entries with latest access time older than TM.
   %% Delete max N number of entries.
  -%% Returns the number of deleted entries.
  +%% Return the number of deleted entries.
  +%%
   delete_older(CacheDb, TM, N) ->
  -    true = ets:safe_fixtable(CacheDb, true),
  -    Res = delete_older(ets:first(CacheDb), CacheDb, TM, N, 0),
  -    true = ets:safe_fixtable(CacheDb, false),
  -    Res.
  -
  -delete_older('$end_of_table', _, _, _, M) ->
  -    M;
  -delete_older(_, _, _, M, M) ->
  -    M;
  -delete_older(Key, CacheDb, TM, N, M) ->
  -    Next = ets:next(CacheDb, Key),
  -    M1 =
  -	case ets:lookup(CacheDb, Key) of
  -	    [{_,_,Cnt}] when Cnt =< TM ->
  -		ets:delete(CacheDb, Key),
  -		M + 1;
  -	    _ ->
  -		M
  -	  end,
  -    delete_older(Next, CacheDb, TM, N, M1).
  +    RRsToDelete =
  +        ets:foldl(
  +          fun (#dns_rr{cnt = C} = RR, RRs)
  +              when C =< TM -> % Candidate for deletion
  +                  [RR | RRs];
  +              (#dns_rr{}, RRs) ->
  +                  RRs
  +          end, [], CacheDb),
  +    N - delete_older_n(CacheDb, lists:keysort(#dns_rr.cnt, RRsToDelete), N).
  +
  +delete_older_n(_CacheDb, RRs, 0) when is_list(RRs) ->
  +    0;
  +delete_older_n(_CacheDb, [], N) ->
  +    N;
  +delete_older_n(CacheDb, [RR | RRs], N) ->
  +    ets:delete_object(CacheDb, RR),
  +    delete_older_n(CacheDb, RRs, N - 1).
   
   
   %% as lists:delete/2, but delete all exact matches
  
positive.code: is_reqname(clear_hosts) -> true;
  is_reqname(_) -> false.
  
  %% Add a resource record to the cache if there are space left.
  %% If the cache is full this function first deletes old entries,
  %% i.e. entries with oldest latest access time.
  do_add_rr(RR, Db, State) ->
      CacheDb = State#state.cache,
      TM = times(),
      case alloc_entry(Db, CacheDb, TM) of
  	true ->
  	    cache_rr(CacheDb, RR#dns_rr{tm = TM, cnt = TM}, TM);
  	_ ->
  	    false
      end.
  
  cache_rr(Cache, RR, Count) ->
      ets:insert(Cache, {cache_key(RR), RR, Count}).
  
  times() ->
      erlang:monotonic_time(second).
      %% erlang:convert_time_unit(erlang:monotonic_time() - erlang:system_info(start_time),
      %%     		     native, second).
  
  %% match and remove old entries
  
  match_rr({_, _, _} = Key) ->
      Time = times(),
      case ets:lookup(inet_cache, Key) of
  	[{_,RR,_}] when RR#dns_rr.ttl =:= 0 ->
  	    %% ttl=0 is served once (by the current process) as we request
  	    %% a deletion immediately. It is served at least once concurrently.
  	    %% Deletions are safe thanks to the use of safe_fixtable.
  	    ets:delete(inet_cache, Key),
  	    [RR];
  	[{_,RR,_}] when RR#dns_rr.tm + RR#dns_rr.ttl < Time ->
  	    ets:delete(inet_cache, Key),
  	    [];
  	[{_,RR,_}] ->
  	    %% Update the entry concurrently. If the server deletes it, we ignore
  	    %% the result. If the server updates it, we will race on the time part
  	    %% which should be close enough to each other (as we are racing).
  	    _ = ets:update_element(inet_cache, Key, {3, Time}),
  	    [RR];
  	[] ->
  	    []
      end.
  
  cache_key(#dns_rr{domain = Domain, class = Class, type = Type}) ->
      {Domain, Class, Type}.
  
  %% Lower case the domain name before storage.
  %%
  lower_rr(#dns_rr{domain=Domain}=RR) when is_list(Domain) ->
      RR#dns_rr { domain = tolower(Domain) };
  
negative.code:     call({add_rr, RR}).
  
  add_rr(Domain, Class, Type, TTL, Data) ->
      call({add_rr, dns_rr_add(Domain, Class, Type, TTL, Data)}).
  
  del_rr(Domain, Class, Type, Data) ->
      call({del_rr, dns_rr_match(Domain, Class, Type, Data)}).
  
  res_cache_answer(Rec) ->
      lists:foreach( fun(RR) -> add_rr(RR) end, Rec#dns_rec.anlist).
  