WIP: first round of tango_oid refactoring, all broken horribly
This commit is contained in:
parent
03f071316c
commit
9a3ac02413
4 changed files with 164 additions and 159 deletions
|
@ -33,6 +33,7 @@
|
||||||
|
|
||||||
-record(proj, { % Projection
|
-record(proj, { % Projection
|
||||||
dir :: string(),
|
dir :: string(),
|
||||||
|
page_size :: non_neg_integer(),
|
||||||
epoch :: non_neg_integer(),
|
epoch :: non_neg_integer(),
|
||||||
seq :: 'undefined' | seq_name(),
|
seq :: 'undefined' | seq_name(),
|
||||||
r :: [#range{}]
|
r :: [#range{}]
|
||||||
|
|
|
@ -372,5 +372,5 @@ simple_test_setup(RootDir, BaseDirName, PageSize, NumPages, NumFLUs) ->
|
||||||
|
|
||||||
{ok, Seq} = corfurl_sequencer:start_link(FLUs),
|
{ok, Seq} = corfurl_sequencer:start_link(FLUs),
|
||||||
P0 = corfurl:new_simple_projection(PDir, 1, 1, 1*100, [FLUs]),
|
P0 = corfurl:new_simple_projection(PDir, 1, 1, 1*100, [FLUs]),
|
||||||
P1 = P0#proj{seq={Seq, unused, unused}},
|
P1 = P0#proj{seq={Seq, unused, unused}, page_size=PageSize},
|
||||||
{FLUs, Seq, P1, DeleteFLUData}.
|
{FLUs, Seq, P1, DeleteFLUData}.
|
||||||
|
|
|
@ -157,30 +157,35 @@ append_page(Proj, Page, StreamList) ->
|
||||||
|
|
||||||
append_page(Proj, _Page, _StreamList, 0) ->
|
append_page(Proj, _Page, _StreamList, 0) ->
|
||||||
{{error_failed, ?MODULE, ?LINE}, Proj};
|
{{error_failed, ?MODULE, ?LINE}, Proj};
|
||||||
append_page(#proj{seq={Sequencer,_,_}} = Proj, Page, StreamList, Retries) ->
|
append_page(#proj{seq={Sequencer,_,_}, page_size=PageSize} = Proj,
|
||||||
|
OrigPage, StreamList, Retries) ->
|
||||||
try
|
try
|
||||||
{ok, LPN} = corfurl_sequencer:get(Sequencer, 1, StreamList),
|
{ok, LPN, BackPsList} = corfurl_sequencer:get_tails(Sequencer, 1,
|
||||||
|
StreamList),
|
||||||
%% pulse_tracing_add(write, LPN),
|
%% pulse_tracing_add(write, LPN),
|
||||||
append_page1(Proj, LPN, Page, StreamList, 5)
|
Page = tango:pack_v1(StreamList, [to_final_page],
|
||||||
|
OrigPage, PageSize),
|
||||||
|
append_page1(Proj, LPN, Page, StreamList, 5, OrigPage)
|
||||||
catch
|
catch
|
||||||
exit:{Reason,{_gen_server_or_pulse_gen_server,call,[Sequencer|_]}}
|
exit:{Reason,{_gen_server_or_pulse_gen_server,call,[Sequencer|_]}}
|
||||||
when Reason == noproc; Reason == normal ->
|
when Reason == noproc; Reason == normal ->
|
||||||
NewSeq = corfurl_client:restart_sequencer(Proj),
|
NewSeq = corfurl_client:restart_sequencer(Proj),
|
||||||
append_page(Proj#proj{seq=NewSeq}, Page, StreamList, Retries);
|
append_page(Proj#proj{seq=NewSeq}, OrigPage, StreamList, Retries);
|
||||||
exit:Exit ->
|
exit:Exit ->
|
||||||
{{error_failed, ?MODULE, ?LINE}, incomplete_code, Exit}
|
{{error_failed, ?MODULE, ?LINE}, incomplete_code, Exit}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
append_page1(Proj, _LPN, _Page, _StreamList, 0) ->
|
append_page1(Proj, _LPN, _Page, _StreamList, 0, _OrigPage) ->
|
||||||
{{error_failed, ?MODULE, ?LINE}, Proj};
|
{{error_failed, ?MODULE, ?LINE}, Proj};
|
||||||
append_page1(Proj, LPN, Page, StreamList, Retries) ->
|
append_page1(Proj, LPN, Page, StreamList, Retries, OrigPage) ->
|
||||||
case append_page2(Proj, LPN, Page) of
|
case append_page2(Proj, LPN, Page) of
|
||||||
lost_race ->
|
lost_race ->
|
||||||
append_page(Proj, Page, StreamList, Retries - 1);
|
append_page(Proj, OrigPage, StreamList, Retries - 1);
|
||||||
error_badepoch ->
|
error_badepoch ->
|
||||||
case corfurl_sequencer:poll_for_new_epoch_projection(Proj) of
|
case corfurl_sequencer:poll_for_new_epoch_projection(Proj) of
|
||||||
{ok, NewProj} ->
|
{ok, NewProj} ->
|
||||||
append_page1(NewProj, LPN, Page, StreamList, Retries - 1);
|
append_page1(NewProj, LPN, Page, StreamList, Retries - 1,
|
||||||
|
OrigPage);
|
||||||
Else ->
|
Else ->
|
||||||
{Else, Proj}
|
{Else, Proj}
|
||||||
end;
|
end;
|
||||||
|
|
|
@ -20,193 +20,192 @@
|
||||||
|
|
||||||
-module(tango_oid).
|
-module(tango_oid).
|
||||||
|
|
||||||
%% -behaviour(gen_server).
|
-behaviour(gen_server).
|
||||||
|
|
||||||
%% %% API
|
%% API
|
||||||
%% -export([start_link/3, stop/1,
|
-export([start_link/3, stop/1,
|
||||||
%% new/2, get/2]).
|
new/2, get/2]).
|
||||||
|
|
||||||
%% %% gen_server callbacks
|
%% gen_server callbacks
|
||||||
%% -export([init/1, handle_call/3, handle_cast/2, handle_info/2,
|
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
|
||||||
%% terminate/2, code_change/3]).
|
terminate/2, code_change/3]).
|
||||||
|
|
||||||
%% %% Tango datatype callbacks (prototype)
|
%% Tango datatype callbacks (prototype)
|
||||||
%% -export([fresh/0,
|
-export([fresh/0,
|
||||||
%% do_pure_op/2, do_dirty_op/5, play_log_mutate_i_state/3]).
|
do_pure_op/2, do_dirty_op/5, play_log_mutate_i_state/3]).
|
||||||
|
|
||||||
%% -define(SERVER, ?MODULE).
|
-define(SERVER, ?MODULE).
|
||||||
%% -define(OID_STREAM_NUMBER, 0).
|
-define(OID_STREAM_NUMBER, 0).
|
||||||
|
|
||||||
%% -define(LONG_TIME, 30*1000).
|
-define(LONG_TIME, 30*1000).
|
||||||
|
|
||||||
%% -define(D(X), io:format(user, "Dbg: ~s =\n ~p\n", [??X, X])).
|
-define(D(X), io:format(user, "Dbg: ~s =\n ~p\n", [??X, X])).
|
||||||
|
|
||||||
%% -type lpn() :: non_neg_integer().
|
-type lpn() :: non_neg_integer().
|
||||||
|
|
||||||
%% -record(state, {
|
-record(state, {
|
||||||
%% page_size :: non_neg_integer(), % Corfurl page size
|
page_size :: non_neg_integer(), % Corfurl page size
|
||||||
%% seq :: pid(), % sequencer pid
|
seq :: pid(), % sequencer pid
|
||||||
%% proj :: term(), % projection
|
proj :: term(), % projection
|
||||||
%% last_fetch_lpn :: lpn(), %
|
last_fetch_lpn :: lpn(), %
|
||||||
%% all_back_ps :: [lpn()], % All back-pointers LIFO order!
|
all_back_ps :: [lpn()], % All back-pointers LIFO order!
|
||||||
%% i_state :: term() % internal state thingie
|
i_state :: term() % internal state thingie
|
||||||
%% }).
|
}).
|
||||||
|
|
||||||
%% start_link(PageSize, SequencerPid, Proj) ->
|
start_link(PageSize, SequencerPid, Proj) ->
|
||||||
%% gen_server:start_link(?MODULE,
|
gen_server:start_link(?MODULE,
|
||||||
%% [PageSize, SequencerPid, Proj], []).
|
[PageSize, SequencerPid, Proj], []).
|
||||||
|
|
||||||
%% stop(Pid) ->
|
stop(Pid) ->
|
||||||
%% gen_server:call(Pid, {stop}, ?LONG_TIME).
|
gen_server:call(Pid, {stop}, ?LONG_TIME).
|
||||||
|
|
||||||
%% new(Pid, Key) ->
|
new(Pid, Key) ->
|
||||||
%% gen_server:call(Pid, {new, Key}, ?LONG_TIME).
|
gen_server:call(Pid, {new, Key}, ?LONG_TIME).
|
||||||
|
|
||||||
%% get(Pid, Key) ->
|
get(Pid, Key) ->
|
||||||
%% gen_server:call(Pid, {get, Key}, ?LONG_TIME).
|
gen_server:call(Pid, {get, Key}, ?LONG_TIME).
|
||||||
|
|
||||||
%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
|
||||||
%% init([PageSize, SequencerPid, Proj]) ->
|
init([PageSize, SequencerPid, Proj]) ->
|
||||||
%% LastLPN = find_last_lpn(SequencerPid),
|
LastLPN = find_last_lpn(SequencerPid),
|
||||||
%% {LPNs, Pages} = fetch_unread_pages(Proj, LastLPN, 0),
|
{LPNs, Pages} = fetch_unread_pages(Proj, LastLPN, 0),
|
||||||
%% BackPs = lists:reverse(LPNs),
|
BackPs = lists:reverse(LPNs),
|
||||||
%% LastFetchLPN = case LPNs of [] -> 0;
|
LastFetchLPN = back_ps2last_lpn(BackPs),
|
||||||
%% [H|_] -> H
|
I_State = play_log_pages(Pages, fresh(), ?MODULE, false),
|
||||||
%% end,
|
{ok, #state{page_size=PageSize,
|
||||||
%% I_State = play_log_pages(Pages, fresh(), ?MODULE, false),
|
seq=SequencerPid,
|
||||||
%% {ok, #state{page_size=PageSize,
|
proj=Proj,
|
||||||
%% seq=SequencerPid,
|
last_fetch_lpn=LastFetchLPN,
|
||||||
%% proj=Proj,
|
all_back_ps=BackPs,
|
||||||
%% last_fetch_lpn=LastFetchLPN,
|
i_state=I_State}}.
|
||||||
%% all_back_ps=BackPs,
|
|
||||||
%% i_state=I_State}}.
|
|
||||||
|
|
||||||
%% handle_call({new, Key}, From,
|
handle_call({new, Key}, From,
|
||||||
%% #state{proj=Proj0, page_size=PageSize, i_state=I_State}=State) ->
|
#state{proj=Proj0, page_size=PageSize, i_state=I_State}=State) ->
|
||||||
%% Op = {new_oid, Key, From, 0},
|
Op = {new_oid, Key, From, 0},
|
||||||
%% {_Res, I_State2, Proj1, LPN} =
|
{_Res, I_State2, Proj1, _LPN} =
|
||||||
%% do_dirty_op(Op, I_State, ?OID_STREAM_NUMBER, Proj0, PageSize),
|
do_dirty_op(Op, I_State, ?OID_STREAM_NUMBER, Proj0, PageSize),
|
||||||
%% %% Let's see how much trouble we can get outselves in here.
|
%% Let's see how much trouble we can get outselves in here.
|
||||||
%% %% If we're here, then we've written to the log without error.
|
%% If we're here, then we've written to the log without error.
|
||||||
%% %% So then the cast to roll forward must see that log entry
|
%% So then the cast to roll forward must see that log entry
|
||||||
%% %% (if it also operates without error). So, the side-effect of
|
%% (if it also operates without error). So, the side-effect of
|
||||||
%% %% the op ought to always send a reply to the client.
|
%% the op ought to always send a reply to the client.
|
||||||
%% gen_server:cast(self(), {roll_forward}),
|
gen_server:cast(self(), {roll_forward}),
|
||||||
%% {noreply, State#state{i_state=I_State2,
|
{noreply, State#state{i_state=I_State2,
|
||||||
%% proj=Proj1}};
|
proj=Proj1}};
|
||||||
%% handle_call({get, _Key}=Op, _From, State) ->
|
handle_call({get, _Key}=Op, _From, State) ->
|
||||||
%% State2 = #state{i_state=I_State} = roll_log_forward(State),
|
State2 = #state{i_state=I_State} = roll_log_forward(State),
|
||||||
%% Reply = do_pure_op(Op, I_State),
|
Reply = do_pure_op(Op, I_State),
|
||||||
%% {reply, Reply, State2};
|
{reply, Reply, State2};
|
||||||
%% handle_call({stop}, _From, State) ->
|
handle_call({stop}, _From, State) ->
|
||||||
%% {stop, normal, ok, State};
|
{stop, normal, ok, State};
|
||||||
%% handle_call(_Request, _From, State) ->
|
handle_call(_Request, _From, State) ->
|
||||||
%% Reply = whaaaaaaaaaaaa,
|
Reply = whaaaaaaaaaaaa,
|
||||||
%% {reply, Reply, State}.
|
{reply, Reply, State}.
|
||||||
|
|
||||||
%% handle_cast({roll_forward}, State) ->
|
handle_cast({roll_forward}, State) ->
|
||||||
%% State2 = roll_log_forward(State),
|
State2 = roll_log_forward(State),
|
||||||
%% {noreply, State2};
|
{noreply, State2};
|
||||||
%% handle_cast(_Msg, State) ->
|
handle_cast(_Msg, State) ->
|
||||||
%% {noreply, State}.
|
{noreply, State}.
|
||||||
|
|
||||||
%% handle_info(_Info, State) ->
|
handle_info(_Info, State) ->
|
||||||
%% {noreply, State}.
|
{noreply, State}.
|
||||||
|
|
||||||
%% terminate(_Reason, _State) ->
|
terminate(_Reason, _State) ->
|
||||||
%% ok.
|
ok.
|
||||||
|
|
||||||
%% code_change(_OldVsn, State, _Extra) ->
|
code_change(_OldVsn, State, _Extra) ->
|
||||||
%% {ok, State}.
|
{ok, State}.
|
||||||
|
|
||||||
%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
|
||||||
%% find_last_lpn(#state{seq=SequencerPid}) ->
|
back_ps2last_lpn([]) ->
|
||||||
%% find_last_lpn(SequencerPid);
|
0;
|
||||||
%% find_last_lpn(SequencerPid) ->
|
back_ps2last_lpn([H|_]) ->
|
||||||
%% {ok, CurrentLPN} = corfurl_sequencer:get(SequencerPid, 0),
|
H.
|
||||||
%% CurrentLPN - 1.
|
|
||||||
|
find_last_lpn(#state{seq=SequencerPid}) ->
|
||||||
|
find_last_lpn(SequencerPid);
|
||||||
|
find_last_lpn(SequencerPid) ->
|
||||||
|
{ok, _, [BackPs]} = corfurl_sequencer:get_tails(SequencerPid, 0, [?OID_STREAM_NUMBER]),
|
||||||
|
back_ps2last_lpn(BackPs).
|
||||||
|
|
||||||
%% %% AAA refactor: return value changes here, propagate
|
|
||||||
%% fetch_unread_pages(#state{proj=Proj, last_fetch_lpn=StopAtLPN,
|
%% fetch_unread_pages(#state{proj=Proj, last_fetch_lpn=StopAtLPN,
|
||||||
%% all_back_ps=BPs} = State) ->
|
%% all_back_ps=BPs} = State) ->
|
||||||
%% LastLPN = find_last_lpn(State),
|
%% LastLPN = find_last_lpn(State),
|
||||||
%% {LPNs, Pages} = fetch_unread_pages(Proj, LastLPN, StopAtLPN),
|
%% {LPNs, Pages} = fetch_unread_pages(Proj, LastLPN, StopAtLPN),
|
||||||
%% NewBPs = append_lpns(LPNs, BPs),
|
%% NewBPs = append_lpns(LPNs, BPs),
|
||||||
%% {LPNS, Pages, State#state{last_fetch_lpn=LastLPN, back_ps=BackPs}}.
|
%% {LPNs, Pages, State#state{last_fetch_lpn=LastLPN, all_back_ps=NewBPs}}.
|
||||||
|
|
||||||
%% fetch_unread_pages(Proj, LastLPN, StopAtLPN)
|
fetch_unread_pages(Proj, LastLPN, StopAtLPN)
|
||||||
%% when LastLPN >= StopAtLPN ->
|
when LastLPN >= StopAtLPN ->
|
||||||
%% %% ?D({fetch_unread_pages, LastLPN, StopAtLPN}),
|
%% ?D({fetch_unread_pages, LastLPN, StopAtLPN}),
|
||||||
%% LPNandPages = tango:scan_backward(Proj, ?OID_STREAM_NUMBER, LastLPN,
|
LPNandPages = tango:scan_backward(Proj, ?OID_STREAM_NUMBER, LastLPN,
|
||||||
%% StopAtLPN, true),
|
StopAtLPN, true),
|
||||||
%% {_LPNs, _Pages} = lists:unzip(LPNandPages).
|
{_LPNs, _Pages} = lists:unzip(LPNandPages).
|
||||||
|
|
||||||
%% play_log_pages(Pages, SideEffectsP,
|
play_log_pages(Pages, SideEffectsP,
|
||||||
%% #state{i_state=I_State} = State) ->
|
#state{i_state=I_State} = State) ->
|
||||||
%% I_State2 = play_log_pages(Pages, I_State, ?MODULE, SideEffectsP),
|
I_State2 = play_log_pages(Pages, I_State, ?MODULE, SideEffectsP),
|
||||||
%% State#state{i_state=I_State2}.
|
State#state{i_state=I_State2}.
|
||||||
|
|
||||||
%% play_log_pages(Pages, I_State, CallbackMod, SideEffectsP) ->
|
play_log_pages(Pages, I_State, CallbackMod, SideEffectsP) ->
|
||||||
%% CallbackMod:play_log_mutate_i_state(Pages, SideEffectsP, I_State).
|
CallbackMod:play_log_mutate_i_state(Pages, SideEffectsP, I_State).
|
||||||
|
|
||||||
%% roll_log_forward(#state{proj=Proj, all_back_ps=BackPs,
|
roll_log_forward(#state{seq=SequencerPid, proj=Proj, all_back_ps=BackPs,
|
||||||
%% last_fetch_lpn=StopAtLPN} = State) ->
|
last_fetch_lpn=StopAtLPN} = State) ->
|
||||||
%% LastLPN = find_last_lpn(SequencerPid),
|
LastLPN = find_last_lpn(SequencerPid),
|
||||||
%% {LPNs, Pages} = fetch_unread_pages(Proj, LastLPN, StopAtLPN),
|
{LPNs, Pages} = fetch_unread_pages(Proj, LastLPN, StopAtLPN),
|
||||||
%% NewBPs = append_lpns(LPNs, BackPs),
|
NewBPs = append_lpns(LPNs, BackPs),
|
||||||
%% play_log_pages(Pages, true, State2#state{all_back_ps=NewBPs}).
|
play_log_pages(Pages, true, State#state{all_back_ps=NewBPs}).
|
||||||
|
|
||||||
%% append_lpns([], BPs) ->
|
append_lpns([], BPs) ->
|
||||||
%% BPs;
|
BPs;
|
||||||
%% append_lpns(LPNs, BPs) ->
|
append_lpns(LPNs, BPs) ->
|
||||||
%% lists:reverse(LPNs) ++ BPs.
|
lists:reverse(LPNs) ++ BPs.
|
||||||
|
|
||||||
%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
|
||||||
%% -record(oid_map, {
|
-record(oid_map, {
|
||||||
%% next :: non_neg_integer(),
|
next :: non_neg_integer(),
|
||||||
%% map :: dict()
|
map :: dict()
|
||||||
%% }).
|
}).
|
||||||
|
|
||||||
%% -define(DICTMOD, dict).
|
-define(DICTMOD, dict).
|
||||||
|
|
||||||
%% fresh() ->
|
fresh() ->
|
||||||
%% #oid_map{next=1,
|
#oid_map{next=1,
|
||||||
%% map=?DICTMOD:new()}.
|
map=?DICTMOD:new()}.
|
||||||
|
|
||||||
%% do_pure_op({get, Key}, #oid_map{map=Dict}) ->
|
do_pure_op({get, Key}, #oid_map{map=Dict}) ->
|
||||||
%% ?DICTMOD:find(Key, Dict).
|
?DICTMOD:find(Key, Dict).
|
||||||
|
|
||||||
%% do_dirty_op({new_oid, _Key, _From, _NumOfAttempts}=Op,
|
do_dirty_op({new_oid, _Key, _From, _NumOfAttempts}=Op,
|
||||||
%% I_State, StreamNum, Proj0, PageSize) ->
|
I_State, StreamNum, Proj0, ___TODO_delme_PageSize) ->
|
||||||
%% Page = term_to_binary(Op),
|
Page = term_to_binary(Op),
|
||||||
%% FullPage = tango:pack_v1([StreamNum], [to_final_page],
|
{{ok, LPN}, Proj1} = tango:append_page(Proj0, Page, [StreamNum]),
|
||||||
%% Page, PageSize),
|
{ok, I_State, Proj1, LPN}.
|
||||||
%% left off here,
|
|
||||||
%% {{ok, LPN}, Proj1} = tango:append_page(Proj0, Page, [StreamNum]),
|
|
||||||
%% {ok, I_State, Proj1, LPN}.
|
|
||||||
|
|
||||||
%% play_log_mutate_i_state(Pages, SideEffectsP, I_State) ->
|
play_log_mutate_i_state(Pages, SideEffectsP, I_State) ->
|
||||||
%% lists:foldl(fun({new_oid, Key, From, _NumOfAttempts}=_Op,
|
lists:foldl(fun({new_oid, Key, From, _NumOfAttempts}=_Op,
|
||||||
%% #oid_map{map=Dict, next=Next}=O) ->
|
#oid_map{map=Dict, next=Next}=O) ->
|
||||||
%% {Res, O2} =
|
{Res, O2} =
|
||||||
%% case ?DICTMOD:find(Key, Dict) of
|
case ?DICTMOD:find(Key, Dict) of
|
||||||
%% error ->
|
error ->
|
||||||
%% Dict2 = ?DICTMOD:store(Key, Next, Dict),
|
Dict2 = ?DICTMOD:store(Key, Next, Dict),
|
||||||
%% {{ok, Next},O#oid_map{map=Dict2,
|
{{ok, Next},O#oid_map{map=Dict2,
|
||||||
%% next=Next + 1}};
|
next=Next + 1}};
|
||||||
%% {ok, _} ->
|
{ok, _} ->
|
||||||
%% {already_exists, O}
|
{already_exists, O}
|
||||||
%% end,
|
end,
|
||||||
%% if SideEffectsP ->
|
if SideEffectsP ->
|
||||||
%% gen_server:reply(From, Res);
|
gen_server:reply(From, Res);
|
||||||
%% true ->
|
true ->
|
||||||
%% ok
|
ok
|
||||||
%% end,
|
end,
|
||||||
%% O2
|
O2
|
||||||
%% end,
|
end,
|
||||||
%% I_State,
|
I_State,
|
||||||
%% [binary_to_term(Page) || Page <- Pages]).
|
[binary_to_term(Page) || Page <- Pages]).
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue