Erlang's Open Telecom Platform (OTP) Framework
Steve Vinoski
Architect, Basho Technologies Cambridge, MA USA vinoski@ieee.org @stevevinoski http://steve.vinoski.net
1
1 Monday, June 18, 12
Erlang's Open Telecom Platform (OTP) Framework Steve Vinoski - - PowerPoint PPT Presentation
Erlang's Open Telecom Platform (OTP) Framework Steve Vinoski Architect, Basho Technologies Cambridge, MA USA vinoski@ieee.org @stevevinoski http://steve.vinoski.net 1 Monday, June 18, 12 1 Erlang 2 Monday, June 18, 12 2 Functional
Steve Vinoski
Architect, Basho Technologies Cambridge, MA USA vinoski@ieee.org @stevevinoski http://steve.vinoski.net
1
1 Monday, June 18, 12
2
2 Monday, June 18, 12
3
3 Monday, June 18, 12
4
4 Monday, June 18, 12
4
4 Monday, June 18, 12
Verivue MDX 9200
4
4 Monday, June 18, 12
Verivue MDX 9200
4
4 Monday, June 18, 12
Verivue MDX 9200
4
4 Monday, June 18, 12
5
5 Monday, June 18, 12
6
6 Monday, June 18, 12
6
6 Monday, June 18, 12
7
7 Monday, June 18, 12
8
8 Monday, June 18, 12
9
9 Monday, June 18, 12
10
10 Monday, June 18, 12
across multiple computers
software faults
11
11 Monday, June 18, 12
across multiple computers
software faults
12
12 Monday, June 18, 12
13
13 Monday, June 18, 12
13
13 Monday, June 18, 12
14
14 Monday, June 18, 12
15
15 Monday, June 18, 12
16
16 Monday, June 18, 12
CPU Core 1
CPU Core N
16
16 Monday, June 18, 12
CPU Core 1
CPU Core N
16
16 Monday, June 18, 12
SMP Schedulers
Erlang VM
CPU Core 1
CPU Core N
16
16 Monday, June 18, 12
SMP Schedulers
Erlang VM
CPU Core 1
CPU Core N
16
16 Monday, June 18, 12
SMP Schedulers
Erlang VM
Process Process Process Process Process Process
CPU Core 1
CPU Core N
16
16 Monday, June 18, 12
message to another Erlang process
Erlang process
always
17
17 Monday, June 18, 12
18
18 Monday, June 18, 12
19
19 Monday, June 18, 12
receive Pattern1 [when Guard1] -> Expressions; Pattern2 [when Guard2] -> Expressions; ... end
is received
(receive ... after Milliseconds -> Expr(s) end)
20
20 Monday, June 18, 12
message queue, even pre-existing ones
expressions and returns
does
after expressions
21
21 Monday, June 18, 12
22
22 Monday, June 18, 12
23
23 Monday, June 18, 12
24
24 Monday, June 18, 12
25
25 Monday, June 18, 12
26
26 Monday, June 18, 12
27
27 Monday, June 18, 12
28
28 Monday, June 18, 12
29
29 Monday, June 18, 12
30
30 Monday, June 18, 12
31
31 Monday, June 18, 12
32
32 Monday, June 18, 12
33
33 Monday, June 18, 12
34
34 Monday, June 18, 12
35
35 Monday, June 18, 12
36
36 Monday, June 18, 12
37
37 Monday, June 18, 12
38
38 Monday, June 18, 12
39
39 Monday, June 18, 12
40
40 Monday, June 18, 12
40
40 Monday, June 18, 12
40
40 Monday, June 18, 12
40
40 Monday, June 18, 12
40
40 Monday, June 18, 12
40
40 Monday, June 18, 12
is tied to the other (erlang:link/1,
erlang:spawn_link/1,2,3,4)
another (erlang:monitor/2)
another one dies
41
41 Monday, June 18, 12
42
42 Monday, June 18, 12
43
43 Monday, June 18, 12
44
44 Monday, June 18, 12
45
45 Monday, June 18, 12
46
46 Monday, June 18, 12
47
47 Monday, June 18, 12
48
48 Monday, June 18, 12
49
not mutation
the value of the right-hand side
the right-hand side
49 Monday, June 18, 12
50
50 Monday, June 18, 12
51
51 Monday, June 18, 12
52
52 Monday, June 18, 12
53
53 Monday, June 18, 12
54
54 Monday, June 18, 12
55
55 Monday, June 18, 12
56
56 Monday, June 18, 12
57
57 Monday, June 18, 12
loop(Callbacks, State) -> {LoopAction, NState} = receive {message1, M1} -> Callbacks:handle_m1(M1,State); {message2, M2} -> Callbacks:handle_m2(M2,State); Other -> Callbacks:handle_other(Other,State) end, case LoopAction of stop -> ok; _ -> loop(Callbacks, NState) end.
58
58 Monday, June 18, 12
loop(Callbacks, State) -> {LoopAction, NState} = receive {message1, M1} -> Callbacks:handle_m1(M1,State); {message2, M2} -> Callbacks:handle_m2(M2,State); Other -> Callbacks:handle_other(Other,State) end, case LoopAction of stop -> ok; _ -> loop(Callbacks, NState) end.
59
59 Monday, June 18, 12
60
60 Monday, June 18, 12
61
61 Monday, June 18, 12
62
62 Monday, June 18, 12
start_link(ServerName, Module, Args, Options) -> Result
where Name becomes the registered process name
63
63 Monday, June 18, 12
64
64 Monday, June 18, 12
call to the server
call(ServerRef, Request, Timeout) -> Reply
gen_server process
65
65 Monday, June 18, 12
gen_server:call
process
66
66 Monday, June 18, 12
{stop, Reason, NewState}
gen_server:reply/2
67
67 Monday, June 18, 12
68
68 Monday, June 18, 12
69
69 Monday, June 18, 12
70
70 Monday, June 18, 12
71
71 Monday, June 18, 12
72
72 Monday, June 18, 12
Module:init gen_server:start_link
gen_server:call Module:handle_call gen_server:cast Module:handle_cast
Module:handle_info
73
73 Monday, June 18, 12
74
74 Monday, June 18, 12
75
75 Monday, June 18, 12
76
76 Monday, June 18, 12
76
76 Monday, June 18, 12
76
76 Monday, June 18, 12
76
76 Monday, June 18, 12
76
76 Monday, June 18, 12
76
76 Monday, June 18, 12
76
76 Monday, June 18, 12
77
77 Monday, June 18, 12
77
77 Monday, June 18, 12
77
77 Monday, June 18, 12
77
77 Monday, June 18, 12
77
77 Monday, June 18, 12
78
78 Monday, June 18, 12
78
78 Monday, June 18, 12
78
78 Monday, June 18, 12
handle_call({store,Key,Value},_From,#state{table=Tbl}=State) -> true = ets:insert(Tbl, {Key, Value}), {reply, ok, State};
79
79 Monday, June 18, 12
handle_call({store,Key,Value},_From,#state{table=Tbl}=State) -> true = ets:insert(Tbl, {Key, Value}), {reply, ok, State};
79
79 Monday, June 18, 12
handle_call({store,Key,Value},_From,#state{table=Tbl}=State) -> true = ets:insert(Tbl, {Key, Value}), {reply, ok, State};
79
79 Monday, June 18, 12
handle_call({store,Key,Value},_From,#state{table=Tbl}=State) -> true = ets:insert(Tbl, {Key, Value}), {reply, ok, State};
79
79 Monday, June 18, 12
handle_call({lookup, Key}, _From, #state{table = Tbl} = State) -> Reply = case ets:lookup(Tbl, Key) of [{Key, Value}] -> {ok, Value}; [] -> not_found end, {reply, Reply, State}; handle_call(_, _From, State) -> {reply, ok, State}.
80
80 Monday, June 18, 12
handle_call({lookup, Key}, _From, #state{table = Tbl} = State) -> Reply = case ets:lookup(Tbl, Key) of [{Key, Value}] -> {ok, Value}; [] -> not_found end, {reply, Reply, State}; handle_call(_, _From, State) -> {reply, ok, State}.
80
80 Monday, June 18, 12
handle_call({lookup, Key}, _From, #state{table = Tbl} = State) -> Reply = case ets:lookup(Tbl, Key) of [{Key, Value}] -> {ok, Value}; [] -> not_found end, {reply, Reply, State}; handle_call(_, _From, State) -> {reply, ok, State}.
80
80 Monday, June 18, 12
handle_call({lookup, Key}, _From, #state{table = Tbl} = State) -> Reply = case ets:lookup(Tbl, Key) of [{Key, Value}] -> {ok, Value}; [] -> not_found end, {reply, Reply, State}; handle_call(_, _From, State) -> {reply, ok, State}.
80
80 Monday, June 18, 12
handle_call({lookup, Key}, _From, #state{table = Tbl} = State) -> Reply = case ets:lookup(Tbl, Key) of [{Key, Value}] -> {ok, Value}; [] -> not_found end, {reply, Reply, State}; handle_call(_, _From, State) -> {reply, ok, State}.
80
80 Monday, June 18, 12
81
81 Monday, June 18, 12
81
81 Monday, June 18, 12
81
81 Monday, June 18, 12
81
81 Monday, June 18, 12
82
82 Monday, June 18, 12
83
83 Monday, June 18, 12
20> key_value:start_link(). {ok,<0.33.0>} 21> key_value:store("foo", "bar").
22> key_value:lookup("foo"). {ok, "bar"} 23> key_value:lookup("baz"). not_found 24> key_value:delete("foo").
25> key_value:lookup("foo"). not_found
84
84 Monday, June 18, 12
20> key_value:start_link(). {ok,<0.33.0>} 21> key_value:store("foo", "bar").
22> key_value:lookup("foo"). {ok, "bar"} 23> key_value:lookup("baz"). not_found 24> key_value:delete("foo").
25> key_value:lookup("foo"). not_found
84
84 Monday, June 18, 12
20> key_value:start_link(). {ok,<0.33.0>} 21> key_value:store("foo", "bar").
22> key_value:lookup("foo"). {ok, "bar"} 23> key_value:lookup("baz"). not_found 24> key_value:delete("foo").
25> key_value:lookup("foo"). not_found
84
84 Monday, June 18, 12
20> key_value:start_link(). {ok,<0.33.0>} 21> key_value:store("foo", "bar").
22> key_value:lookup("foo"). {ok, "bar"} 23> key_value:lookup("baz"). not_found 24> key_value:delete("foo").
25> key_value:lookup("foo"). not_found
84
84 Monday, June 18, 12
20> key_value:start_link(). {ok,<0.33.0>} 21> key_value:store("foo", "bar").
22> key_value:lookup("foo"). {ok, "bar"} 23> key_value:lookup("baz"). not_found 24> key_value:delete("foo").
25> key_value:lookup("foo"). not_found
84
84 Monday, June 18, 12
20> key_value:start_link(). {ok,<0.33.0>} 21> key_value:store("foo", "bar").
22> key_value:lookup("foo"). {ok, "bar"} 23> key_value:lookup("baz"). not_found 24> key_value:delete("foo").
25> key_value:lookup("foo"). not_found
84
84 Monday, June 18, 12
20> key_value:start_link(). {ok,<0.33.0>} 21> key_value:store("foo", "bar").
22> key_value:lookup("foo"). {ok, "bar"} 23> key_value:lookup("baz"). not_found 24> key_value:delete("foo").
25> key_value:lookup("foo"). not_found
84
84 Monday, June 18, 12
26> key_value:stop().
27> key_value:lookup("foo"). ** exception exit: {noproc, {gen_server,call, [key_value,{lookup,"foo"}]}} in function gen_server:call/2 (gen_server.erl, line 180)
85
85 Monday, June 18, 12
86
86 Monday, June 18, 12
87
87 Monday, June 18, 12
88
88 Monday, June 18, 12
89
89 Monday, June 18, 12
gen_fsm process
function named for the current state
into gen_fsm process
regardless of current state
90
90 Monday, June 18, 12
gen_fsm process
function named for the current state
into gen_fsm process
regardless of current state
91
91 Monday, June 18, 12
92
92 Monday, June 18, 12
93
93 Monday, June 18, 12
94
94 Monday, June 18, 12
starts the app
OTP behaviors
95
95 Monday, June 18, 12
%% Application callbacks
start(_StartType, _StartArgs) -> bitcask_sup:start_link(). stop(_State) ->
96
96 Monday, June 18, 12
%% Application callbacks
start(_StartType, _StartArgs) -> bitcask_sup:start_link(). stop(_State) ->
97
97 Monday, June 18, 12
%% Application callbacks
start(_StartType, _StartArgs) -> bitcask_sup:start_link(). stop(_State) ->
98
98 Monday, June 18, 12
%% Application callbacks
start(_StartType, _StartArgs) -> bitcask_sup:start_link(). stop(_State) ->
99
99 Monday, June 18, 12
%% Application callbacks
start(_StartType, _StartArgs) -> bitcask_sup:start_link(). stop(_State) ->
100
100 Monday, June 18, 12
supervisors
restarting one or more children
101
101 Monday, June 18, 12
102
102 Monday, June 18, 12
103
103 Monday, June 18, 12
103
103 Monday, June 18, 12
103
103 Monday, June 18, 12
103
103 Monday, June 18, 12
%% API
%% Supervisor callbacks
start_link() -> supervisor:start_link({local, ?MODULE}, ?MODULE, []).
104
104 Monday, June 18, 12
init([]) -> {ok, {{RestartStrategy, MaxRestarts, MaxTime}, [ChildSpecifications]}}.
105
105 Monday, June 18, 12
init([]) -> {ok, {{one_for_one, 5, 10}, [{bitcask_merge_worker, {bitcask_merge_worker, start_link, []}, permanent, 5000, worker, [bitcask_merge_worker]}]}}.
106
106 Monday, June 18, 12
init([]) -> {ok, {{one_for_one, 5, 10}, [{bitcask_merge_worker, {bitcask_merge_worker, start_link, []}, permanent, 5000, worker, [bitcask_merge_worker]}]}}.
106
106 Monday, June 18, 12
init([]) -> {ok, {{one_for_one, 5, 10}, [{bitcask_merge_worker, {bitcask_merge_worker, start_link, []}, permanent, 5000, worker, [bitcask_merge_worker]}]}}.
106
106 Monday, June 18, 12
init([]) -> {ok, {{one_for_one, 5, 10}, [{bitcask_merge_worker, {bitcask_merge_worker, start_link, []}, permanent, 5000, worker, [bitcask_merge_worker]}]}}.
106
106 Monday, June 18, 12
107
107 Monday, June 18, 12
init([]) -> {ok, {{RestartStrategy, MaxRestarts, MaxTime}, [ChildSpecifications]}}.
108
108 Monday, June 18, 12
109
109 Monday, June 18, 12
109
109 Monday, June 18, 12
109
109 Monday, June 18, 12
109
109 Monday, June 18, 12
109
109 Monday, June 18, 12
109
109 Monday, June 18, 12
109
109 Monday, June 18, 12
109
109 Monday, June 18, 12
110
110 Monday, June 18, 12
111
behaviors, very useful for debug
here)
111 Monday, June 18, 12
31> {ok, Pid} = key_value:start_link(). {ok,<0.71.0>} 32> sys:get_status(key_value). {status,<0.71.0>, {module,gen_server}, [[{'$ancestors',[<0.67.0>]}, {'$initial_call',{key_value,init,1}}], running,<0.67.0>,[], [{header,"Status for generic server key_value"}, {data,[{"Status",running}, {"Parent",<0.67.0>}, {"Logged events",[]}]}, {data,[{"State",{state,24592}}]}]]}
112
112 Monday, June 18, 12
33> process_info(Pid). [{registered_name,key_value}, {current_function,{gen_server,loop,6}}, {initial_call,{proc_lib,init_p,5}}, {status,waiting}, {message_queue_len,0}, {messages,[]}, {links,[<0.67.0>]}, ... (more here, truncated)
113
113 Monday, June 18, 12
38> sys:trace(key_value, true).
39> key_value:lookup("foo"). *DBG* key_value got call {lookup,"foo"} from <0.67.0> *DBG* key_value sent {ok,"bar"} to <0.67.0>, new state {state,24592} {ok,"bar"}
114
114 Monday, June 18, 12
need for special build
results, the caller, time of call
use
if not careful
115
115 Monday, June 18, 12
40> dbg:tracer(). {ok,<0.125.0>} 41> dbg:p(all, call). {ok,[{matched,nonode@nohost,27}]} 42> dbg:p(key_value, [c,m]). {ok,[{matched,nonode@nohost,1}]} 43> dbg:tpl(key_value, c). {ok,[{matched,nonode@nohost,13},{saved,c}]}
116
116 Monday, June 18, 12
40> dbg:tracer(). {ok,<0.125.0>} 41> dbg:p(all, call). {ok,[{matched,nonode@nohost,27}]} 42> dbg:p(key_value, [c,m]). {ok,[{matched,nonode@nohost,1}]} 43> dbg:tpl(key_value, c). {ok,[{matched,nonode@nohost,13},{saved,c}]}
116
116 Monday, June 18, 12
40> dbg:tracer(). {ok,<0.125.0>} 41> dbg:p(all, call). {ok,[{matched,nonode@nohost,27}]} 42> dbg:p(key_value, [c,m]). {ok,[{matched,nonode@nohost,1}]} 43> dbg:tpl(key_value, c). {ok,[{matched,nonode@nohost,13},{saved,c}]}
116
116 Monday, June 18, 12
40> dbg:tracer(). {ok,<0.125.0>} 41> dbg:p(all, call). {ok,[{matched,nonode@nohost,27}]} 42> dbg:p(key_value, [c,m]). {ok,[{matched,nonode@nohost,1}]} 43> dbg:tpl(key_value, c). {ok,[{matched,nonode@nohost,13},{saved,c}]}
116
116 Monday, June 18, 12
40> dbg:tracer(). {ok,<0.125.0>} 41> dbg:p(all, call). {ok,[{matched,nonode@nohost,27}]} 42> dbg:p(key_value, [c,m]). {ok,[{matched,nonode@nohost,1}]} 43> dbg:tpl(key_value, c). {ok,[{matched,nonode@nohost,13},{saved,c}]}
116
116 Monday, June 18, 12
44> key_value:store("foo", "bar").
(<0.67.0>) call key_value:store("foo","bar") ({erl_eval,do_apply,6}) (<0.71.0>) << {'$gen_call',{<0.67.0>,#Ref<0.0.0.490>}, {store,"foo","bar"}} (<0.71.0>) call key_value:handle_call({store,"foo","bar"}, {<0.67.0>,#Ref<0.0.0.490>},{state,36880}) ({gen_server,handle_msg, 5}) (<0.71.0>) <0.67.0> ! {#Ref<0.0.0.490>,ok}
117
117 Monday, June 18, 12
44> key_value:store("foo", "bar").
(<0.67.0>) call key_value:store("foo","bar") ({erl_eval,do_apply,6}) (<0.71.0>) << {'$gen_call',{<0.67.0>,#Ref<0.0.0.490>}, {store,"foo","bar"}} (<0.71.0>) call key_value:handle_call({store,"foo","bar"}, {<0.67.0>,#Ref<0.0.0.490>},{state,36880}) ({gen_server,handle_msg, 5}) (<0.71.0>) <0.67.0> ! {#Ref<0.0.0.490>,ok}
117
117 Monday, June 18, 12
44> key_value:store("foo", "bar").
(<0.67.0>) call key_value:store("foo","bar") ({erl_eval,do_apply,6}) (<0.71.0>) << {'$gen_call',{<0.67.0>,#Ref<0.0.0.490>}, {store,"foo","bar"}} (<0.71.0>) call key_value:handle_call({store,"foo","bar"}, {<0.67.0>,#Ref<0.0.0.490>},{state,36880}) ({gen_server,handle_msg, 5}) (<0.71.0>) <0.67.0> ! {#Ref<0.0.0.490>,ok}
117
117 Monday, June 18, 12
44> key_value:store("foo", "bar").
(<0.67.0>) call key_value:store("foo","bar") ({erl_eval,do_apply,6}) (<0.71.0>) << {'$gen_call',{<0.67.0>,#Ref<0.0.0.490>}, {store,"foo","bar"}} (<0.71.0>) call key_value:handle_call({store,"foo","bar"}, {<0.67.0>,#Ref<0.0.0.490>},{state,36880}) ({gen_server,handle_msg, 5}) (<0.71.0>) <0.67.0> ! {#Ref<0.0.0.490>,ok}
117
117 Monday, June 18, 12
44> key_value:store("foo", "bar").
(<0.67.0>) call key_value:store("foo","bar") ({erl_eval,do_apply,6}) (<0.71.0>) << {'$gen_call',{<0.67.0>,#Ref<0.0.0.490>}, {store,"foo","bar"}} (<0.71.0>) call key_value:handle_call({store,"foo","bar"}, {<0.67.0>,#Ref<0.0.0.490>},{state,36880}) ({gen_server,handle_msg, 5}) (<0.71.0>) <0.67.0> ! {#Ref<0.0.0.490>,ok}
117
117 Monday, June 18, 12
44> key_value:store("foo", "bar").
(<0.67.0>) call key_value:store("foo","bar") ({erl_eval,do_apply,6}) (<0.71.0>) << {'$gen_call',{<0.67.0>,#Ref<0.0.0.490>}, {store,"foo","bar"}} (<0.71.0>) call key_value:handle_call({store,"foo","bar"}, {<0.67.0>,#Ref<0.0.0.490>},{state,36880}) ({gen_server,handle_msg, 5}) (<0.71.0>) <0.67.0> ! {#Ref<0.0.0.490>,ok}
117
117 Monday, June 18, 12
args
extensive, we’ve barely scratched the surface
(https://github.com/massemanet/eper)
118
118 Monday, June 18, 12
119
concurrent distributed applications
take care of nitty-gritty details, let you focus on your application
number of projects with years in production
119 Monday, June 18, 12
120
120 Monday, June 18, 12
121
121 Monday, June 18, 12
122
122 Monday, June 18, 12