anchor.diff:           terminate/2, code_change/3]).
   
   -define(FLU_PC, machi_proxy_flu1_client).
  +-define(TIMEOUT, 2*1000).
   
   -record(state, {
             members_dict    :: p_srvr_dict(),
  
positive.code: 
  update_proj2(Count, #state{bad_proj=BadProj, proxies_dict=ProxiesDict}=S) ->
      Timeout = 2*1000,
      PidsMons =
          [spawn_monitor(fun() ->
                                 exit(catch ?FLU_PC:read_latest_projection(
                                               Proxy, private, Timeout))
                         end) || {_K, Proxy} <- orddict:to_list(ProxiesDict)],
      Rs = gather_worker_statuses(PidsMons, Timeout*2),
      case choose_best_proj(Rs) of
          P when P >= BadProj ->
              io:format(user, "~s: proj ~P\n", [?MODULE, P, 10]),
              EpochID = {P#projection_v1.epoch_number,
                         P#projection_v1.epoch_csum},
              S#state{bad_proj=undefined, proj=EpochID, epoch_id=EpochID};
          _ ->
              timer:sleep(10 + (Count * 20)),
              update_proj2(Count + 1, S)
  
negative.code: %%%%%%%%%%%%%%%%%%%%%%%%%%%
  
  handle_call2({append_chunk_extra, Prefix, Chunk, ChunkExtra}, _From, S) ->
      do_append_chunk_extra1(Prefix, Chunk, ChunkExtra, S).
  
  do_append_chunk_extra1(Prefix, Chunk, ChunkExtra,
                         #state{epoch_id=EpochID, proj=P,
                                proxies_dict=PD}=S) ->
      #projection_v1{upi=[HeadFLU|RestFLUs]} = P,
      case ?FLU_PC:append_chunk_extra(orddict:fetch(HeadFLU, PD),
                                      EpochID, Prefix, Chunk, ChunkExtra,
                                      ?TIMEOUT) of
          {ok, {Offset, _Size, File}=_X} ->
              io:format(user, "TODO: X ~p\n", [_X]),
              do_append_chunk_extra2(RestFLUs, File, Offset, Chunk,
                                     HeadFLU, 1, S);
          {error, Change} when Change == bad_epoch; Change == wedged ->
              S2 = update_proj(S#state{proj=undefined, bad_proj=P}),
              do_append_chunk_extra1(Prefix, Chunk, ChunkExtra, S2)
          %% TODO return values here
      end.
  
  do_append_chunk_extra2([], File, Offset, _Chunk, _OldHeadFLU, _OkCount, S) ->
      {reply, {ok, {File, Offset}}, S};
  do_append_chunk_extra2([FLU|RestFLUs], File, Offset, Chunk, OldHeadFLU, OkCount,
                         #state{epoch_id=EpochID, proj=P,
                                proxies_dict=PD}=S) ->
      case ?FLU_PC:write_chunk(orddict:fetch(FLU, PD),
                                      EpochID, File, Offset, Chunk, ?TIMEOUT) of
          ok ->
              do_append_chunk_extra2(RestFLUs, File, Offset, Chunk,
                                     OldHeadFLU, OkCount + 1, S);
          {error, Change} when Change == bad_epoch; Change == wedged ->
              S2 = update_proj(S#state{proj=undefined, bad_proj=P}),
              #projection_v1{upi=[NewHeadFLU|NewRestFLUs]} = S2#state.proj,
              if OkCount == 1, NewHeadFLU == OldHeadFLU ->
                      do_append_chunk_extra2(NewRestFLUs, File, Offset, Chunk,
                                             OldHeadFLU, OkCount, S2);
                 true ->
                      {error, partition}
              end
          %% TODO return values here
      end.
  
  update_proj(#state{proj=undefined}=S) ->
      update_proj2(1, S);
  