[erlang-questions] help with gen_fsm for a new erlang user
Greg Smyth
gsmyth@REDACTED
Mon Aug 17 17:23:55 CEST 2009
Thanks Torben!
I ended up trying it in a slightly different way (using the 'timeout' event
for the run state as well, rather than explicitly using the timeout module)
- but your explanation helped me to see the mistakes in my thinking (how i
needed an explicit event to drive into the run state).
Cheers,
Greg
On Mon, Aug 17, 2009 at 3:10 PM, Torben Hoffmann <
torben.lehoff@REDACTED> wrote:
> Hi Greg,
>
> You have run into one of the small beauties of gen_fsm which can be a bit
> confusing when starting out with the state machines in Erlang.
>
> Your problem is that there is nothing driving your gen_fsm forward except
> for the initial timeout.
>
> In run you are waiting for an arbitrary event, but you never generate an
> event that will trigger the code.
>
> Speaking in terms of other state machine formalisms you are expecting an
> entry action to be executed when you enter a state, but there is no such
> thing out of the box for a gen_fsm.
>
> Given your requirements I might go as far as to suggest using a gen_server,
> but regardless you need to have something that drives your process.
>
> Suppose you create an API function for your existing code:
> run_stuff() ->
> gen_fsm:send_event(?MODULE,run_it).
>
> Then you add the following to run state:
> run(run_it,State) ->
> ... your old code
>
> This will allow you to call runner_fsm:run_stuff() from the command line
> and see some action.
>
> Doing this ever so often requires usage of functions from the timer module
> which I encourage you to investigate.
>
> You can use the timer module functions to call a function at your required
> rate inside or outside your gen_fsm.
>
> Hope this helps,
> Torben
>
>
>
> On Mon, Aug 17, 2009 at 15:22, Greg Smyth <gsmyth@REDACTED> wrote:
>
>> Hi all,
>>
>> I'm learning erlang/OTP and I'm trying to write a pretty simple gen_fsm
>> service, but i'm having a bit of trouble and was wondering if someone
>> could
>> help correct my mistakes:-
>>
>> The service should have 2 states:-
>>
>> 1) waiting - where it will be waiting on a specified timeout.
>> 2) running - where it will be running a function over a list of hosts
>> (specified in 'Hostlist' dictionary with the host as the key)
>>
>> The code i have compiles ok, and returns {ok, Pid} from start_link/1 - but
>> i
>> see none of my io:format messages ever appear...
>>
>> Here's the code:-
>>
>> %%%%%%%%%
>>
>> -module(runner_fsm).
>> -behaviour(gen_fsm).
>>
>> %% API
>> -export([start_link/1]).
>>
>> %% gen_fsm callbacks
>> -export([init/1, wait/2, run/2, wait/3, run/3, handle_event/3,
>> handle_sync_event/4, handle_info/3, terminate/3, code_change/4]).
>>
>> %% internals
>> -export([pinger/1]).
>>
>> -define(SERVER, ?MODULE).
>>
>> start_link(Hostlist) ->
>> gen_fsm:start_link({local, ?SERVER}, ?MODULE, Hostlist, []).
>>
>> init(Hostlist) ->
>> {ok, wait, Hostlist, 30000}.
>>
>> wait(timeout, State) ->
>> {next_state, run, State}.
>>
>> run(_Event, State) ->
>> Hosts = dict:fetch_keys(State),
>> case lists:foreach(fun(Elem) -> runner_fsm:pinger(Elem) end, Hosts) of
>> ok ->
>> doNothingforNow;
>> fail ->
>> doNothingforNow
>> end,
>> {next_state, wait, State, 30000}.
>>
>> wait(_Event, _From, State) ->
>> Reply = ok,
>> {reply, Reply, wait, State, 30000}.
>>
>> run(_Event, _From, State) ->
>> Reply = ok,
>> {reply, Reply, run, State}.
>>
>> handle_event(_Event, StateName, State) ->
>> {next_state, StateName, State}.
>>
>> handle_sync_event(Event, From, StateName, State) ->
>> Reply = ok,
>> {reply, Reply, StateName, State}.
>>
>> handle_info(_Info, StateName, State) ->
>> {next_state, StateName, State}.
>>
>> terminate(_Reason, _StateName, _State) ->
>> ok.
>>
>> code_change(_OldVsn, StateName, State, _Extra) ->
>> {ok, StateName, State}.
>>
>> pinger(Host) ->
>> Command = lists:concat(["ping -c 1 ", Host, "; echo $?"]),
>> ExitCode = lists:last(string:tokens(os:cmd(Command), "\n")),
>> case ExitCode of
>> "0" -> io:format("OK: ~p~n", [Host]),
>> ok;
>> _ -> io:format("BAD: ~p~n", [Host]),
>> fail
>> end.
>>
>> %%%%%%%%%%%
>>
>> Any ideas/hints as to what i'm doing wrong?
>>
>> Many thanks,
>> Greg
>>
>
>
>
> --
> http://www.linkedin.com/in/torbenhoffmann
>
More information about the erlang-questions
mailing list