anchor.diff:          , switch/3            %% switch to a new segment
           , switch_append/4     %% switch then append
           , delete_oldest_seg/2 %% Delete oldest segment from index
  +        , delete_from_cache/2 %% Delete given log entry from index cache
           ]).
   
   %% APIs for readers (public access)
  
positive.code:       after
          ok = file:close(Fd)
        end,
        init_ets_from_index_files(Tid, Rest);
      {error, Reason} ->
        file:close(Fd),
        erlang:error(Reason)
    end.
  
  -spec init_ets_from_index_file(logvsn(), cache(), segid(), file:fd()) -> ok | no_return().
  
negative.code:     file:close(Fd)
    end.
  
  %% @doc Delete given log entry (logid) from index.
  %% Return new index.
  %% NB! Refuse to delete the first log entry of each segment (i.e. when segid = logid).
  %% @end
  -spec delete_from_cache(index() | cache(), logid()) -> cache() | index().
  delete_from_cache(#idx{tid = Tid} = Idx, LogId) ->
    Tid = delete_from_cache(Tid, LogId),
    Idx;
  delete_from_cache(Tid, LogId) ->
    LatestLogId = get_latest_logid(Tid),
    case LogId =:= LatestLogId of
      true ->
        false; %% never delete the latest to keep a correect boundary check
      false ->
        case ets:lookup(Tid, LogId) of
          [] ->
            false; %% either out of range, or already deleted
          [?ETS_ENTRY(SegId, SegId, _Pos)] ->
            false; %% refuse to delete
          [?ETS_ENTRY(_SegId, LogId, _Pos)] ->
            ets:delete(Tid, LogId)
        end
    end,
    Tid.
  
  %%%*_ PRIVATE FUNCTIONS ========================================================
  
  %% @private Scan the index file to locate the log position in segment file
  