/src/riak_zab_log.erl

http://github.com/jtuple/riak_zab · Erlang · 135 lines · 97 code · 26 blank · 12 comment · 2 complexity · 05ba406e2d7628e8553f9acf039ddce0 MD5 · raw file

  1. -module(riak_zab_log).
  2. -compile(export_all).
  3. -define(BC, riak_zab_bitcask_backend).
  4. -record(synclog, {sync_log :: term(),
  5. sync_idx :: non_neg_integer()}).
  6. %-define(DOUT(Msg, Args), io:format(Msg, Args)).
  7. -define(DOUT(Msg, Args), true).
  8. %% History API
  9. init_history_log(VG) ->
  10. <<P:128/integer>> = crypto:md5(term_to_binary(VG)),
  11. {ok, BC} = ?BC:start(P, [{data_root, "data/zab_bitcask"}]),
  12. F = fun({propose, Zxid}, _V, {MaxP, MaxC}) ->
  13. NewP = erlang:max(Zxid, MaxP),
  14. {NewP, MaxC};
  15. ({last_commit, _Prefs}, Zxid, {MaxP, MaxC}) ->
  16. NewC = erlang:max(binary_to_term(Zxid), MaxC),
  17. {MaxP, NewC};
  18. ({_B, _K}, _V, {MaxP, MaxC}) ->
  19. {MaxP, MaxC}
  20. end,
  21. {LastProposedZxid, LastCommittedZxid} = ?BC:fold(BC, F, {{0,0}, {0,0}}),
  22. LastZxid = erlang:max(LastProposedZxid, LastCommittedZxid),
  23. {LastZxid, LastCommittedZxid, BC}.
  24. get_or_default(BC, BKey, Default) ->
  25. case ?BC:get(BC, BKey) of
  26. {ok, Value} ->
  27. binary_to_term(Value);
  28. _ ->
  29. Default
  30. end.
  31. get_old_proposals(BC, LastCommittedZxid) ->
  32. ?BC:fold(BC,
  33. fun({propose, Zxid}, V, L) ->
  34. case Zxid > LastCommittedZxid of
  35. true -> [{Zxid, binary_to_term(V)} | L];
  36. false -> L
  37. end;
  38. ({_B, _K}, _V, L) ->
  39. L
  40. end,
  41. []).
  42. sync(BC={Ref,_}) ->
  43. bitcask:sync(Ref),
  44. BC.
  45. log_proposal(Zxid, Msg, BC) ->
  46. ok = ?BC:put(BC, {propose, Zxid}, term_to_binary(Msg)),
  47. sync(BC).
  48. get_proposed_keys(BC) ->
  49. ?BC:list_bucket(BC, propose).
  50. get_proposal(Zxid, BC) ->
  51. {ok, Value} = ?BC:get(BC, {propose, Zxid}),
  52. binary_to_term(Value).
  53. del_proposal(Zxid, BC) ->
  54. ok = ?BC:delete(BC, {propose, Zxid}),
  55. sync(BC).
  56. log_accepted_epoch(BC, Epoch) ->
  57. ok = ?BC:put(BC, {meta, accepted_epoch}, term_to_binary(Epoch)),
  58. sync(BC).
  59. log_current_epoch(BC, Epoch) ->
  60. ok = ?BC:put(BC, {meta, current_epoch}, term_to_binary(Epoch)),
  61. sync(BC).
  62. log_last_commit(Preflist, Zxid, BC) ->
  63. ok = ?BC:put(BC, {last_commit, Preflist}, term_to_binary(Zxid)),
  64. sync(BC).
  65. get_accepted_epoch(BC) ->
  66. get_or_default(BC, {meta, accepted_epoch}, 0).
  67. get_current_epoch(BC) ->
  68. get_or_default(BC, {meta, current_epoch}, 0).
  69. get_last_commit(Preflist, BC) ->
  70. get_or_default(BC, {last_commit, Preflist}, {0,0}).
  71. clear_proposals(BC) ->
  72. Keys = get_proposed_keys(BC),
  73. [?BC:delete(BC, Key) || Key <- Keys],
  74. sync(BC).
  75. init_sync_log(VG) ->
  76. <<P:128/integer>> = crypto:md5(term_to_binary(VG)),
  77. {ok, BC} = ?BC:start(P, [{data_root, "data/zab_sync_bitcask"}]),
  78. SyncIdx = ?BC:fold(BC,
  79. fun({_B,K}, _V, Max) -> erlang:max(K, Max) end,
  80. 0),
  81. #synclog{sync_log=BC, sync_idx=SyncIdx}.
  82. log_sync_message(Msg, SyncLog=#synclog{sync_log=BC, sync_idx=Idx}) ->
  83. Idx2 = Idx + 1,
  84. ?BC:put(BC, {<<"sync">>, Idx2}, term_to_binary(Msg)),
  85. ?DOUT("Sync: Logging ~p~n", [{Idx2, Msg}]),
  86. SyncLog#synclog{sync_idx=Idx2}.
  87. clear_sync_log(SyncLog=#synclog{sync_log=BC, sync_idx=Idx}) ->
  88. [?BC:delete(BC, {<<"sync">>, N}) || N <- lists:seq(1,Idx)],
  89. SyncLog#synclog{sync_idx=0}.
  90. fold_sync_log(SyncLog=#synclog{}, Fun, Acc) ->
  91. fold_sync_log(1, SyncLog, Fun, Acc).
  92. fold_sync_log(Idx, #synclog{sync_idx=N}, _Fun, Acc) when Idx > N ->
  93. Acc;
  94. fold_sync_log(Idx, SyncLog=#synclog{sync_log=BC}, Fun, Acc) ->
  95. {ok, Value} = ?BC:get(BC, {<<"sync">>, Idx}),
  96. Msg = binary_to_term(Value),
  97. ?DOUT("Sync: Handling ~p~n", [{Idx, Msg}]),
  98. Acc2 = Fun(Msg, Acc),
  99. fold_sync_log(Idx + 1, SyncLog, Fun, Acc2).
  100. %% Old History API
  101. %% init_history_log() ->
  102. %% {{0,0}, {0,0}, dict:new()}.
  103. %% get_old_proposals(#state{history=History,
  104. %% last_committed_zxid=LastCommittedZxid}) ->
  105. %% lists:keysort(1, dict:to_list(dict:filter(fun(K,_V) -> (K > LastCommittedZxid) end, History))).
  106. %% log_proposal(Zxid, Msg, History) ->
  107. %% dict:store(Zxid, Msg, History).
  108. %% get_proposal(Zxid, History) ->
  109. %% dict:fetch(Zxid, History).