cnst
cnst

Reputation: 27218

Is code reload in Erlang limited to only two version?

The ability of Erlang to reload code with ease, without dropping existing connections, is a very attractive proposition, heavily featured as one of the features of the language.

What's not explicitly advertised, however, is that, apparently, you can only do such seamless reload a single time, before dropping the existing connections that haven't yet had the chance to switch the execution code path from old to new.

Is it indeed so, or does Erlang/OTP has an extra advanced code reload feature that avoids dropping the executing code paths from the already previous generation, when a second code reload is executed? (I mean, nginx, for example, can be binary upgraded any number of times.)

Upvotes: 3

Views: 254

Answers (2)

Pascal
Pascal

Reputation: 14042

2 versions only. To illustrate the behavior, I have used the small module:

-module (tver).

-compile([export_all]).

start(Name) ->
    Pid = spawn(?MODULE,loop,[]),
    register(Name,Pid).

loop() ->
    receive
        % an internal call won't reload the code. The process keeps
        % executing the current version 
        version -> io:format("version 1~n"), loop();
        % an external call will reload the code. The process will use
        % the new version if any available in the VM. Notes that it
        % will not search in the path if a new version exists!
        update -> io:format("update code~n"), ?MODULE:loop();
        stop -> io:format("bye...~n")
    end.

where I change the printed string when I change the version. and now the version management in action:

Erlang/OTP 18 [erts-7.0] [64-bit] [smp:4:4] [async-threads:10]

Eshell V7.0  (abort with ^G)
1> c(tver).
{ok,tver}
2> tver:start(v1).
true
3> v1 ! version.
version 1
version
4> whereis(v1).
<0.39.0>

modify version to version 2. The c/1 command compiles the code and load it in the VM

5> c(tver).        
{ok,tver}

Checks that the v1 process is still executing version 1

6> v1 ! version.   
version 1
version
7> whereis(v1).    
<0.39.0>

But a newly spawned process executes the version 2.

8> tver:start(v2). 
true
9> v1 ! version.  
version 1
version
10> v2 ! version.
version 2
version

an external call forces to use the new version. In real life, you should make some verifications like what is the old version, what is the new one, is the upgrade possible, is there some data to adapt...

11> v1 ! update. 
update code
update
12> v1 ! version.
version 2
version
13> v2 ! version.
version 2
version
14> whereis(v1).   
<0.39.0>
15> whereis(v2). 
<0.50.0>

make version 3, compile and reload

16> % modif version.
16> c(tver).        
{ok,tver}
17> whereis(v1).    
<0.39.0>
18> whereis(v2).    
<0.50.0>
19> v1 ! version.   
version 2
version
20> v1 ! version.   
version 2
version
21> v2 ! version.   
version 2
version
22> tver:start(v3). 
true
23> v2 ! version.  
version
version 2
24> v3 ! version.
version 3
version

fine version the pocesses 1 and 2 are executing the version 2, and the process 3 the version 3.

Now modify to version 4 without upgrading the processes v1 and v2, compile and load the code.

25> c(tver).                                                  
{ok,tver}
26> whereis(v1).                                              
undefined
27> whereis(v2).                                              
undefined

The n-2 version doesn't exist anymore! The processes V1 and V2 have died, although they were simply waiting on the receive block. In a real OTP system, their supervisor would have restarted them according to their restart strategy.

28> tver:start(v4).                                           
true
29> whereis(v3).                            
<0.69.0>
30> whereis(v4).
<0.80.0>

V3 and V4 processes are executing the version 3 and 4 respectively

31> v3 ! version.                                             
version
version 3
32> v4 ! version.
version 4
version
33>

Upvotes: 5

Hynek -Pichi- Vychodil
Hynek -Pichi- Vychodil

Reputation: 26121

Yep, you can only have two versions of one module running in one time. But you can write your code in a way which switches code to the new one during serving one connection.

Upvotes: 1

Related Questions