diff options
-rw-r--r-- | src/mem3.erl | 52 | ||||
-rw-r--r-- | test/mem3_test.erl | 12 |
2 files changed, 45 insertions, 19 deletions
diff --git a/src/mem3.erl b/src/mem3.erl index 1018af29..b59a1d60 100644 --- a/src/mem3.erl +++ b/src/mem3.erl @@ -1,4 +1,18 @@ - +%%% membership module +%%% +%%% State of the gen_server is a #mem record +%%% +%%% Nodes and Gossip are the same thing, and are a list of three-tuples like: +%%% +%%% [ {Pos,NodeName,Options} | _ ] +%%% +%%% Position is 1-based incrementing in order of node joining +%%% +%%% Options is a proplist, with [{hints, [Part1|_]}] denoting that the node +%%% is responsible for the extra partitions too. +%%% +%%% TODO: dialyzer type specs +%%% -module(mem3). -author('brad@cloudant.com'). @@ -57,10 +71,7 @@ state() -> init(Args) -> process_flag(trap_exit,true), Config = configuration:get_config(), - OldState = case Args of - test -> nil; - _ -> read_latest_state_file(Config) - end, + OldState = read_latest_state_file(Args, Config), State = handle_init(OldState), {ok, State#mem{test=(Args == test)}}. @@ -69,8 +80,8 @@ init(Args) -> %% new node joining to this node handle_call({join, JoinType, ExtNodes}, _From, State) -> Config = configuration:get_config(), - Reply = handle_join(JoinType, ExtNodes, State, Config), - {reply, Reply, State}; + NewState = handle_join(JoinType, ExtNodes, State, Config), + {reply, ok, NewState}; %% clock handle_call(clock, _From, State = #mem{clock=Clock}) -> @@ -142,23 +153,26 @@ handle_init(nil) -> net_kernel:monitor_nodes(true), Table = init_ets_table(), Node = node(), - Nodes = [{Node, []}], + Nodes = [{0, Node, []}], Clock = vector_clock:create(Node), #mem{node=Node, nodes=Nodes, clock=Clock, ets=Table}; handle_init(_OldState) -> ?debugHere, % there's an old state, let's try to rejoin automatically + % but only if we can compare our old state to all other + % available nodes and get a match... otherwise get a human involved % TODO implement me Table = init_ets_table(), #mem{ets=Table}. -%% handle join activities -handle_join(first, ExtNodes, State, Config) -> +%% handle join activities, return NewState +handle_join(first, ExtNodes, #mem{node=Node, clock=Clock} = State, Config) -> Map = create_map(Config, ExtNodes), ?debugFmt("~nmap: ~p~n", [Map]), - State#mem{}; + NewClock = vector_clock:increment(Node, Clock), + State#mem{nodes=ExtNodes, clock=NewClock}; handle_join(new, _ExtNodes, _State, _Config) -> ok; @@ -190,7 +204,9 @@ find_latest_state_filename(Config) -> end. -read_latest_state_file(Config) -> +read_latest_state_file(test, _) -> + nil; +read_latest_state_file(_, Config) -> try {ok, File} = find_latest_state_filename(Config), case file:consult(File) of @@ -206,10 +222,14 @@ read_latest_state_file(Config) -> %% @doc given Config and a list of Nodes, construct a Fullmap create_map(#config{q=Q}, Nodes) -> - [{FirstNode,_}|_] = Nodes, - Pmap = lists:foldl(fun({Node, Hints}, Map) -> - partitions:join(Node, Map, Hints) - end, partitions:create(Q, FirstNode), Nodes), + [{_,FirstNode,_}|_] = Nodes, + Fun = fun({_Pos, Node, Options}, Map) -> + Hints = proplists:get_value(hints, Options), + {ok, NewMap} = partitions:join(Node, Map, Hints), + NewMap + end, + Acc0 = partitions:create_partitions(Q, FirstNode), + Pmap = lists:foldl(Fun, Acc0, lists:keysort(1, Nodes)), make_fullmap(Pmap). diff --git a/test/mem3_test.erl b/test/mem3_test.erl index 6286936e..ae6dcaa5 100644 --- a/test/mem3_test.erl +++ b/test/mem3_test.erl @@ -14,7 +14,8 @@ all_tests_test_() -> fun(Pid) -> {with, Pid, [ - fun init/1 + fun init/1, + fun join_first/1 ]} end} ] @@ -33,6 +34,11 @@ test_teardown(Pid) -> %% TESTS init(_Pid) -> - State = #mem{test=Test} = mem3:state(), - ?debugFmt("~nState: ~p~n", [State]), + #mem{test=Test} = mem3:state(), ?assertEqual(true, Test). + + +join_first(_Pid) -> + mem3:join(first, [{1, a, []}, {2, b, []}]), + ?debugFmt("~nState: ~p~n", [mem3:state()]), + ok. |