diff --git a/apps/kv/src/kv_sup.erl b/apps/kv/src/kv_sup.erl index 86f36b2..8d0b271 100644 --- a/apps/kv/src/kv_sup.erl +++ b/apps/kv/src/kv_sup.erl @@ -20,7 +20,10 @@ init([]) -> intensity => 0, period => 1 }, - ChildSpecs = [], + ChildSpecs = [ + #{id => vnode_manager, start => {kv_vnode_manager, start_link, []}, type => worker}, + #{id => vnode_sup, start => {kv_vnode_sup, start_link, []}, type => supervisor} + ], {ok, {SupFlags, ChildSpecs}}. %%% internal functions diff --git a/apps/kv/src/kv_vnode.erl b/apps/kv/src/kv_vnode.erl new file mode 100644 index 0000000..8a83303 --- /dev/null +++ b/apps/kv/src/kv_vnode.erl @@ -0,0 +1,58 @@ +-module(kv_vnode). +-moduledoc """ +Holds data for a single partition in the ring. +""". + +-behaviour(gen_server). + +-export([ + start_link/1, + get/2, + put/3 +]). + +%%% gen_server callbacks +-export([ + init/1, + handle_call/3, + handle_cast/2 +]). + +-record(kv_vnode, { + index :: non_neg_integer(), + table :: ets:table() +}). + +-type state() :: #kv_vnode{}. + +%%% public api + +-spec start_link(Index :: non_neg_integer()) -> gen_server:start_ret(). +start_link(Index) -> + gen_server:start_link(?MODULE, [Index], []). + +-spec get(VNode :: gen_server:server_ref(), Key :: term()) -> {ok, Value :: term()} | none. +get(VNode, Key) -> + gen_server:call(VNode, {get, Key}). + +-spec put(VNode :: gen_server:server_ref(), Key :: term(), Value :: term()) -> ok. +put(VNode, Key, Value) -> + gen_server:cast(VNode, {put, Key, Value}). + +%%% gen_server callbacks + +-spec init([Index :: non_neg_integer()]) -> {ok, state()}. +init([Index]) -> + {ok, #kv_vnode{index = Index, table = ets:new(?MODULE, [set, private])}}. + +handle_call({get, Key}, _From, #kv_vnode{table = Table} = State) -> + Reply = + case ets:lookup(Table, Key) of + [{_, Value}] -> {ok, Value}; + [] -> none + end, + {reply, Reply, State}. + +handle_cast({put, Key, Value}, #kv_vnode{table = Table} = State) -> + ets:insert(Table, {Key, Value}), + {noreply, State}. diff --git a/apps/kv/src/kv_vnode_manager.erl b/apps/kv/src/kv_vnode_manager.erl new file mode 100644 index 0000000..1c6c847 --- /dev/null +++ b/apps/kv/src/kv_vnode_manager.erl @@ -0,0 +1,44 @@ +-module(kv_vnode_manager). + +-behaviour(gen_server). + +-export([ + start_link/0, + get_vnode/1 +]). + +%%% gen_server callbacks +-export([init/1, handle_call/3, handle_cast/2]). + +-record(kv_vnode_manager, {table :: ets:table()}). + +-type state() :: #kv_vnode_manager{}. + +%%% public api + +start_link() -> + gen_server:start_link({local, ?MODULE}, ?MODULE, [], []). + +get_vnode(Index) -> + gen_server:call(?MODULE, {get_vnode, Index}). + +%%% gen_server callbacks + +-spec init([]) -> {ok, state()}. +init([]) -> + {ok, #kv_vnode_manager{table = ets:new(?MODULE, [set])}}. + +handle_call({get_vnode, Index}, _From, State) -> + Table = State#kv_vnode_manager.table, + Reply = + case ets:lookup(Table, Index) of + [{_, Pid}] -> + {ok, Pid}; + [] -> + {ok, Pid} = kv_vnode_sup:start_vnode(Index), + ets:insert(Table, {Index, Pid}), + {ok, Pid} + end, + {reply, Reply, State}. + +handle_cast(_, _) -> error(not_implemented). diff --git a/apps/kv/src/kv_vnode_sup.erl b/apps/kv/src/kv_vnode_sup.erl new file mode 100644 index 0000000..431e3d8 --- /dev/null +++ b/apps/kv/src/kv_vnode_sup.erl @@ -0,0 +1,35 @@ +-module(kv_vnode_sup). + +-behaviour(supervisor). + +-export([start_link/0, start_vnode/1]). + +%%% supervisor callbacks +-export([init/1]). + +%%% public api + +start_link() -> + supervisor:start_link({local, ?MODULE}, ?MODULE, []). + +-spec start_vnode(Index :: non_neg_integer()) -> supervisor:startchild_ret(). +start_vnode(Index) -> + supervisor:start_child(?MODULE, [Index]). + +%%% supervisor callbacks + +init([]) -> + SupFlags = #{ + strategy => simple_one_for_one, + intensity => 0, + period => 1 + }, + ChildSpec = #{ + id => undefined, + start => {kv_vnode, start_link, []}, + restart => temporary, + type => worker + }, + {ok, {SupFlags, [ChildSpec]}}. + +%%% internal functions diff --git a/rebar.lock b/rebar.lock new file mode 100644 index 0000000..57afcca --- /dev/null +++ b/rebar.lock @@ -0,0 +1 @@ +[].