- simple_cache.app
{application, simple_cache, [ {description, "A simple caching system"}, {vsn, "0.1.0"}, {modules, [ sc_app, sc_sup]}, {registered, [sc_sup]}, {applications, [kernel, stdlib]}, {mod, {sc_app, []}} ] }.
- sc_app.erl
-module(sc_app). -behaviour(application). %% API -export([ start/2, stop/1]). start(_Type, _StartArgs) -> sc_store:init(), case sc_sup:start_link() of {ok, Pid} -> {ok, Pid}; Other -> {error, Other} end. stop(_State) -> ok.
- sc_sup.erl
-module(sc_sup). -behaviour(supervisor). %% API -export([start_link/0, start_child/2]). -export([init/1]). -define(SERVER, ?MODULE). start_link() -> supervisor:start_link({local, ?SERVER}, ?MODULE, []). start_child(Value, LeaseTime) -> supervisor:start_child(?SERVER, [Value, LeaseTime]). init([]) -> Element = {sc_element, {sc_element, start_link, []}, temporary, brutal_kill, worker, [sc_element]}, Children = [Element], RestartStrategy = {simple_one_for_one, 0, 1}, {ok, {RestartStrategy, Children}}.
- sc_element.erl
-module(sc_element). -behaviour(gen_server). %% API -export([ start_link/2, create/2, create/1, fetch/1, replace/2, delete/1 ]). -export([ init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3 ]). -define(SERVER, ?MODULE). -define(DEFAULT_LEASE_TIME, (60 * 60 * 24)). -record(state, {value, lease_time, start_time}). start_link(Value, LeaseTime) -> gen_server:start_link(?MODULE, [Value, LeaseTime], []). create(Value, LeaseTime) -> sc_sup:start_child(Value, LeaseTime). create(Value) -> sc_sup:start_child(Value, ?DEFAULT_LEASE_TIME). fetch(Pid) -> gen_server:call(Pid, fetch). replace(Pid, Value) -> gen_server:cast(Pid, {replace, Value}). delete(Pid) -> gen_server:cast(Pid, delete). init([Value, LeaseTime]) -> Now = calendar:local_time(), StartTime = calendar:datetime_to_gregorian_seconds(Now), {ok, #state{value = Value, lease_time = LeaseTime, start_time = StartTime}, time_left(StartTime, LeaseTime)}. time_left(_StartTime, infinity) -> infinity; time_left(StartTime, LeaseTime) -> Now = calendar:local_time(), CurrentTime = calendar:datetime_to_gregorian_seconds(Now), TimeElapsed = CurrentTime - StartTime, case LeaseTime - TimeElapsed of Time when Time =< 0 -> 0; Time -> Time * 1000 end. handle_call(fetch, _From, State) -> #state{value = Value, lease_time = LeaseTime, start_time = StartTime} = State, TimeLeft = time_left(StartTime, LeaseTime), {reply, {ok, Value}, State, TimeLeft}. handle_cast({replace, Value}, State) -> #state{lease_time = LeaseTime, start_time = StartTime} = State, TimeLeft = time_left(StartTime, LeaseTime), {noreply, State#state{value = Value}, TimeLeft}; handle_cast(delete, State) -> {stop, normal, State}. handle_info(timeout, State) -> {stop, normal, State}. terminate(_Reason, _State) -> sc_store:delete(self()), ok. code_change(_OldVsn, State, _Extra) -> {ok, State}. %% 一旦用上服务器超时,切记在每个回调函数的每个子句中都设置好超时。
- sc_store.erl
-module(sc_store). %% API -export([init/0, insert/2, delete/1, lookup/1]). -define(TABLE_ID, ?MODULE). init() -> ets:new(?TABLE_ID, [public, named_table]), ok. insert(Key, Pid) -> ets:insert(?TABLE_ID, {Key, Pid}). lookup(Key) -> case ets:lookup(?TABLE_ID, Key) of [{Key, Pid}] -> {ok, Pid}; [] -> {error, not_found} end. delete(Pid) -> ets:match_delete(?TABLE_ID, {'_', Pid}).
- simple_cache.erl
-module(simple_cache). %% API -export([insert/2, lookup/1, delete/1]). insert(Key, Value) -> case sc_store:lookup(Key) of {ok, Pid} -> sc_element:replace(Pid, Value); {error, _} -> {ok, Pid} = sc_element:create(Value), sc_store:insert(Key, Pid) end. lookup(Key) -> try {ok, Pid} = sc_store:lookup(Key), {ok, Value} = sc_element:fetch(Pid), {ok, Value} catch _Class:_Exception -> {error, not_found} end. delete(Key) -> case sc_store:lookup(Key) of {ok, Pid} -> sc_element:delete(Pid); {error, _Reason} -> ok end.
《Erlang/OTP并发编程实战》第六章 打造一套缓存系统
猜你喜欢
转载自blog.csdn.net/sanmao123456_/article/details/103447844
今日推荐
周排行