anchor.diff:  -module(consistent_hashing).
   -author("Tomasz Lichon").
   
  --type chash() :: chash:chash() | node().
  +-record(ring, {
  +    type :: single_node | multi_node | broken,
  +    chash :: chash:chash() | node(),
  +    broken_nodes = [] :: [node()]
  +}).
  +
  +-type ring() :: #ring{}.
   
   %% API
   -export([init/1, cleanup/0, get_chash_ring/0, set_chash_ring/1,
  -    get_node/1, get_nodes/2, get_all_nodes/0]).
  -
  --define(SINGLE_NODE_CHASH(Node), Node).
  --define(IS_SINGLE_NODE_CHASH(CHash), is_atom(CHash)).
  +    set_broken_node/1, set_fixed_node/1,
  +    get_node/1, get_nodes/2, get_alive_and_broken_nodes/2, get_all_nodes/0]).
   
   %%%===================================================================
   %%% API
  
positive.code: get_nth_index(N, CHash) ->
      {Index, _} = lists:nth(N, chash:nodes(CHash)),
      Index.
  
negative.code:     case get_chash_ring() of
          undefined ->
              error(chash_ring_not_initialized);
          #ring{type = single_node, chash = Node} ->
              Node;
          #ring{type = multi_node, chash = CHash} ->
              Index = chash:key_of(Label),
              [{_, BestNode}] = chash:successors(Index, CHash, 1),
              BestNode;
          #ring{type = broken, chash = CHash, broken_nodes = BrokenNodes} ->
              Index = chash:key_of(Label),
              [{_, BestNode}] = chash:successors(Index, CHash, 1),
              case lists:member(BestNode, BrokenNodes) of
                  true -> throw(broken_node);
                  false -> BestNode
              end
      end.
  
  %%--------------------------------------------------------------------
  