anchor.diff:      NewState = {NewNeighborhood, NewRandViewSize, NewInterval, TriggerState, NewCache, NewChurn},
       case nodelist:pred(OldNeighborhood) =/= nodelist:pred(NewNeighborhood) orelse
           nodelist:succ(OldNeighborhood) =/= nodelist:succ(NewNeighborhood) of
  -        true -> element(2, handle_custom_message({rm_trigger_action}, NewState));
  +        true -> element(2, rm_trigger_action(NewState));
           _    -> NewState
       end.
   
  
positive.code: update_node({Neighborhood, RandViewSize, Interval, TriggerState, Cache, Churn}, NewMe) ->
      NewNeighborhood = nodelist:update_node(Neighborhood, NewMe),
      % inform neighbors
      handle_custom_message({rm_trigger_action}, {NewNeighborhood, RandViewSize, 
                                                  Interval, TriggerState, Cache, Churn}).
  
  
  -spec leave(State::state()) -> ok.
  
negative.code: handle_custom_message({rm_trigger},
     {Neighborhood, RandViewSize, _Interval, TriggerState, Cache, Churn}) ->
      NewTriggerState = trigger:next(TriggerState),
      rm_trigger_action({Neighborhood, RandViewSize, base_interval,
                         NewTriggerState, Cache, Churn});
  
  handle_custom_message({rm_trigger_action}, State) ->
      rm_trigger_action(State);
  
  % got empty cyclon cache
  handle_custom_message({rm, {cy_cache, []}},
     {_Neighborhood, RandViewSize, _Interval, _TriggerState, _Cache, _Churn} = State)  ->
      % ignore empty cache from cyclon
      cyclon:get_subset_rand_next_interval(RandViewSize,
                                           comm:reply_as(self(), 2, {rm, '_'})),
      {{unknown}, State};
  
  % got cyclon cache
  handle_custom_message({rm, {cy_cache, NewCache}},
     {Neighborhood, RandViewSize, Interval, TriggerState, _Cache, Churn}) ->
      % increase RandViewSize (no error detected):
      RandViewSizeNew =
          case (RandViewSize < config:read(cyclon_cache_size)) of
              true  -> RandViewSize + 1;
              false -> RandViewSize
          end,
      % trigger new cyclon cache request
      cyclon:get_subset_rand_next_interval(RandViewSizeNew,
                                           comm:reply_as(self(), 2, {rm, '_'})),
      MyRndView = get_RndView(RandViewSizeNew, NewCache),
      OtherNeighborhood =
          nodelist:mk_neighborhood(NewCache, nodelist:node(Neighborhood),
                                   get_pred_list_length(), get_succ_list_length()),
      NewNeighborhood = trigger_update(Neighborhood, MyRndView, OtherNeighborhood),
      {{node_discovery}, {NewNeighborhood, RandViewSizeNew, Interval,
                          TriggerState, NewCache, Churn}};
  
  % got shuffle request
  handle_custom_message({rm, buffer, OtherNeighbors, RequestPredsMinCount, RequestSuccsMinCount},
     {Neighborhood, RandViewSize, Interval, TriggerState, Cache, Churn}) ->
      MyRndView = get_RndView(RandViewSize, Cache),
      MyView = lists:append(MyRndView, nodelist:to_list(Neighborhood)),
      OtherNode = nodelist:node(OtherNeighbors),
      OtherNodeId = node:id(OtherNode),
      OtherLastPredId = node:id(lists:last(nodelist:preds(OtherNeighbors))),
      OtherLastSuccId = node:id(lists:last(nodelist:succs(OtherNeighbors))),
      % note: the buffer message, esp. OtherNode, might already be outdated
      % and our own view may contain a newer version of the node
      {[OtherNodeUpd], MyViewUpd} = nodelist:lupdate_ids([OtherNode], MyView),
      NeighborsToSendTmp = nodelist:mk_neighborhood(MyViewUpd, OtherNodeUpd,
                                                    get_pred_list_length(),
                                                    get_succ_list_length()),
      NeighborsToSend =
          nodelist:filter_min_length(
            NeighborsToSendTmp,
            fun(N) ->
                    intervals:in(node:id(N), intervals:new('(', OtherNodeId, OtherLastSuccId, ')')) orelse
                        intervals:in(node:id(N), intervals:new('(', OtherLastPredId, OtherNodeId, ')'))
            end,
            RequestPredsMinCount, RequestSuccsMinCount),
      comm:send(node:pidX(nodelist:node(OtherNeighbors)),
                {rm, buffer_response, NeighborsToSend}, ?SEND_OPTIONS),
      NewNeighborhood = trigger_update(Neighborhood, MyRndView, OtherNeighbors),
      {{node_discovery}, {NewNeighborhood, RandViewSize, Interval,
                          TriggerState, Cache, Churn}};
  
  handle_custom_message({rm, buffer_response, OtherNeighbors},
     {Neighborhood, RandViewSize, Interval, TriggerState, Cache, Churn}) ->
      MyRndView = get_RndView(RandViewSize, Cache),
      NewNeighborhood = trigger_update(Neighborhood, MyRndView, OtherNeighbors),
      % increase RandViewSize (no error detected):
      NewRandViewSize =
          case RandViewSize < config:read(cyclon_cache_size) of
              true ->  RandViewSize + 1;
              false -> RandViewSize
          end,
      {{node_discovery}, {NewNeighborhood, NewRandViewSize, Interval,
                          TriggerState, Cache, Churn}};
  
  % we asked another node we wanted to add for its node object -> now add it
  % (if it is not in the process of leaving the system)
  handle_custom_message({rm, {get_node_details_response, NodeDetails}}, State) ->
      case node_details:get(NodeDetails, is_leaving) of
          false ->
              NewState =
                  update_nodes(State, [node_details:get(NodeDetails, node)], [], null),
              {{node_discovery}, NewState};
          true ->
              {{unknown}, State}
      end;
  
  handle_custom_message(_, _State) -> unknown_event.
  
  -spec rm_trigger_action(State::state_t())
          -> {ChangeReason::rm_loop:reason(), state()}.
  rm_trigger_action({Neighborhood, RandViewSize, Interval, TriggerState, Cache, Churn} = State) ->
      % Trigger an update of the Random view
      % Test for being alone:
      case nodelist:has_real_pred(Neighborhood) andalso
  