Erlang/OTP并发编程实例(二)
来源:互联网 发布:ubuntu 16.04应用商店 编辑:程序博客网 时间:2024/04/30 02:34
第七章 添加了自定义消息流的简单缓存系统
simple_cache.app应用系统元数据
{application, simple_cache,[{description, "A simple cacheing system"},{vsn, "0.1.0"},{modules, [sc_app,sc_sup,sc_element_sup,sc_element,sc_store,sc_event,sc_event_logger,simple_cache]}, %% 此处也可以写少于实际的模块名{registered, [sc_sup, sc_element_sup, sc_event]},%% 感觉此处可以随便写,不影响运行和结果{applications, [kernel, stdlib, sasl]},{mod, {sc_app, []}}]}.
sc_app.erl
-module(sc_app).-behaviour(application).%% ====================================================================%% API functions%% ====================================================================-export([start/2, stop/1]).%% ====================================================================%% Internal functions%% ====================================================================start(_startType, _startArgs) ->sc_store:init(),case sc_sup:start_link() of%% 启动顶层监督者进程{ok, Pid} ->sc_event_logger:add_handler(),%% 添加自定义事件处理器{ok, Pid};Other ->{error, Other}end.stop(_State) ->ok.
sc_element.erl
-module(sc_element).%% ====================================================================%% API functions%% ====================================================================-behaviour(gen_server).-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]).-export([start_link/2, create/1, create/2, fetch/1, replace/2, delete/1]).-define(DEF_LEASE_TIME, 60).-record(proState, {value, lease_time, start_time}).%% ====================================================================%% Internal functions%% ====================================================================start_link(Value, LeaseTime) ->gen_server:start_link(?MODULE, [Value, LeaseTime], []).%% ????????create(Value) ->create(Value, ?DEF_LEASE_TIME).create(Value, LeaseTime) ->sc_element_sup:start_child(Value, LeaseTime).%% 注意此处修改为sc_element_supfetch(Pid) ->gen_server:call(Pid, fetch).replace(Pid, Value) ->gen_server:cast(Pid, {replace, Value}).delete(Pid) ->gen_server:cast(Pid, delete).%% ====================================================================%% Extra functions %% ====================================================================%% 判断距离超时还有多少毫秒time_left(_Time, infinity) ->infinity;time_left(StartTime, LeaseTime) ->Now = calendar:local_time(),CurTime = calendar:datetime_to_gregorian_seconds(Now),TimeElapsed = CurTime - StartTime,case LeaseTime - TimeElapsed ofTime when Time =< 0 ->0;Time ->Time * 1000end.%% ====================================================================%% Behavioural functions %% ====================================================================init([Value, LeaseTime]) ->Now = calendar:local_time(),StartTime = calendar:datetime_to_gregorian_seconds(Now),TimeLeft = time_left(StartTime, LeaseTime),{ok, #proState{value = Value, lease_time = LeaseTime, start_time = StartTime}, TimeLeft}.handle_call(fetch, _From, State) ->#proState{value = Value, lease_time = LeaseTime, start_time = StartTime} = State,TimeLeft = time_left(StartTime, LeaseTime),{reply, {ok, Value}, State, TimeLeft}.handle_cast({replace, Value}, State) ->#proState{lease_time = LeaseTime, start_time = StartTime} = State,TimeLeft = time_left(StartTime, LeaseTime),{noreply, State#proState{value = Value}, TimeLeft};handle_cast(delete, State) ->{stop, normal, State}.handle_info(timeout, State) ->{stop, normal, State}.terminate(_Reason, _State) ->sc_store:delete(self()).code_change(_OldVsn, State, _ExtraCondition) ->{ok, State}.
sc_element_sup.erl
-module(sc_element_sup).-behaviour(supervisor).-export([init/1]).%% ====================================================================%% API functions%% ====================================================================-export([start_link/0, start_child/2]).%% ====================================================================%% Behavioural functions %% ====================================================================init([]) -> AChild = {sc_element, {sc_element,start_link,[]}, temporary, brutal_kill, worker, [sc_element]},Children = [AChild],Strategy = {simple_one_for_one, 0, 1}, {ok,{Strategy, Children}}.%% ====================================================================%% Internal functions%% ====================================================================start_link() ->supervisor:start_link({local, ?MODULE}, ?MODULE, []).start_child(Value, LeaseTime) ->supervisor:start_child(?MODULE, [Value, LeaseTime]).
sc_event.erl
-module(sc_event).-export([start_link/0, add_handler/2, delete_handler/2, lookup/1, replace/2, create/2, delete/1]).%% ====================================================================%% Internal functions%% ====================================================================start_link() ->gen_event:start_link({local, ?MODULE}).add_handler(Handler, Args) ->gen_event:add_handler(?MODULE, Handler, Args).delete_handler(Handler, Args) ->gen_event:delete_handler(?MODULE, Handler, Args).lookup(Key) ->gen_event:notify(?MODULE, {lookup, Key}).replace(Key, Value) ->gen_event:notify(?MODULE, {replay, {Key, Value}}).create(Key, Value) ->gen_event:notify(?MODULE, {create, {Key, Value}}).delete(Key) ->gen_event:notify(?MODULE, {delete, Key}).
sc_event_logger.erl
-module(sc_event_logger).-behaviour(gen_event).-export([init/1, handle_event/2, handle_call/2, handle_info/2, terminate/2, code_change/3]).-export([add_handler/0, delete_handler/0]).-record(proState, {}).%% ====================================================================%% Internal functions%% ====================================================================add_handler() ->sc_event:add_handler(?MODULE, []).delete_handler() ->sc_event:delete_handler(?MODULE, []).%% ====================================================================%% Behavioural functions %% ====================================================================init([]) ->{ok, #proState{}}.handle_event({create, {Key, Value}}, State) ->error_logger:info_msg("创建缓存数据(~w, ~w)~n", [Key, Value]),%% 在shell中无法显示中文{ok, State};handle_event({lookup, Key}, State) ->error_logger:info_msg("lookup(~w)~n", [Key]),{ok, State};handle_event({replace, {Key, Value}}, State) ->error_logger:info_msg("replace(~w, ~w)~n", [Key, Value]),{ok, State};handle_event({delete, Key}, State) ->error_logger:info_msg("delete(~w)~n", [Key]),{ok, State}.handle_call(_Request, State) ->Reply = ok,{ok, Reply, State}.handle_info(_Info, State) ->{ok, State}.terminate(_Reason, _State) ->ok.code_change(_OldVsn, State, _ExtraCondition) ->{ok, State}.
sc_store.erl
%% @author Administrator%% @doc @todo Add description to sc_store.-module(sc_store).%% ====================================================================%% API functions%% ====================================================================-export([init/0, lookup/1, insert/2, delete/1]).-define(TABLE_ID, ?MODULE).%% ====================================================================%% Internal functions%% ====================================================================init() ->ets:new(?TABLE_ID, [named_table, public]),ok.lookup(Key) ->case ets:lookup(?TABLE_ID, Key) of[{Key, Pid}] -> {ok, Pid};[] -> {error, not_found}end.insert(Key, Pid) ->ets:insert(?TABLE_ID, {Key, Pid}).delete(Key) ->ets:match_delete(?TABLE_ID, {'_', Key}).
sc_sup.erl
%% @author Administrator%% @doc @todo Add description to sc_sup.-module(sc_sup).-behaviour(supervisor).-export([init/1]).%% ====================================================================%% API functions%% ====================================================================-export([start_link/0, start_child/2]).%% ====================================================================%% Behavioural functions %% ====================================================================init([]) -> ElementSupervisor = {sc_element_sup,%% 注意此处是sc_element_sup {sc_element_sup,start_link,[]},%% 注意此处是sc_element_sup,如果还是sc_element则会导致信息不详的错误提示 permanent,%% 重启策略修改了 2000,%% 关闭时间修改了 supervisor,%% 类型修改了 [sc_element]},%% 注意此处是sc_elementEventSupervisor = {sc_event,{sc_event, start_link, []},permanent,2000,worker,[sc_event]}, Children = [ElementSupervisor, EventSupervisor],Strategy = {one_for_one, 4, 3600}, {ok,{Strategy, Children}}.%% ====================================================================%% Internal functions%% ====================================================================start_link() ->supervisor:start_link({local, ?MODULE}, ?MODULE, []).start_child(Value, LeaseTime) ->supervisor:start_child(?MODULE, [Value, LeaseTime]).
simple_cache.erl
%% @author Administrator%% @doc @todo Add description to simple_cache.-module(simple_cache).%% ====================================================================%% API functions%% ====================================================================-export([lookup/1, insert/2, delete/1]).%% ====================================================================%% Internal functions%% ====================================================================lookup(Key) ->try{ok, Pid} = sc_store:lookup(Key),{ok, Value} = sc_element:fetch(Pid),sc_event:lookup(Key),{ok, Value}catch_Class:_Exception ->{error, not_found}end.insert(Key, Value) ->case sc_store:lookup(Key) of{ok, Pid} -> sc_element:replace(Pid, Value),sc_event:replace(Key, Value);{error, _} -> {ok, Pid} = sc_element:create(Value),sc_store:insert(Key, Pid),sc_event:create(Key, Value)%% 投递自定义的创建事件end.delete(Key) ->case sc_store:lookup(Key) of{ok, Pid} ->sc_element:delete(Pid),sc_event:delete(Key);{error, _Reason} ->okend.
0 0
- Erlang/OTP并发编程实例(二)
- Erlang/OTP并发编程实战
- erlang otp并发编程实战
- Erlang 并发编程基础二
- 图书封面的故事之“阿尔特温人”——选自《Erlang/OTP并发编程实战》图书封面
- Actor编程模型——Erlang/OTP
- Erlang入门(二)— 并发编程
- Erlang并发编程(二) --- Web服务
- Erlang并发编程实例一,客户机服务器模式
- Erlang—并发编程
- Erlang并发编程(一)
- erlang并发编程模板
- Erlang并发编程1
- Erlang并发编程2
- erlang 并发编程
- Erlang并发编程
- Erlang并发编程
- 业余研究 erlang /OTP
- 初学ucore操统笔记(1)
- P1190 繁忙的都市(Kruskal)
- 黑马程序员_IO流(三)
- Linux学习笔记(三)
- poj1330 求二叉树的公共父节点
- Erlang/OTP并发编程实例(二)
- 我做的仓库管理系统
- Java反射机制的缺点
- CC2530与zigbee学习笔记の初识zigbee(2)
- 第二章 HttpClient连接管理
- Apache中设置可以访问根目录,禁止访问子目录的方法
- 学习笔记之一shell脚本语法
- 生活随笔:程序员的自尊心和高傲、洁癖
- Longest Common Prefix