anchor.diff:  -undef(DEF_TIMEOUT).
   
   -ifdef(TEST).
  --define(CURRENT_TIME,      65432100000).
  +-define(CURRENT_TIME, 65432100000).
   -define(DEF_SYNC_MIN_INTERVAL,  5).
   -define(DEF_SYNC_MAX_INTERVAL, 10).
   -define(DEF_TIMEOUT,         1000).
   -else.
  --define(CURRENT_TIME,      leo_date:now()).
  +-define(CURRENT_TIME, leo_date:now()).
   -define(DEF_SYNC_MIN_INTERVAL,  250).
   -define(DEF_SYNC_MAX_INTERVAL, 1500).
  --define(DEF_TIMEOUT,       3000).
  +-define(DEF_TIMEOUT,           3000).
   -endif.
   
   -define(DEF_NUM_OF_DIV, 32).
   
   -record(routing_table, {index = []    :: list(pos_integer()),
                           checksum = -1 :: integer(),
  +                        rows  = -1    :: integer(),
                           table = []    :: list()
                          }).
   
  
positive.code: 
  %% @private
  maybe_sync_1(State, {R1, R2}, {CurHash, PrevHash}) ->
      State1 = case (R1 == CurHash) of
                   true  -> State;
                   false ->
                       {ok, {CurHash1, CurIdx, CurTbl}} = gen_routing_table(?SYNC_MODE_CUR_RING),
                       State#state{cur = #routing_table{checksum = CurHash1,
                                                        index    = CurIdx,
                                                        table    = CurTbl}}
               end,
      State2 = case (R2 == PrevHash) of
                   true  -> State1;
                   false ->
                       {ok, {PrevHash1, PrevIdx, PrevTbl}} = gen_routing_table(?SYNC_MODE_PREV_RING),
                       State1#state{prev = #routing_table{checksum = PrevHash1,
                                                          index    = PrevIdx,
                                                          table    = PrevTbl}}
               end,
      State2.
  
  
  %% @doc Generate RING for this process
  %% @private
  gen_routing_table(Version) ->
      %% Retrieve ring from local's master [etc|mnesia]
      {ok, CurRing} = leo_redundant_manager_api:get_ring(Version),
      Checksum  = erlang:crc32(term_to_binary(CurRing)),
      RingSize  = length(CurRing),
      GroupSize = leo_math:ceiling(RingSize / ?DEF_NUM_OF_DIV),
  
      %% table:{id, vnode-id, node, next-vnode-id}
      {_,_,_,Index,Table} =
          lists:foldl(
            fun({VId, Node}, {Id, GId, NextVId, IdxAcc, TblAcc}) when GId == GroupSize ->
                    {Id - 1, 0, VId, [{Id, VId}|IdxAcc], [{Id, VId, Node, NextVId}|TblAcc]};
               ({VId, Node}, {Id, GId, NextVId, IdxAcc, TblAcc}) ->
                    {Id - 1, GId + 1, VId, IdxAcc, [{Id, VId, Node, NextVId}|TblAcc]}
            end, {RingSize, 0, '$end_of_table', [], []}, lists:reverse(CurRing)),
      {ok, {Checksum, lists:reverse(Index), Table}}.
  
  
  %% @doc Retrieve a ring's list
  %% @private
  get_ring(Tbl, State) ->
      case Tbl of
          ?CUR_RING_TABLE  -> (State#state.cur )#routing_table.table;
          ?PREV_RING_TABLE -> (State#state.prev)#routing_table.table;
          _ ->
              []
      end.
  
  
  %% @doc Retrieve index's list
  %%      - [{rowid, addr-id}|...]
  %% @private
  get_index(Tbl, State) ->
      case Tbl of
          ?CUR_RING_TABLE  -> (State#state.cur )#routing_table.index;
          ?PREV_RING_TABLE -> (State#state.prev)#routing_table.index;
          _ ->
              []
      end.
  
  
  %% @doc Retrieve vnode-id from a ring's list
  %% @private
  get_vnode_id(RowId, VNodeId, Ring) when RowId =< length(Ring) ->
      {_, Rest} = lists:split(RowId, Ring),
      get_vnode_id_1(VNodeId, Rest);
  get_vnode_id(_,_,_) ->
      [].
  
  get_vnode_id_1(_VNodeId, []) ->
      [];
  get_vnode_id_1(VNodeId, [{_, AddrId,_VNode, _}|_Rest] ) when VNodeId < AddrId ->
      [];
  get_vnode_id_1(VNodeId, [{_, AddrId, VNode, _}|_Rest]) when VNodeId == AddrId ->
      VNode;
  get_vnode_id_1(VNodeId, [{_, AddrId,_VNode, _}|Rest]) when VNodeId > AddrId ->
      get_vnode_id_1(VNodeId, Rest).
  
  
  %% @doc Find index by vnode-id
  %% @private
  find_index(_VNodeId,[]) ->
      0;
  find_index(VNodeId, [{RowId, Index}|_]) when VNodeId >= Index ->
      RowId - 1;
  find_index(VNodeId, [_|Rest]) ->
      find_index(VNodeId, Rest).
  
  
  %% @doc Find vnode-id by rowid and addrId
  %% @private
  next_vnode_id(RowId, VNodeId, Ring) when RowId =< length(Ring) ->
      {_, Rest} = lists:split(RowId, Ring),
      next_vnode_id_1(VNodeId, Rest);
  next_vnode_id(_,_,_) ->
      '$end_of_table'.
  
  next_vnode_id_1(_VNodeId, []) ->
      '$end_of_table';
  next_vnode_id_1(VNodeId, [{_, AddrId,_Node, _}|_]) when VNodeId < AddrId ->
      AddrId;
  next_vnode_id_1(VNodeId, [_|Rest]) ->
      next_vnode_id_1(VNodeId, Rest).
  
  
  %% @doc Find vnode-id by rowid and addrId
  %% @private
  prev_vnode_id(RowId, VNodeId, Ring) when RowId =< length(Ring) ->
      {Head, _Rest} = lists:split(RowId + 1, Ring),
      prev_vnode_id_1(VNodeId, lists:reverse(Head));
  prev_vnode_id(_,_,_) ->
      '$end_of_table'.
  
  prev_vnode_id_1(_VNodeId, []) ->
      '$end_of_table';
  prev_vnode_id_1(VNodeId, [{_, AddrId,_Node, _}|_]) when VNodeId > AddrId ->
      AddrId;
  prev_vnode_id_1(VNodeId, [_|Rest]) ->
      prev_vnode_id_1(VNodeId, Rest).
  
  
negative.code:     {stop, normal, ok, State};
  
  
  handle_call({lookup, Tbl, VNodeId},_From, State) ->
      ?debugVal({Tbl, VNodeId}),
      Reply = ok,
      {reply, Reply, State};
  
  
  handle_call({first, Tbl},_From, State) ->
      ?debugVal(Tbl),
      Reply = ok,
      {reply, Reply, State};
  
  
  handle_call({last, Tbl},_From, State) ->
      ?debugVal(Tbl),
      Reply = ok,
      {reply, Reply, State};
  
  
  handle_call({force_sync, {_, ?CUR_RING_TABLE}},_From, State) ->
      {ok, Members} = leo_redundant_manager_table_member:find_all(),
      {ok, Options} = leo_misc:get_env(?APP, ?PROP_OPTIONS),
      N  = leo_misc:get_value(?PROP_N,  Options),
      L2 = leo_misc:get_value(?PROP_L2, Options, 0),
  
      {ok, {Checksum, Index, RingSize, Ring}} =
          gen_routing_table(?SYNC_MODE_CUR_RING, N, L2, Members),
      NewState = State#state{cur = #routing_table{checksum = Checksum,
                                                  index    = Index,
                                                  rows     = RingSize,
                                                  table    = Ring}},
      {reply, ok, NewState};
  handle_call({force_sync, {_, ?PREV_RING_TABLE}},_From, State) ->
      {ok, Members} = leo_redundant_manager_table_member:find_all(),
      {ok, Options} = leo_misc:get_env(?APP, ?PROP_OPTIONS),
      N  = leo_misc:get_value(?PROP_N,  Options),
      L2 = leo_misc:get_value(?PROP_L2, Options, 0),
  
      {ok, {Checksum, Index, RingSize, Ring}} =
          gen_routing_table(?SYNC_MODE_PREV_RING, N, L2, Members),
      NewState = State#state{prev = #routing_table{checksum = Checksum,
                                                   index    = Index,
                                                   rows     = RingSize,
                                                   table    = Ring}},
      {reply, ok, NewState};
  
  
  