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:
parent
adfc9b41dd
commit
79777e7b1c
4 changed files with 104 additions and 16 deletions
|
@ -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
41
src/ggs_backup.erl
Normal 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.
|
|
@ -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.
|
||||||
|
|
|
@ -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..
|
||||||
|
|
Reference in a new issue