Now we have a backup server which keeps track of ggs_server's state between crashes. JSVM doesn't seem to survive crash even though port to it is backed up by ggs_backup..

This commit is contained in:
Jonatan Pålsson 2011-02-05 15:24:30 +01:00
parent adfc9b41dd
commit 79777e7b1c
4 changed files with 104 additions and 16 deletions

View file

@ -1,8 +1,6 @@
#!/usr/bin/env python #!/usr/bin/env python
import sys import sys, time, socket
import socket
HOST = 'localhost' # The remote host HOST = 'localhost' # The remote host
PORT = int(sys.argv[1]) # The same port as used by the server PORT = int(sys.argv[1]) # The same port as used by the server
@ -53,5 +51,21 @@ fs = s.makefile()
data = fs.readline() data = fs.readline()
print "Token:", token print "Token:", token
print "Data: ", ' '.join(data.split(" ")[1:]) print "Data: ", ' '.join(data.split(" ")[1:])
s.close()
# Call that function!
print "Calling myFun"
s.send(
"Token: %s\n\
Command: call\n\
Content-Type: text\n\
Content-Length: 6\n\
\n\
myFun" % token)
fs = s.makefile()
data = fs.readline()
print "Token:", token
print "Data: ", ' '.join(data.split(" ")[1:])
s.close()

41
src/ggs_backup.erl Normal file
View file

@ -0,0 +1,41 @@
-module(ggs_backup).
-behaviour(gen_server).
%% API
-export([start_link/0 ]).
%% gen_server callbacks
-export([init/1, handle_call/3, handle_cast/2,
handle_info/2, terminate/2, code_change/3]).
-define(SERVER, ?MODULE).
-record(state, {port, lsock, client_vm_map = []}).
start_link() ->
gen_server:start_link({local, ?SERVER}, ?MODULE, [], []).
init([]) ->
{ok, #state{port = -1, lsock = -1, client_vm_map = -1}, 0}.
handle_call(get_backup, _From, State) ->
BackedUpState = case State of
#state{port = -1, lsock = -1, client_vm_map = -1} ->
not_initialized;
Other ->
Other
end,
{reply, {backup_state, BackedUpState}, State}.
handle_cast({set_backup, NewState}, _State) ->
{noreply, NewState}.
handle_info(_Msg, State) ->
{noreply, State}.
code_change(_OldVsn, State, _Extra) ->
{ok, State}.
terminate(_Reason, _State) ->
ok.

View file

@ -34,9 +34,12 @@
%% @end %% @end
%%----------------------------------------------------- %%-----------------------------------------------------
start_link(Port) -> start_link(Port) ->
process_flag(trap_exit, true),
gen_server:start_link({local, ?SERVER}, ?MODULE, [Port], []). gen_server:start_link({local, ?SERVER}, ?MODULE, [Port], []).
start_link(start_as_slave, State) ->
gen_server:start_link({local, ?SERVER}, ?MODULE,
[start_as_slave, State], []).
start_link() -> start_link() ->
start_link(?DEFAULT_PORT). start_link(?DEFAULT_PORT).
@ -63,12 +66,23 @@ stop() ->
%%----------------------------------------------------- %%-----------------------------------------------------
init([Port]) -> init([Port]) ->
{ok, LSock} = gen_tcp:listen(Port, [{active, true}, case gen_server:call(ggs_backup, get_backup) of
{reuseaddr, true}]), {backup_state, not_initialized} ->
{ok, #state{port = Port, lsock = LSock}, 0}. {ok, LSock} = gen_tcp:listen(Port, [{active, true},
{reuseaddr, true}]),
{ok, #state{port = Port, lsock = LSock}, 0};
{backup_state, State} ->
{ok, LSock} = gen_tcp:listen(Port, [{active, true},
{reuseaddr, true}]),
{ok, State#state{lsock = LSock}, 0}
end.
handle_call(get_count, _From, State) -> handle_call(get_count, _From, State) ->
{reply, {ok, State#state.client_vm_map}, State}. {reply, {ok, State#state.client_vm_map}, State};
handle_call({backup_state, OldState}, _From, State) ->
io:format("Received old state from backup~n"),
{noreply, OldState}.
handle_cast(stop, State) -> handle_cast(stop, State) ->
{stop, normal, State}. {stop, normal, State}.
@ -79,12 +93,16 @@ handle_info({tcp, Socket, RawData}, State) ->
io:format("Old map: ~p NewState: ~p~n", [OldMap, NewState]), io:format("Old map: ~p NewState: ~p~n", [OldMap, NewState]),
{noreply, State#state{client_vm_map = OldMap ++ [NewState]}}; {noreply, State#state{client_vm_map = OldMap ++ [NewState]}};
handle_info({tcp_closed, _}, State) -> handle_info({tcp_closed, Socket}, State) ->
gen_tcp:close(Socket),
{stop, "Client closed socket", State}; {stop, "Client closed socket", State};
handle_info(timeout, #state{lsock = LSock} = State) -> handle_info(timeout, #state{lsock = LSock} = State) ->
{ok, _Sock} = gen_tcp:accept(LSock), {ok, _Sock} = gen_tcp:accept(LSock),
{noreply, State}. {noreply, State};
handle_info(Other, State) ->
erlang:display(Other).
terminate(_Reason, _State) -> terminate(_Reason, _State) ->
ok. ok.
@ -105,6 +123,7 @@ do_JSCall(Socket, Data, State) ->
send(Socket, Token, "Okay, defined that for you!"), send(Socket, Token, "Okay, defined that for you!"),
[]; [];
{call, Token, Payload} -> {call, Token, Payload} ->
io:format("Got call request: ~p~n", [Payload]),
JSVM = getJSVM(Token, State), JSVM = getJSVM(Token, State),
{ok, Ret} = js_runner:call(JSVM, Payload, []),%Payload, []), {ok, Ret} = js_runner:call(JSVM, Payload, []),%Payload, []),
send(Socket, Token, "JS says:", binary_to_list(Ret)); send(Socket, Token, "JS says:", binary_to_list(Ret));
@ -114,6 +133,13 @@ do_JSCall(Socket, Data, State) ->
JSVM = js_runner:boot(), JSVM = js_runner:boot(),
Client = getRef(), Client = getRef(),
send(Socket, Client, "This is your refID"), send(Socket, Client, "This is your refID"),
%% This shouldnt be here...
OldMap = State#state.client_vm_map,
BackupState = State#state{client_vm_map = OldMap ++ [{Client, JSVM}]},
gen_server:cast(ggs_backup, {set_backup, BackupState}),
%%
{Client, JSVM}; {Client, JSVM};
{echo, RefID, _, MSG} -> {echo, RefID, _, MSG} ->
send(Socket, RefID, "Your VM is ", getJSVM(RefID, State)), send(Socket, RefID, "Your VM is ", getJSVM(RefID, State)),
@ -121,11 +147,11 @@ do_JSCall(Socket, Data, State) ->
{crash, Zero} -> {crash, Zero} ->
10/Zero; 10/Zero;
{vms} -> {vms} ->
send(Socket, "RefID", State) send(Socket, "RefID", State);
% Set the new state to [] % Set the new state to []
% Other -> Other ->
% send(Socket, "RefID", "__error"), send(Socket, "RefID", "__error"),
% [] []
end, end,
% Return the new state % Return the new state
NewState. NewState.

View file

@ -24,6 +24,13 @@ init([Port]) ->
worker, worker,
[ggs_server] [ggs_server]
}, },
Backup = {ggs_backup,
{ggs_backup, start_link, []},
permanent,
2000,
worker,
[ggs_backup]
},
MnesiaServer = {ggs_mnesia_controller_server, MnesiaServer = {ggs_mnesia_controller_server,
{ggs_mnesia_controller_server, start_link, []}, {ggs_mnesia_controller_server, start_link, []},
permanent, permanent,
@ -31,7 +38,7 @@ init([Port]) ->
worker, worker,
[ggs_mnesia_controller_server] [ggs_mnesia_controller_server]
}, },
Children = [MnesiaServer, GGSServer], Children = [MnesiaServer, Backup, GGSServer],
RestartStrategy = { one_for_one, % Restart only crashing child RestartStrategy = { one_for_one, % Restart only crashing child
10, % Allow ten crashes per.. 10, % Allow ten crashes per..