From 6184272d959e2633e361dbc3c53cb95715e035bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20S=C3=B8e=20S=C3=B8rensen?= Date: Thu, 5 Jan 2012 15:34:50 +0100 Subject: [PATCH 1/7] Remove unused level:size(). --- src/fractal_btree_level.erl | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/fractal_btree_level.erl b/src/fractal_btree_level.erl index a024fff..7c14370 100644 --- a/src/fractal_btree_level.erl +++ b/src/fractal_btree_level.erl @@ -333,6 +333,3 @@ close_a_and_b(State) -> filename(PFX, State) -> filename:join(State#state.dir, PFX ++ "-" ++ integer_to_list(State#state.level) ++ ".data"). -size(State) -> - (1 bsl State#state.level). - From 285b7bc95e536925e5a509ccfcb4a4a441ba8caf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20S=C3=B8e=20S=C3=B8rensen?= Date: Thu, 5 Jan 2012 15:35:16 +0100 Subject: [PATCH 2/7] Rename main_loop{0,1,2}() to main_loop(). --- src/fractal_btree_level.erl | 60 ++++++++++++++++++------------------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/src/fractal_btree_level.erl b/src/fractal_btree_level.erl index 7c14370..ec0b21f 100644 --- a/src/fractal_btree_level.erl +++ b/src/fractal_btree_level.erl @@ -95,7 +95,7 @@ initialize(State) -> ok = file:rename(CFileName, AFileName), {ok, BT} = fractal_btree_reader:open(CFileName), - main_loop1(State#state{ a= BT, b=undefined }); + main_loop(State#state{ a= BT, b=undefined }); {error, enoent} -> case file:read_file_info(BFileName) of @@ -105,63 +105,63 @@ initialize(State) -> {ok, MergePID} = begin_merge(State), - main_loop2(State#state{ a=BT1, b=BT2, merge_pid=MergePID }); + main_loop(State#state{ a=BT1, b=BT2, merge_pid=MergePID }); {error, enoent} -> case file:read_file_info(AFileName) of {ok, _} -> {ok, BT1} = fractal_btree_reader:open(AFileName), - main_loop1(State#state{ a=BT1 }); + main_loop(State#state{ a=BT1 }); {error, enoent} -> - main_loop0(State) + main_loop(State) end end end. -main_loop0(State = #state{ a=undefined, b=undefined }) -> +main_loop(State = #state{ a=undefined, b=undefined }) -> Parent = plain_fsm:info(parent), - error_logger:info_msg("in main_loop0~n", []), + error_logger:info_msg("in main_loop~n", []), receive ?REQ(From, {lookup, _})=Msg -> - error_logger:info_msg("in main_loop0, msg=~p~n", [Msg]), + error_logger:info_msg("in main_loop, msg=~p~n", [Msg]), case State#state.next of undefined -> reply(From, notfound); Next -> Next ! Msg end, - main_loop0(State); + main_loop(State); ?REQ(From, {inject, FileName})=_Msg -> - error_logger:info_msg("in main_loop0, msg=~p~n", [_Msg]), + error_logger:info_msg("in main_loop, msg=~p~n", [_Msg]), AFileName = filename("A",State), ok = file:rename(FileName, AFileName), {ok, BT} = fractal_btree_reader:open(AFileName), reply(From, ok), - main_loop1(State#state{ a=BT }); + main_loop(State#state{ a=BT }); ?REQ(From, close)=_Msg -> - error_logger:info_msg("in main_loop0, msg=~p~n", [_Msg]), + error_logger:info_msg("in main_loop, msg=~p~n", [_Msg]), reply(From, ok), ok; %% gen_fsm handling {system, From, Req}=_Msg -> - error_logger:info_msg("in main_loop0, msg=~p~n", [_Msg]), + error_logger:info_msg("in main_loop, msg=~p~n", [_Msg]), plain_fsm:handle_system_msg( - From, Req, State, fun(S1) -> main_loop0(S1) end); + From, Req, State, fun(S1) -> main_loop(S1) end); {'EXIT', Parent, Reason}=_Msg -> - error_logger:info_msg("in main_loop0, msg=~p~n", [_Msg]), + error_logger:info_msg("in main_loop, msg=~p~n", [_Msg]), plain_fsm:parent_EXIT(Reason, State) - end. + end; -main_loop1(State = #state{ a=BT1, b=undefined, next=Next }) -> +main_loop(State = #state{ a=BT1, b=undefined, next=Next }) -> Parent = plain_fsm:info(parent), - error_logger:info_msg("in main_loop1~n", []), + error_logger:info_msg("in main_loop~n", []), receive ?REQ(From, {lookup, Key})=Req -> case fractal_btree_reader:lookup(BT1, Key) of @@ -174,7 +174,7 @@ main_loop1(State = #state{ a=BT1, b=undefined, next=Next }) -> notfound -> Next ! Req end, - main_loop1(State); + main_loop(State); ?REQ(From, {inject, FileName}) -> BFileName = filename("B",State), @@ -182,7 +182,7 @@ main_loop1(State = #state{ a=BT1, b=undefined, next=Next }) -> {ok, BT2} = fractal_btree_reader:open(BFileName), reply(From, ok), {ok, MergePID} = begin_merge(State), - main_loop2(State#state{ b=BT2, merge_pid=MergePID }); + main_loop(State#state{ b=BT2, merge_pid=MergePID }); ?REQ(From, close) -> fractal_btree_reader:close(BT1), @@ -192,23 +192,23 @@ main_loop1(State = #state{ a=BT1, b=undefined, next=Next }) -> %% gen_fsm handling {system, From, Req} -> plain_fsm:handle_system_msg( - From, Req, State, fun(S1) -> main_loop1(S1) end); + From, Req, State, fun(S1) -> main_loop(S1) end); {'EXIT', Parent, Reason} -> plain_fsm:parent_EXIT(Reason, State) - end. + end; -main_loop2(State = #state{ next=Next }) -> +main_loop(State = #state{ next=Next }) -> Parent = plain_fsm:info(parent), - error_logger:info_msg("in main_loop2~n", []), + error_logger:info_msg("in main_loop~n", []), receive ?REQ(From, {lookup, Key})=Req -> case fractal_btree_reader:lookup(State#state.b, Key) of {ok, deleted} -> reply(From, notfound), - main_loop2(State); + main_loop(State); {ok, _}=Reply -> reply(From, Reply), - main_loop2(State); + main_loop(State); _ -> case fractal_btree_reader:lookup(State#state.a, Key) of {ok, deleted} -> @@ -220,7 +220,7 @@ main_loop2(State = #state{ next=Next }) -> notfound -> Next ! Req end, - main_loop2(State) + main_loop(State) end; @@ -255,7 +255,7 @@ main_loop2(State = #state{ next=Next }) -> ok = file:rename(CFileName, AFileName), {ok, BT} = fractal_btree_reader:open(AFileName), - main_loop1(State2#state{ a=BT, b=undefined, merge_pid=undefined }); + main_loop(State2#state{ a=BT, b=undefined, merge_pid=undefined }); %% %% We need to push the output of merging to the next level @@ -270,7 +270,7 @@ main_loop2(State = #state{ next=Next }) -> end, MRef = send_request(State1#state.next, {inject, OutFileName}), - main_loop2(State1#state{ inject_done_ref = MRef, merge_pid=undefined }); + main_loop(State1#state{ inject_done_ref = MRef, merge_pid=undefined }); %% %% Our successor accepted the inject @@ -278,7 +278,7 @@ main_loop2(State = #state{ next=Next }) -> ?REPLY(MRef, ok) when MRef =:= State#state.inject_done_ref -> erlang:demonitor(MRef, [flush]), {ok, State2} = close_a_and_b(State), - main_loop0(State2#state{ inject_done_ref=undefined }); + main_loop(State2#state{ inject_done_ref=undefined }); %% %% Our successor died! @@ -289,7 +289,7 @@ main_loop2(State = #state{ next=Next }) -> %% gen_fsm handling {system, From, Req} -> plain_fsm:handle_system_msg( - From, Req, State, fun(S1) -> main_loop2(S1) end); + From, Req, State, fun(S1) -> main_loop(S1) end); {'EXIT', Parent, Reason} -> plain_fsm:parent_EXIT(Reason, State) From 76c6cbd58501549c8bcab748318c0f201b6933ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20S=C3=B8e=20S=C3=B8rensen?= Date: Thu, 5 Jan 2012 15:46:13 +0100 Subject: [PATCH 3/7] Simplify lookup in main_loop2(). --- src/fractal_btree_level.erl | 43 ++++++++++++++++++------------------- 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/src/fractal_btree_level.erl b/src/fractal_btree_level.erl index ec0b21f..ea480ad 100644 --- a/src/fractal_btree_level.erl +++ b/src/fractal_btree_level.erl @@ -202,27 +202,15 @@ main_loop(State = #state{ next=Next }) -> error_logger:info_msg("in main_loop~n", []), receive ?REQ(From, {lookup, Key})=Req -> - case fractal_btree_reader:lookup(State#state.b, Key) of - {ok, deleted} -> - reply(From, notfound), - main_loop(State); - {ok, _}=Reply -> - reply(From, Reply), - main_loop(State); - _ -> - case fractal_btree_reader:lookup(State#state.a, Key) of - {ok, deleted} -> - reply(From, notfound); - {ok, _}=Reply -> - reply(From, Reply); - notfound when Next =:= undefined -> - reply(From, notfound); - notfound -> - Next ! Req - end, - main_loop(State) - end; - + case do_lookup(Key, [State#state.b, State#state.b, Next]) of + notfound -> + reply(From, notfound); + {found, Result} -> + reply(From, {ok, Result}); + {delegate, DelegatePid} -> + DelegatePid ! Req + end, + main_loop(State); ?REQ(From, close) -> fractal_btree_reader:close(State#state.a), @@ -295,7 +283,18 @@ main_loop(State = #state{ next=Next }) -> end. - +do_lookup(_Key, []) -> + notfound; +do_lookup(_Key, [Pid]) when is_pid(Pid) -> + {delegate, Pid}; +do_lookup(Key, [undefined|Rest]) -> + do_lookup(Key, Rest); +do_lookup(Key, [BT|Rest]) -> + case fractal_btree_reader:lookup(BT, Key) of + {ok, deleted} -> notfound; + {ok, Result} -> {found, Result}; + notfound -> do_lookup(Key, Rest) + end. begin_merge(State) -> AFileName = filename("A",State), From c93505fa58a97bb74fcd5bdd9672b3125cf3caa7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20S=C3=B8e=20S=C3=B8rensen?= Date: Thu, 5 Jan 2012 15:59:45 +0100 Subject: [PATCH 4/7] Simplify main_loop() by collapsing to one clause. --- src/fractal_btree_level.erl | 115 +++++++++--------------------------- 1 file changed, 29 insertions(+), 86 deletions(-) diff --git a/src/fractal_btree_level.erl b/src/fractal_btree_level.erl index ea480ad..4d861ad 100644 --- a/src/fractal_btree_level.erl +++ b/src/fractal_btree_level.erl @@ -81,7 +81,6 @@ reply({PID,Ref}, Reply) -> initialize(State) -> error_logger:info_msg("in ~p level=~p~n", [self(), State]), - AFileName = filename("A",State), BFileName = filename("B",State), CFileName = filename("C",State), @@ -120,82 +119,12 @@ initialize(State) -> end end. - -main_loop(State = #state{ a=undefined, b=undefined }) -> - Parent = plain_fsm:info(parent), - error_logger:info_msg("in main_loop~n", []), - receive - ?REQ(From, {lookup, _})=Msg -> - error_logger:info_msg("in main_loop, msg=~p~n", [Msg]), - case State#state.next of - undefined -> - reply(From, notfound); - Next -> - Next ! Msg - end, - main_loop(State); - - ?REQ(From, {inject, FileName})=_Msg -> - error_logger:info_msg("in main_loop, msg=~p~n", [_Msg]), - AFileName = filename("A",State), - ok = file:rename(FileName, AFileName), - {ok, BT} = fractal_btree_reader:open(AFileName), - reply(From, ok), - main_loop(State#state{ a=BT }); - - ?REQ(From, close)=_Msg -> - error_logger:info_msg("in main_loop, msg=~p~n", [_Msg]), - reply(From, ok), - ok; - - %% gen_fsm handling - {system, From, Req}=_Msg -> - error_logger:info_msg("in main_loop, msg=~p~n", [_Msg]), - plain_fsm:handle_system_msg( - From, Req, State, fun(S1) -> main_loop(S1) end); - - {'EXIT', Parent, Reason}=_Msg -> - error_logger:info_msg("in main_loop, msg=~p~n", [_Msg]), - plain_fsm:parent_EXIT(Reason, State) - end; - -main_loop(State = #state{ a=BT1, b=undefined, next=Next }) -> - Parent = plain_fsm:info(parent), - error_logger:info_msg("in main_loop~n", []), - receive - ?REQ(From, {lookup, Key})=Req -> - case fractal_btree_reader:lookup(BT1, Key) of - {ok, deleted} -> - reply(From, notfound); - {ok, _}=Reply -> - reply(From, Reply); - notfound when Next =:= undefined -> - reply(From, notfound); - notfound -> - Next ! Req - end, - main_loop(State); - - ?REQ(From, {inject, FileName}) -> - BFileName = filename("B",State), - ok = file:rename(FileName, BFileName), - {ok, BT2} = fractal_btree_reader:open(BFileName), - reply(From, ok), - {ok, MergePID} = begin_merge(State), - main_loop(State#state{ b=BT2, merge_pid=MergePID }); - - ?REQ(From, close) -> - fractal_btree_reader:close(BT1), - reply(From, ok), - ok; - - %% gen_fsm handling - {system, From, Req} -> - plain_fsm:handle_system_msg( - From, Req, State, fun(S1) -> main_loop(S1) end); - {'EXIT', Parent, Reason} -> - plain_fsm:parent_EXIT(Reason, State) - end; +check_begin_merge_then_loop(State=#state{a=BT1, b=BT2, merge_pid=undefined}) + when BT1/=undefined, BT2 /= undefined -> + {ok, MergePID} = begin_merge(State), + main_loop(State#state{merge_pid=MergePID }); +check_begin_merge_then_loop(State) -> + main_loop(State). main_loop(State = #state{ next=Next }) -> Parent = plain_fsm:info(parent), @@ -212,16 +141,23 @@ main_loop(State = #state{ next=Next }) -> end, main_loop(State); + ?REQ(From, {inject, FileName}) when State#state.b == undefined -> + if State#state.a == undefined -> + ToFileName = filename("A",State), + SetPos = #state.a; + true -> + ToFileName = filename("B",State), + SetPos = #state.b + end, + ok = file:rename(FileName, ToFileName), + {ok, BT} = fractal_btree_reader:open(ToFileName), + reply(From, ok), + check_begin_merge_then_loop(setelement(SetPos, State, BT)); + ?REQ(From, close) -> - fractal_btree_reader:close(State#state.a), - fractal_btree_reader:close(State#state.b), - MergePID = State#state.merge_pid, - if MergePID =:= undefined -> - ok; - true -> - erlang:exit(State#state.merge_pid, shutdown) - end, - %% TODO: stop merger, if any? + close_if_defined(State#state.a), + close_if_defined(State#state.b), + stop_if_defined(State#state.merge_pid), reply(From, ok), ok; @@ -296,6 +232,13 @@ do_lookup(Key, [BT|Rest]) -> notfound -> do_lookup(Key, Rest) end. +close_if_defined(undefined) -> ok; +close_if_defined(BT) -> fractal_btree_reader:close(BT). + +stop_if_defined(undefined) -> ok; +stop_if_defined(MergePid=) when is_pid(MergePid) -> + erlang:exit(MergePid, shutdown). + begin_merge(State) -> AFileName = filename("A",State), BFileName = filename("B",State), From fa43e41c519235aadf91f9d27c03e0754fe524a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20S=C3=B8e=20S=C3=B8rensen?= Date: Thu, 5 Jan 2012 16:01:14 +0100 Subject: [PATCH 5/7] Simplify slightly in level:initialize(). --- src/fractal_btree_level.erl | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/fractal_btree_level.erl b/src/fractal_btree_level.erl index 4d861ad..062bf39 100644 --- a/src/fractal_btree_level.erl +++ b/src/fractal_btree_level.erl @@ -102,9 +102,7 @@ initialize(State) -> {ok, BT1} = fractal_btree_reader:open(AFileName), {ok, BT2} = fractal_btree_reader:open(BFileName), - {ok, MergePID} = begin_merge(State), - - main_loop(State#state{ a=BT1, b=BT2, merge_pid=MergePID }); + check_begin_merge_then_loop(State#state{ a=BT1, b=BT2, merge_pid=MergePID }); {error, enoent} -> From c04c11c67fffbf3bbcd34a914d2dae350f134273 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20S=C3=B8e=20S=C3=B8rensen?= Date: Thu, 5 Jan 2012 16:02:29 +0100 Subject: [PATCH 6/7] First compile and test, then commit. --- src/fractal_btree_level.erl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/fractal_btree_level.erl b/src/fractal_btree_level.erl index 062bf39..6054835 100644 --- a/src/fractal_btree_level.erl +++ b/src/fractal_btree_level.erl @@ -102,7 +102,7 @@ initialize(State) -> {ok, BT1} = fractal_btree_reader:open(AFileName), {ok, BT2} = fractal_btree_reader:open(BFileName), - check_begin_merge_then_loop(State#state{ a=BT1, b=BT2, merge_pid=MergePID }); + check_begin_merge_then_loop(State#state{ a=BT1, b=BT2 }); {error, enoent} -> @@ -234,7 +234,7 @@ close_if_defined(undefined) -> ok; close_if_defined(BT) -> fractal_btree_reader:close(BT). stop_if_defined(undefined) -> ok; -stop_if_defined(MergePid=) when is_pid(MergePid) -> +stop_if_defined(MergePid) when is_pid(MergePid) -> erlang:exit(MergePid, shutdown). begin_merge(State) -> From b9abf21bacd0ff60c1b002a0b7a1406ec1c89425 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20S=C3=B8e=20S=C3=B8rensen?= Date: Thu, 5 Jan 2012 16:23:21 +0100 Subject: [PATCH 7/7] Correct embarrasing typo wrt. use of do_lookup(). --- src/fractal_btree_level.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fractal_btree_level.erl b/src/fractal_btree_level.erl index 4c07fb7..6035716 100644 --- a/src/fractal_btree_level.erl +++ b/src/fractal_btree_level.erl @@ -128,7 +128,7 @@ main_loop(State = #state{ next=Next }) -> Parent = plain_fsm:info(parent), receive ?REQ(From, {lookup, Key})=Req -> - case do_lookup(Key, [State#state.b, State#state.b, Next]) of + case do_lookup(Key, [State#state.b, State#state.a, Next]) of notfound -> reply(From, notfound); {found, Result} ->