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
import sys
import socket
import sys, time, socket
HOST = 'localhost' # The remote host
PORT = int(sys.argv[1]) # The same port as used by the server
@ -53,5 +51,21 @@ fs = s.makefile()
data = fs.readline()
print "Token:", token
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
%%-----------------------------------------------------
start_link(Port) ->
process_flag(trap_exit, true),
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(?DEFAULT_PORT).
@ -63,12 +66,23 @@ stop() ->
%%-----------------------------------------------------
init([Port]) ->
case gen_server:call(ggs_backup, get_backup) of
{backup_state, not_initialized} ->
{ok, LSock} = gen_tcp:listen(Port, [{active, true},
{reuseaddr, true}]),
{ok, #state{port = Port, lsock = LSock}, 0}.
{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) ->
{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) ->
{stop, normal, State}.
@ -79,12 +93,16 @@ handle_info({tcp, Socket, RawData}, State) ->
io:format("Old map: ~p NewState: ~p~n", [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};
handle_info(timeout, #state{lsock = LSock} = State) ->
{ok, _Sock} = gen_tcp:accept(LSock),
{noreply, State}.
{noreply, State};
handle_info(Other, State) ->
erlang:display(Other).
terminate(_Reason, _State) ->
ok.
@ -105,6 +123,7 @@ do_JSCall(Socket, Data, State) ->
send(Socket, Token, "Okay, defined that for you!"),
[];
{call, Token, Payload} ->
io:format("Got call request: ~p~n", [Payload]),
JSVM = getJSVM(Token, State),
{ok, Ret} = js_runner:call(JSVM, Payload, []),%Payload, []),
send(Socket, Token, "JS says:", binary_to_list(Ret));
@ -114,6 +133,13 @@ do_JSCall(Socket, Data, State) ->
JSVM = js_runner:boot(),
Client = getRef(),
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};
{echo, RefID, _, MSG} ->
send(Socket, RefID, "Your VM is ", getJSVM(RefID, State)),
@ -121,11 +147,11 @@ do_JSCall(Socket, Data, State) ->
{crash, Zero} ->
10/Zero;
{vms} ->
send(Socket, "RefID", State)
send(Socket, "RefID", State);
% Set the new state to []
% Other ->
% send(Socket, "RefID", "__error"),
% []
Other ->
send(Socket, "RefID", "__error"),
[]
end,
% Return the new state
NewState.

View file

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