[erlang-questions] code_change for gen_fsm: how to actually handle a state change

Daniel Dormont <>
Wed Nov 23 05:13:15 CET 2011


Not precisely, it's a little more decoupled than that. This is inside
ejabberd. terminate/3 would inform the clients that the particular
resource (in this case a multi user chat) was disconnected and they
could reconnect at their leisure.

dan

On Tue, Nov 22, 2011 at 10:37 PM, Barco You <> wrote:
> And then a new process would be restarted by the supervisor with new version
> code?
> If in that way, how do you recover the state data?
> Barco
>
> On Tue, Nov 22, 2011 at 10:46 PM, Daniel Dormont <>
> wrote:
>>
>> Thanks, that makes sense.
>>
>> Here's another crazy idea, that I don't imagine is possible: can I
>> give code_change some kind of return value that says to the system "go
>> ahead and terminate this process, but call terminate/3 with the _old_
>> version of the code"? I know it sounds weird, but that would also be a
>> solution here.
>>
>> dan
>>
>> On Tue, Nov 22, 2011 at 5:35 AM, Richard Carlsson
>> <> wrote:
>> > On 11/22/2011 08:40 AM, Bengt Kleberg wrote:
>> >>
>> >> Is it correct to say that the old definition of #state{} is
>> >> -record(state, {item1, item2}).
>> >> and that the new is
>> >> -record(state, {item1, item2, newfield}).
>> >>
>> >> I think you will find it difficult to get both these records to work in
>> >> the same file at the same time (during code change).
>> >
>> >
>> > Possible solution: let code_change call a separate module that
>> > transforms
>> > the old definition to an intermediate format that the gen_fsm module can
>> > use
>> > to initialize the new state. That way, the different record declarations
>> > are
>> > never present in the same module.
>> >
>> > code_change(#state{}=State) ->
>> >    State;  % already the new state
>> > code_change(OldState) ->
>> >    init_state(state_converter:old_to_proplist(OldState)).
>> >
>> > init_state([{foo, Foo} | Ps], State) ->
>> >    init_state(Ps, State#state{foo=Foo});
>> > ...
>> > init_state([], State) ->
>> >    State.
>> >
>> > A more quick-and-dirty solution is to re-tag the old state so you can
>> > use it
>> > with a different state declaration:
>> >
>> > -record(old_state, {item1, item2}).
>> > -record(state, {item1, item2, newfield}).
>> >
>> > code_change(#state{}=State) ->
>> >    State;  % already the new state
>> > code_change(OldState) ->
>> >    update_state(setelement(1, State, 'old_state'), #state{}).
>> >
>> > update_state(OldState, State) ->
>> >    State#state{item1 = OldState#old_state.item1,
>> >                item2 = OldState#old_state.item2,
>> >                newfield = 42}.
>> >
>> >
>> >    /Richard
>> > _______________________________________________
>> > erlang-questions mailing list
>> > 
>> > http://erlang.org/mailman/listinfo/erlang-questions
>> >
>> _______________________________________________
>> erlang-questions mailing list
>> 
>> http://erlang.org/mailman/listinfo/erlang-questions
>
>



More information about the erlang-questions mailing list