4 编程技术
4.1抽象并出发
eg:thesis_server1.erl
-module(thesis_server1).
-export([start/3, stop/1, rpc/2]).
start(Name, F, State) ->
register(Name, spawn(fun()->loop(Name, F, State) end)).
loop(Name, F, State) ->
receive
stop -> void;
{Pid, Query} -> {Reply, State1} = F(Query, State),
Pid ! {Name, Reply},
loop(Name, F, State1)
end.
stop(Name) -> Name ! stop.
rpc(Name, Query) ->
Name ! {self(), Query},
receive
{Name, Reply} -> Reply
end.
thesis_vshlr1.erl
-module(thesis_vshlr1).
-export([start/0, stop/0, handle_event/2, i_am_at/2,find/1]).
-import(thesis_server1,[start/3,stop/1,rpc/2]).
-import(dict, [new/0, store/3, find/2]).
start() -> start(vshlr, fun handle_event/2, new()).
stop() ->stop(vshlr).
i_am_at(Who, Where) ->
rpc(vshlr, {i_am_at, Who, Where}).
find(Who) ->
rpc(vshlr, {find, Who}).
handle_event({i_am_at, Who, Where}, Dict) ->
{ok, store(Who, Where, Dict)};
handle_event({find, Who}, Dict) ->
{find(Who, Dict), Dict}.
调用
1>thesis_vshlr1:start().
true
2>thesis_vshlr1:find("joe").
error
3>thesis_vshlr1:i_am_at("joe","sics").
ack
4>thesis_vshlr1:find"joe").
{ok,"sics"}
4.1.1 一个可容错的客户服务器模型
增加catch,可容错,其它同上
eg:thesis_server2.erl
-module(thesis_server2).
-export([start/3, stop/1, rpc/2]).
start(Name, F, State) ->
register(Name, spawn(fun()->loop(Name, F, State) end)).
loop(Name, F, State) ->
receive
stop -> void;
{From, Query} ->
case (catch F(Query, State)) of
{'EXIT', Why} ->
log(Name, Query, Why),
From ! {Name, crase},
loop(Name, F, State);
{Reply, State1} ->
log(Name, ok, Reply),
From ! {Name, Reply},
loop(Name, F, State1)
end
end.
stop(Name) -> Name ! stop.
rpc(Name, Query) ->
Name ! {self(), Query},
receive
{Name, crash} -> exit(rpc);
{Name, Reply} -> Reply
after 1000 ->
exit(timeout)
end.
log(Name, Query, Why) ->
io:format("Server ~p is ~p by ~p~n",[Name, Query, Why]).
thesis_vshlr2.erl
-module(thesis_vshlr2).
-export([start/0, stop/0, handle_event/2, i_am_at/2,find/1]).
-import(thesis_server2,[start/3,stop/1,rpc/2]).
-import(dict, [new/0, store/3, find/2]).
start() -> start(vshlr, fun handle_event/2, new()).
stop() ->stop(vshlr).
i_am_at(Who, Where) ->
rpc(vshlr, {i_am_at, Who, Where}).
find(Who) ->
rpc(vshlr, {find, Who}).
handle_event({i_am_at, Who, Where}, Dict) ->
{ok, store(Who, Where, Dict)};
handle_event({find, "myerror"}, Dict) ->
1/0;
handle_event({find, Who}, Dict) ->
{find(Who, Dict), Dict}.
1>thesis_vshlr2:start().
true
2>thesis_vshlr2:find("myerror").
Server vshlr is {find,"myerror"} by {badarith,
[{thesis_vshlr2,handle_event,2},
{thesis_server2,loop,3}]}
crase
eg:thesis_server3.erl
热替换程序,(还有问题,没成功)
-module(thesis_server3).
-export([start/3, stop/1, rpc/2,swap_code/2]).
start(Name, F, State) ->
register(Name, spawn(fun()->loop(Name, F, State) end)).
loop(Name, F, State) ->
receive
stop -> void;
{From, {swap_code, Fnew}} ->
From ! {Name,ok, ack},
loop(Name, Fnew,State);
{From, Query} ->
case (catch F(Query, State)) of
{'EXIT', Why} ->
log(Name, Query, Why),
From ! {Name, crase},
loop(Name, F, State);
{Reply, State1} ->
log(Name, ok, Reply),
From ! {Name,ok, Reply},
loop(Name, F, State1)
end
end.
stop(Name) -> Name ! stop.
swap_code(Name, F) ->
rpc(Name, {swap_code, F}).
rpc(Name, Query) ->
Name ! {self(), Query},
receive
{Name, crash} -> exit(rpc);
{Name,ok, Reply} -> Reply
after 1000 ->
exit(timeout)
end.
log(Name, Query, Why) ->
io:format("Server ~p is ~p by ~p~n",[Name, Query, Why]).
thesis_vshlr3.erl
-module(thesis_vshlr3).
-export([start/0, stop/0, handle_event/2, i_am_at/2,find/1]).
-import(thesis_server3,[start/3,stop/1,rpc/2,swap_code/2]).
-import(dict, [new/0, store/3, find/2]).
start() -> start(vshlr, fun handle_event/2, new()).
stop() ->stop(vshlr).
i_am_at(Who, Where) ->
rpc(vshlr, {i_am_at, Who, Where}).
find(Who) ->
rpc(vshlr, {find, Who}).
handle_event({i_am_at, Who, Where}, Dict) ->
{ok, store(Who, Where, Dict)};
handle_event({find, Who}, Dict) ->
{find(Who, Dict), Dict}.
1> thesis_server3:swap_code(thesis_vshlr1, fun(I,J)->thesis_vshlr1:handle_event(I,J) end).