anchor.diff:      empty(Neighbors).
   
   %% @doc Hashes the key to the identifier space.
  --spec hash_key(client_key()) -> key().
   hash_key(Key) -> hash_key_(Key).
   
   %% @doc Hashes the key to the identifier space (internal function to allow
   %%      use in e.g. get_random_node_id without dialyzer complaining about the
   %%      opaque key type).
  --spec hash_key_(client_key()) -> key_t().
   hash_key_(Key) ->
       <<N:128>> = erlang:md5(client_key_to_binary(Key)),
       N.
  
positive.code:     ;
  
  handle_custom_message({get_rt_reply, RT}, State) ->
      io:format("Got my succs RT~n", []),
      %% merge the routing tables
      LocalRT = rt_loop:get_rt(State),
      io:format("Got local RT~n"),
      NewRT = case LocalRT =:= RT of
          true ->
              io:format("Will try to merge ~p~n", [to_list(RT)]),
              %% TODO should all entries be converted to normal nodes here?
              lists:foldl(
                  fun(Entry, Acc) ->
                          entry_learn(Entry, Acc)
                  end
                  , LocalRT, to_list(RT))
              ;
          false ->
              io:format("RTs are already the same."),
              LocalRT
      end,
      io:format("Merged RTs"),
      rt_loop:set_rt(State, NewRT)
  
negative.code: %% userdevguide-begin rt_frtchord:filter_dead_node
  %% @doc Removes dead nodes from the routing table (rely on periodic
  %%      stabilization here).
  filter_dead_node(RT, DeadPid) -> 
      % find the node id of DeadPid and delete it from the RT
      [Node] = [N || {N, _,_,_} <- to_list(RT), node:pidX(N) =:= DeadPid],
      entry_delete(node:id(Node), RT)
      .
  %% userdevguide-end rt_frtchord:filter_dead_node
  
  %% userdevguide-begin rt_frtchord:to_pid_list
  %% @doc Returns the pids of the routing table entries.
  %% TODO RT should probably be a State tuple, not the RT itself
  to_pid_list(RT) -> [node:pidX(rt_entry_node(N)) || N <- to_list(RT)].
  %% userdevguide-end rt_frtchord:to_pid_list
  
  %% userdevguide-begin rt_frtchord:get_size
  %% @doc Returns the size of the routing table.
  get_size(RT) -> gb_trees:size(get_rt_tree(RT)).
  %% userdevguide-end rt_frtchord:get_size
  
  %% userdevguide-begin rt_frtchord:n
  %% @doc Returns the size of the address space.
  n() -> n_().
  %% @doc Helper for n/0 to make dialyzer happy with internal use of n/0.
  n_() -> 16#FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + 1.
  %% userdevguide-end rt_frtchord:n
  
  %% @doc Keep a key in the address space. See n/0.
  normalize(Key) -> Key band 16#FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF.
  
  %% @doc Gets the number of keys in the interval (Begin, End]. In the special
  %%      case of Begin==End, the whole key range as specified by n/0 is returned.
  get_range(Begin, End) -> get_range_(Begin, End).
  
  %% @doc Helper for get_range/2 to make dialyzer happy with internal use of
  %%      get_range/2 in the other methods, e.g. get_split_key/3.
  get_range_(Begin, Begin) -> n_(); % I am the only node
  get_range_(?MINUS_INFINITY, ?PLUS_INFINITY) -> n_(); % special case, only node
  get_range_(Begin, End) when End > Begin -> End - Begin;
  