Erlang/OTP Callback Modules II
April 23, 2009
Hynek (Pichi) Vychodil kindly pointed me to Joe Armstrong’s thesis to help deepen my understanding of callback modules.
Starting on page 98, Joe talks about “abstracting out concurrency.”
Keeping track of many concurrent process is mentally challenging and error-prone, he says. For this reason he advocates a library of generic components, written by skilled Erlang programmers, and “plugins,” written by programmers competent in Erlang sequential programming. This component library, of course, has become OTP.
Says Joe, “The generic component should hide details of concurrency and mechanisms for fault-tolerance from the plugins. The plugins should be written using only sequential code with well-defined types.”
My quick reading did not turn up the phrase “callback module.” May be there. But I take it that “callback module” and “plugin” are synonymous.
Check out Joe’s thesis for yourself. Tons of invaluable background straight from the man himself.
One crucial point still clouds my aging brain: When you call a function in, say, a gen_server callback module and, say, it returns a tuple like {ok, yada yada}, who’s listening and expected to respond? I definitely need to think this one through before I get back to my walk-through of iserve.
Meanwhile, I’m packing up for Erlang University. Plan to spend three days learning what I can from Chris Anderson and Jan Lehnard about CouchDB.
The following two days, Thursday and Friday, promise many hours of brain food. I’m particularly looking forward to Rusty Klophaus’s Nitrogen presentation. If you haven’t been following Google Groups Nitrogen Web Framework for Erlang, drop in. Lively exchange of performance profiling data has been particularly interesting.
While rubbing shoulders with Erlang greats at Erlang University, I also hope to learn much more about Web Machine and Erlyweb.
Can’t promise, but maybe I’ll come back with a few pearls of wisdom. Maybe even a photo or two. I certainly plan to get back to my dissection of iserve.
So, be back sometime in early May just as soon as the jet lag wears off.
April 24, 2009 at 3:41 pm
Callback modules are tricky, and the major part of the hump that you have to get over in order to grok OTP. Think of it this way: The gen_server (or gen_*) _is_ the server, not a library that the server that you’ve written is calling. What you’re doing when you write the callback module is writing a library (or plugin) that the gen_server will use to figure out how to react to different calls and casts – but the main server wait loop is contained in gen_server.
April 24, 2009 at 4:56 pm
Hi Jamaal,
OK, let’s take a real-world example.
Here’s the init function in iserve_server.erl.
init([Starter, PortAndIP, CbMod, CbData]) ->
process_flag(trap_exit, true),
erlang:link(Starter),
Port = port_of(PortAndIP),
IP = ip_of(PortAndIP),
case gen_tcp:listen(Port,[binary, {packet, http},
{reuseaddr, true},
{ip, IP},
{active, false},
{backlog, 30}]) of
{ok, ListenSocket} ->
%%Create first accepting process
Pid = iserve_socket:start_link(CbMod, CbData,
self(), ListenSocket, Port),
{ok, #state{listen_socket = ListenSocket,
port = Port,
acceptor = Pid,
cb_mod = CbMod,
cb_data = CbData,
starter = Starter
}};
{error, Reason} ->
{stop, Reason}
end.
If I’m understanding you, if init/1 gets the message {ok, ListenSocket}, then it sends the message
{ok, #state{listen_socket = ListenSocket,
port = Port,
acceptor = Pid,
cb_mod = CbMod,
cb_data = CbData,
starter = Starter
}}
back to iserve_server so, I presume, iserve_server knows where to listen for a request. Is this correct?
Also, what are CbMod and CbData and where do they come from? And, with no comments, how am I supposed to know this?
Jamaal, as always, I really really appreciate your help.
LRP
April 27, 2009 at 4:58 pm
> If I’m understanding you, if init/1 gets
> the message {ok, ListenSocket}, then it
> sends the message
> {ok, #state{listen_socket = ListenSocket,
> port = Port,
> acceptor = Pid,
> cb_mod = CbMod,
> cb_data = CbData,
> starter = Starter
> }}
That’s almost exactly true, except that this tuple isn’t a message, it’s just the return value of init/1, which is in the form of {ok, State}. That “State” variable is the gen_server’s state – which in this case and in many cases, has been declared as a record to give it some structure. gen_server is dumb, so it’s a little off to say that it now knows where to listen for a request, but what happens is that the State is threaded throughout every cast and call made to the server, therefore it is available to every handle_c[all/ast]/[3,4] function that you write in your callback module as one of the arguments.
> Also, what are CbMod and CbData and
> where do they come from? And, with no
> comments, how am I supposed to know
> this?
I have no idea what CbMod and CbData are (mainly because I can’t get on github today for some reason), but they are passed into iserve_server when it is started with start[_link]/3,4, in the Args parameter. In turn, start[_link]/3,4 is what starts init/1, with that /1 being the Args that it initially received.
The best way to figure out what those two things are would be to look through the handle_* functions in the module and find out when they are used again. When they are, they’ll always be referred to as cb_mod or cb_data when they’re fished out of the State#state{} record, so a search should be good enough to find them.
I hope that’s not insanely confusing. It might be easier to think about the entries in the #state record as OO object properties.
Jamaal.
April 28, 2009 at 4:42 am
Hi Jamaal,
As always, your reply is quite helpful, though I do need to think about it a bit more. I’m in Palo Alto, CA now. End of first day tutorials on couchDB. So I won’t have time to think much about iserve until I return early next week. May have more questions then.
CouchDB’s pretty interesting. The presenters, Jan Lehnardt and Chris Anderson, are doing a good job.
Can’t tell you how much comfort it gives me to have you looking over my shoulders.
Thanks again,
Lloyd
June 16, 2009 at 2:40 pm
How was the conf? Soured on erlang now?
June 16, 2009 at 4:56 pm
Hi Jamaal,
Not at all soured on Erlang. Conference was exciting and stoked me with much to think and write about. And a determination to role up my sleeves and start programming.
Unfortunately, I returned from Palo Alto to a week of listlessness — not quite flu, but close; a couple of weeks of man-page hell as I worked to bring up a new workstation, my son’s wedding, a house full of relatives, and two out-of-town graduations.
Plus the muse has been nagging me to keep forward progress on my novel. Down to the last two chapters of first draft.
Jamaal, I much appreciate your interest. And I will, I promise, start posting again within a week or two.
Thanks again,
LRP
July 27, 2009 at 2:45 pm
http://steve.vinoski.net/pdf/IC-Build_Your_Next_Web_Application_with_Erlang.pdf