anchor.diff:  %% @doc Updates the routing table due to a changed node ID, pred and/or succ.
   %% TODO what should be done here? should we really throw away everything? or trigger
   %rebuild?
  --spec update(OldRT::rt(), OldNeighbors::nodelist:neighborhood(),
  -             NewNeighbors::nodelist:neighborhood()) -> {ok, rt()}.
   update(_OldRT, _OldNeighbors, NewNeighbors) ->
       {ok, empty(NewNeighbors)}.
   %% userdevguide-end rt_frtchord:update
  
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:types
  -type key_t() :: 0..16#FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF. % 128 bit numbers
  -type external_rt_t() :: gb_tree().
  -type custom_message() :: {get_rt, SourcePID :: comm:mypid()}.
  
  % define the possible types of nodes in the routing table:
  %  - normal nodes are nodes which have been added by entry learning
  %  - source is the node at which this RT is
  %  - sticky is a node which is not to be deleted with entry filtering
  -type entry_type() :: normal | source | sticky.
  -record(rt_entry, {
          node :: node:node_type()
          , id :: key()
          , type :: entry_type()
          , spacing = 0.0 :: float() % canonical space around a node
          , adjacent_fingers = {undefined, undefined} ::
              {#rt_entry{} | 'undefined', #rt_entry{} | 'undefined'}
  
      }).
  
  -opaque(rt_entry() :: #rt_entry{}).
  
  -record(rt_t, {
          source = undefined :: key() | undefined
          , nodes = gb_trees:empty() :: gb_tree()
      }).
  
  -opaque(rt_t() :: #rt_t{}).
  
  %% userdevguide-end rt_frtchord:types
  
  % Note: must include rt_beh.hrl AFTER the type definitions for erlang < R13B04
  % to work.
  -include("rt_beh.hrl").
  
  % @doc Maximum number of entries in a routing table
  maximum_entries() -> 1000.
  
  
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %% Key Handling
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  
  %% userdevguide-begin rt_frtchord:empty
  %% @doc Creates an "empty" routing table containing the successor.
  add_sticky_nodes_to_rt([H|_] = List, RT) when is_tuple(H) ->
      lists:foldl(fun(Entry, Acc) ->
                  add_sticky_entry(Entry, Acc)
          end, RT, List).
  
  empty(Neighbors) -> 
      % enter all known nodes as sticky entries into the gb tree
      EmptyRT = #rt_t{},
      Preds = nodelist:preds(Neighbors),
      Succs = nodelist:succs(Neighbors),
      PredsAdded = add_sticky_nodes_to_rt(Preds, EmptyRT),
      SuccsAndPredsAdded = add_sticky_nodes_to_rt(Succs, PredsAdded),
      add_source_entry(nodelist:node(Neighbors), SuccsAndPredsAdded)
      .
  %% userdevguide-end rt_frtchord:empty
  
  % @doc Initialize the routing table. This function is allowed to send messages.
  init(Neighbors) -> 
      % ask the successor node for its routing table
      % XXX i have to wrap the message as the Pid given as the succ is actually the dht
  