From 3285bb9a7e77ae84dac0fb74fc9d85726ed02053 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonatan=20P=C3=A5lsson?= Date: Wed, 2 Feb 2011 19:09:44 +0100 Subject: [PATCH 01/20] Added new 'root' supervisor, and mnesia as child to this supervisor --- ebin/ggs.app | 3 +- src/ggs_mnesia_controller_server.erl | 63 ++++++++++++++++++++++++++++ src/ggs_server.erl | 1 + src/ggs_server_sup.erl | 41 ++++++++++++++++++ src/ggs_sup.erl | 6 +-- start | 2 +- 6 files changed, 110 insertions(+), 6 deletions(-) create mode 100644 src/ggs_mnesia_controller_server.erl create mode 100644 src/ggs_server_sup.erl diff --git a/ebin/ggs.app b/ebin/ggs.app index cafc9df..3315864 100644 --- a/ebin/ggs.app +++ b/ebin/ggs.app @@ -3,8 +3,7 @@ {vsn, "0.1.0"}, {modules, [ ggs_app, - ggs_sup, - ggs_server + ggs_sup ]}, {registered, [ggs_sup]}, {applications, [kernel, stdlib]}, diff --git a/src/ggs_mnesia_controller_server.erl b/src/ggs_mnesia_controller_server.erl new file mode 100644 index 0000000..0b384f1 --- /dev/null +++ b/src/ggs_mnesia_controller_server.erl @@ -0,0 +1,63 @@ +-module(ggs_mnesia_controller_server). +-behaviour(gen_server). + +%% API +-export([start_link/0, + stop/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, {}). + +%%%==================================================== +%%% API +%%%==================================================== + +%%----------------------------------------------------- +%% @doc Starts the server +%% @end +%%----------------------------------------------------- +start_link() -> + gen_server:start_link({local, ?SERVER}, ?MODULE, [], []). + +%%----------------------------------------------------- +%% @doc Stops the server. +%% @spec stop() -> ok +%% @end +%%----------------------------------------------------- +stop() -> + gen_server:cast(?SERVER, stop). + +%%----------------------------------------------------- +%% gen_server callbacks +%%----------------------------------------------------- + +init([]) -> + mnesia:create_schema([node()]), + mnesia:start(), + {ok, {}, 0}. + +handle_cast(a, State) -> + {noreply, State}. + +handle_call({getValue, Key},_From,State) -> + {reply,value_of_key_requested_goes_here, State}. + +handle_info(timeout, State) -> + {noreply, State}. + +terminate(_Reason, _State) -> + ok. + +code_change(_OldVsn, State, _Extra) -> + {ok, State}. + +%%----------------------------------------------------- +%% Internal functions +%%----------------------------------------------------- diff --git a/src/ggs_server.erl b/src/ggs_server.erl index d7be36e..566d354 100644 --- a/src/ggs_server.erl +++ b/src/ggs_server.erl @@ -109,6 +109,7 @@ do_JSCall(Socket, Data, State) -> {hello} -> Client = getRef(), send(Socket, Client, "__ok_hello"), + %gen_server:call(ggs_mnesia_controller_server, {hello, "Someone said hello!"}), {Client, JSVM}; {echo, RefID, _, MSG} -> send(Socket, RefID, "Your VM is ", getJSVM(RefID, State)), diff --git a/src/ggs_server_sup.erl b/src/ggs_server_sup.erl new file mode 100644 index 0000000..df665d6 --- /dev/null +++ b/src/ggs_server_sup.erl @@ -0,0 +1,41 @@ +-module(ggs_server_sup). +-behaviour(supervisor). + +%% API +-export([start/1, start_link/1]). + +%% Supervisor callbacks +-export([init/1]). +-define(SERVER, ?MODULE). + +start(Port) -> + [FirstArg] = Port, + {IntPort, _} = string:to_integer(FirstArg), + start_link(IntPort). + +start_link(Port) -> + supervisor:start_link({local, ?SERVER}, ?MODULE, [Port]). + +init([Port]) -> + GGSServer = {ggs_server, + {ggs_server, start_link, [Port]}, + permanent, + 2000, + worker, + [ggs_server] + }, + MnesiaServer = {ggs_mnesia_controller_server, + {ggs_mnesia_controller_server, start_link, []}, + permanent, + 2000, + worker, + [ggs_mnesia_controller_server] + }, + Children = [MnesiaServer, GGSServer], + + RestartStrategy = { one_for_one, % Restart only crashing child + 10, % Allow ten crashes per.. + 1 % 1 second, then crash supervisor. + }, + {ok, {RestartStrategy, Children}}. + diff --git a/src/ggs_sup.erl b/src/ggs_sup.erl index 0cc8335..ee6f8cd 100644 --- a/src/ggs_sup.erl +++ b/src/ggs_sup.erl @@ -17,12 +17,12 @@ start_link(Port) -> supervisor:start_link({local, ?SERVER}, ?MODULE, [Port]). init([Port]) -> - Server = {ggs_server, - {ggs_server, start_link, [Port]}, + Server = {ggs_server_sup, + {ggs_server_sup, start_link, [Port]}, permanent, 2000, worker, - [ggs_server] + [ggs_server_sup] }, Children = [Server], diff --git a/start b/start index f3720a5..37040d3 100755 --- a/start +++ b/start @@ -1,3 +1,3 @@ #!/usr/bin/env bash -erl -boot start_sasl -pa erlang_js/ebin/ -pa ebin -pa src -s start_ggs +erl -mnesia -boot start_sasl -pa erlang_js/ebin/ -pa ebin -pa src -s start_ggs From ae9034934e59f5b6a0e575ef82963977c702e1f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonatan=20P=C3=A5lsson?= Date: Wed, 2 Feb 2011 19:58:34 +0100 Subject: [PATCH 02/20] Added future handlers for Mnesia --- src/ggs_mnesia_controller_server.erl | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/ggs_mnesia_controller_server.erl b/src/ggs_mnesia_controller_server.erl index 0b384f1..c1f8a10 100644 --- a/src/ggs_mnesia_controller_server.erl +++ b/src/ggs_mnesia_controller_server.erl @@ -46,8 +46,13 @@ init([]) -> handle_cast(a, State) -> {noreply, State}. -handle_call({getValue, Key},_From,State) -> - {reply,value_of_key_requested_goes_here, State}. +% Request a value from the Mnesia database +handle_call({getValue, _Key},_From,State) -> + {reply,value_of_key_requested_goes_here, State}; + +% Set a value in the Mnesia database +handle_call({setValue, _Key, Value},_From,State) -> + {reply,value_set_or_updated, State}. handle_info(timeout, State) -> {noreply, State}. From f5fac06849e619b57d0d1e1c00abcc81e2cd176c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonatan=20P=C3=A5lsson?= Date: Wed, 2 Feb 2011 21:19:33 +0100 Subject: [PATCH 03/20] Started working on the new protocol --- python_client | 8 ++++- src/ggs_protocol.erl | 77 +++++++++++++++++++++++++++----------------- src/ggs_server.erl | 3 ++ 3 files changed, 58 insertions(+), 30 deletions(-) diff --git a/python_client b/python_client index 77574e6..4205c8c 100755 --- a/python_client +++ b/python_client @@ -8,7 +8,13 @@ HOST = 'localhost' # The remote host PORT = int(sys.argv[1]) # The same port as used by the server s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect((HOST, PORT)) -s.send('__hello 0') +s.send( +'Token: 1001\n\ +Command: define\n\ +Content-Type: text\n\ +Content-Length: 40\n\ +\n\ +function helloWorld(x) {return x + 2 ;}') fs = s.makefile() data = fs.readline() token = data.split(" ")[0] diff --git a/src/ggs_protocol.erl b/src/ggs_protocol.erl index c470beb..48144c2 100644 --- a/src/ggs_protocol.erl +++ b/src/ggs_protocol.erl @@ -5,32 +5,51 @@ -export([parse/1]). parse(Data) -> - Message = string:tokens(Data, " "), - io:format(Message), - case Message of - ["__get_vms"] -> - {vms}; - [RefID, "__error", Size, Message ] -> - {ok, you_said_error}; - [_, "__boot", _ ] -> - {ok, you_said_boot}; - [RefID, "__stop", _] -> - {ok, you_said_stop}; - [RefID, "__start", _] -> - {ok, you_said_start}; - ["__hello", _] -> - {hello}; - [RefID, "__define",_, JavaScript ] -> - {ok, you_said_define}; - [RefID, "__echo", Length, Msg ] -> - {Ref, _} = string:to_integer(RefID), - {echo, Ref, Length, Msg}; - [RefID, Command, _, Parameter ] -> - {cmd, Command, Parameter}; - %% Debugging tools, not for production use - ["__crash"] -> - {crash, 0}; - %% End debugging tools - Other -> - {out_of_bounds, Other} - end. + Message =string:tokens(Data, "\n"), + % Turn "A: B" pairs into "{A, B}" tuples, for searching. + MsgKV = lists:map((fun(Str) -> + list_to_tuple(string:tokens(Str, ": ")) end + ), Message), + % Hacky way to build a tuple, filter out not_found later on + Processed = { + case lists:keysearch("Token", 1, MsgKV) of + {value,{_, Value}} -> + Value; + false -> + not_found + end, + case lists:keysearch("Command", 1, MsgKV) of + {value,{_, "define"}} -> + define; + false -> + not_found + end + }, + Processed. +% case Message of +% ["__get_vms"] -> +% {vms}; +% [RefID, "__error", Size, Message ] -> +% {ok, you_said_error}; +% [_, "__boot", _ ] -> +% {ok, you_said_boot}; +% [RefID, "__stop", _] -> +% {ok, you_said_stop}; +% [RefID, "__start", _] -> +% {ok, you_said_start}; +% ["__hello", _] -> +% {hello}; +% [RefID, "__define",_, JavaScript ] -> +% {ok, you_said_define}; +% [RefID, "__echo", Length, Msg ] -> +% {Ref, _} = string:to_integer(RefID), +% {echo, Ref, Length, Msg}; +% [RefID, Command, _, Parameter ] -> +% {cmd, Command, Parameter}; +% %% Debugging tools, not for production use +% ["__crash"] -> +% {crash, 0}; +% %% End debugging tools +% Other -> +% {out_of_bounds, Other} +% end. diff --git a/src/ggs_server.erl b/src/ggs_server.erl index 566d354..6c76a9d 100644 --- a/src/ggs_server.erl +++ b/src/ggs_server.erl @@ -98,6 +98,9 @@ do_JSCall(Socket, Data, State) -> js_runner:define(JSVM, "function userCommand(cmd, par) {return cmd+' '+ par}"), Parsed = ggs_protocol:parse(Data), NewState = case Parsed of + {Token, define} -> + io:format("Got define!!\n"), + []; {cmd, Command, Parameter} -> % Set the new state to [] Ret = js_runner:call(JSVM, "userCommand", From 4c6d0987bdae9dbe6a3d15d5c0b98e002feb2de8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonatan=20P=C3=A5lsson?= Date: Fri, 4 Feb 2011 19:09:41 +0100 Subject: [PATCH 04/20] Now we can define and run functions, but not in the same JSVM at the moment. A lookup is needed --- python_client | 26 ++++++++++++++++++++------ src/ggs_protocol.erl | 18 +++++++++++++++--- src/ggs_server.erl | 28 ++++++++++++++-------------- 3 files changed, 49 insertions(+), 23 deletions(-) diff --git a/python_client b/python_client index 4205c8c..34d5be0 100755 --- a/python_client +++ b/python_client @@ -8,21 +8,35 @@ HOST = 'localhost' # The remote host PORT = int(sys.argv[1]) # The same port as used by the server s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect((HOST, PORT)) + +# Define ourselves a function! + s.send( -'Token: 1001\n\ +"Token: 1001\n\ Command: define\n\ Content-Type: text\n\ -Content-Length: 40\n\ +Content-Length: 42\n\ \n\ -function helloWorld(x) {return x + 2 ;}') +function myFun() {return 'Hello world!' ;}") fs = s.makefile() data = fs.readline() token = data.split(" ")[0] print "Token:", token +print "Data: ", ' '.join(data.split(" ")[1:]) -s.send(token+" __echo 0 msg") -data = s.recv(1024) -print data +# Call that function! +s.send( +"Token: 1001\n\ +Command: call\n\ +Content-Type: text\n\ +Content-Length: 6\n\ +\n\ +myFun()") +fs = s.makefile() +data = fs.readline() +token = data.split(" ")[0] +print "Token:", token +print "Data: ", ' '.join(data.split(" ")[1:]) s.close() diff --git a/src/ggs_protocol.erl b/src/ggs_protocol.erl index 48144c2..ec4ed09 100644 --- a/src/ggs_protocol.erl +++ b/src/ggs_protocol.erl @@ -12,15 +12,27 @@ parse(Data) -> ), Message), % Hacky way to build a tuple, filter out not_found later on Processed = { + case lists:keysearch("Command", 1, MsgKV) of + {value,{_, "define"}} -> + define; + {value,{_, "call"}} -> + call; + false -> + not_found + end, case lists:keysearch("Token", 1, MsgKV) of {value,{_, Value}} -> Value; false -> not_found end, - case lists:keysearch("Command", 1, MsgKV) of - {value,{_, "define"}} -> - define; + case lists:keysearch("Content-Length", 1, MsgKV) of + {value,{_, Value}} -> + {Length, _} = string:to_integer(Value), + [_|Cont] = re:split(Data, "\n\n",[{return,list}]), + Content = string:join(Cont, "\n\n"), + Payload = string:substr(Content,1,Length), + Payload; false -> not_found end diff --git a/src/ggs_server.erl b/src/ggs_server.erl index 6c76a9d..819fdf0 100644 --- a/src/ggs_server.erl +++ b/src/ggs_server.erl @@ -79,6 +79,9 @@ 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) -> + {stop, "Client closed socket", State}; + handle_info(timeout, #state{lsock = LSock} = State) -> {ok, _Sock} = gen_tcp:accept(LSock), {noreply, State}. @@ -95,19 +98,16 @@ code_change(_OldVsn, State, _Extra) -> do_JSCall(Socket, Data, State) -> JSVM = js_runner:boot(), - js_runner:define(JSVM, "function userCommand(cmd, par) {return cmd+' '+ par}"), Parsed = ggs_protocol:parse(Data), NewState = case Parsed of - {Token, define} -> - io:format("Got define!!\n"), - []; - {cmd, Command, Parameter} -> - % Set the new state to [] - Ret = js_runner:call(JSVM, "userCommand", - [list_to_binary(Command), - list_to_binary(Parameter)]), - send(Socket, "RefID", "JS says: ", Ret), + {define, Token, Payload} -> + js_runner:define(JSVM, Payload), + send(Socket, "RefID", "Okay, defined that for you!"), []; + {call, Token, Payload} -> + Ret = js_runner:call(JSVM, Payload, []),%Payload, []), + send(Socket, "RefID", "JS says: ", Ret); + % Set the new state to the reference generated, and JSVM associated {hello} -> Client = getRef(), @@ -120,11 +120,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. From 40fdb8b4319bffcb765733813a408f42f8e28331 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonatan=20P=C3=A5lsson?= Date: Fri, 4 Feb 2011 19:52:43 +0100 Subject: [PATCH 05/20] Now we can call the defined code (lookup performed) --- python_client | 27 +++++++++++++++++++++------ src/ggs_protocol.erl | 2 ++ src/ggs_server.erl | 19 ++++++++++++------- 3 files changed, 35 insertions(+), 13 deletions(-) diff --git a/python_client b/python_client index 34d5be0..f8c5496 100755 --- a/python_client +++ b/python_client @@ -9,33 +9,48 @@ PORT = int(sys.argv[1]) # The same port as used by the server s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect((HOST, PORT)) +# Say hello + +print "Saying hello to server" +s.send( +"Command: hello\n\ +Content-Type: text\n\ +Content-Length: 0\n\ +\n\ +") +fs = s.makefile() +data = fs.readline() +token = data.split(" ")[0] +print "Token:", token +print "Data: ", ' '.join(data.split(" ")[1:]) + # Define ourselves a function! +print "Defining a function called myFun" s.send( -"Token: 1001\n\ +"Token: %s\n\ Command: define\n\ Content-Type: text\n\ Content-Length: 42\n\ \n\ -function myFun() {return 'Hello world!' ;}") +function myFun() {return 'Hello world!' ;}" % token) fs = s.makefile() data = fs.readline() -token = data.split(" ")[0] print "Token:", token print "Data: ", ' '.join(data.split(" ")[1:]) # Call that function! +print "Calling myFun" s.send( -"Token: 1001\n\ +"Token: %s\n\ Command: call\n\ Content-Type: text\n\ Content-Length: 6\n\ \n\ -myFun()") +myFun" % token) fs = s.makefile() data = fs.readline() -token = data.split(" ")[0] print "Token:", token print "Data: ", ' '.join(data.split(" ")[1:]) s.close() diff --git a/src/ggs_protocol.erl b/src/ggs_protocol.erl index ec4ed09..4d65739 100644 --- a/src/ggs_protocol.erl +++ b/src/ggs_protocol.erl @@ -17,6 +17,8 @@ parse(Data) -> define; {value,{_, "call"}} -> call; + {value,{_, "hello"}} -> + hello; false -> not_found end, diff --git a/src/ggs_server.erl b/src/ggs_server.erl index 819fdf0..9e25d70 100644 --- a/src/ggs_server.erl +++ b/src/ggs_server.erl @@ -97,22 +97,23 @@ code_change(_OldVsn, State, _Extra) -> %%----------------------------------------------------- do_JSCall(Socket, Data, State) -> - JSVM = js_runner:boot(), Parsed = ggs_protocol:parse(Data), NewState = case Parsed of {define, Token, Payload} -> + JSVM = getJSVM(Token, State), js_runner:define(JSVM, Payload), send(Socket, "RefID", "Okay, defined that for you!"), []; {call, Token, Payload} -> + JSVM = getJSVM(Token, State), Ret = js_runner:call(JSVM, Payload, []),%Payload, []), send(Socket, "RefID", "JS says: ", Ret); % Set the new state to the reference generated, and JSVM associated - {hello} -> - Client = getRef(), - send(Socket, Client, "__ok_hello"), - %gen_server:call(ggs_mnesia_controller_server, {hello, "Someone said hello!"}), + {hello, _, _} -> + JSVM = js_runner:boot(), + Client = integer_to_list(getRef()), + send(Socket, Client, "This is your refID"), {Client, JSVM}; {echo, RefID, _, MSG} -> send(Socket, RefID, "Your VM is ", getJSVM(RefID, State)), @@ -138,11 +139,15 @@ getRef() -> getJSVM(RefID, State) -> VMs = State#state.client_vm_map, + erlang:display(RefID), + erlang:display(VMs), {value, {_,VM}} = lists:keysearch(RefID, 1, VMs), VM. send(Socket, RefID, String) -> - gen_tcp:send(Socket, io_lib:fwrite("~p ~p~n", [RefID,String])). + {Ref, _} = string:to_integer(RefID), + gen_tcp:send(Socket, io_lib:fwrite("~p ~p~n", [Ref,String])). send(Socket, RefID, String1, String2) -> - gen_tcp:send(Socket, io_lib:fwrite("~p ~p ~p~n", [RefID, String1, String2])). + {Ref, _} = string:to_integer(RefID), + gen_tcp:send(Socket, io_lib:fwrite("~p ~p ~p~n", [Ref, String1, String2])). From adfc9b41dd3a70904d79ead54d3fa52301071fcb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonatan=20P=C3=A5lsson?= Date: Sat, 5 Feb 2011 00:53:49 +0100 Subject: [PATCH 06/20] Changed from random numbers to UUIDs in tokens --- src/ggs_server.erl | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/src/ggs_server.erl b/src/ggs_server.erl index 9e25d70..4226737 100644 --- a/src/ggs_server.erl +++ b/src/ggs_server.erl @@ -102,17 +102,17 @@ do_JSCall(Socket, Data, State) -> {define, Token, Payload} -> JSVM = getJSVM(Token, State), js_runner:define(JSVM, Payload), - send(Socket, "RefID", "Okay, defined that for you!"), + send(Socket, Token, "Okay, defined that for you!"), []; {call, Token, Payload} -> JSVM = getJSVM(Token, State), - Ret = js_runner:call(JSVM, Payload, []),%Payload, []), - send(Socket, "RefID", "JS says: ", Ret); + {ok, Ret} = js_runner:call(JSVM, Payload, []),%Payload, []), + send(Socket, Token, "JS says:", binary_to_list(Ret)); % Set the new state to the reference generated, and JSVM associated {hello, _, _} -> JSVM = js_runner:boot(), - Client = integer_to_list(getRef()), + Client = getRef(), send(Socket, Client, "This is your refID"), {Client, JSVM}; {echo, RefID, _, MSG} -> @@ -133,9 +133,10 @@ do_JSCall(Socket, Data, State) -> %% Helpers %%----------------------------------------------------- getRef() -> - {A1,A2,A3} = now(), - random:seed(A1, A2, A3), - random:uniform(1000). + %{A1,A2,A3} = now(), + %#random:seed(A1, A2, A3), + %random:uniform(1000). + string:strip(os:cmd("uuidgen"), right, $\n ). getJSVM(RefID, State) -> VMs = State#state.client_vm_map, @@ -145,9 +146,7 @@ getJSVM(RefID, State) -> VM. send(Socket, RefID, String) -> - {Ref, _} = string:to_integer(RefID), - gen_tcp:send(Socket, io_lib:fwrite("~p ~p~n", [Ref,String])). + gen_tcp:send(Socket, string:join([RefID,String,"\n"], " ")). send(Socket, RefID, String1, String2) -> - {Ref, _} = string:to_integer(RefID), - gen_tcp:send(Socket, io_lib:fwrite("~p ~p ~p~n", [Ref, String1, String2])). + gen_tcp:send(Socket, string:join([RefID,String1, String2,"\n"], " ")). From fcdba0912e18a4fbe64fd1d0464070aa2b04755e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonatan=20P=C3=A5lsson?= Date: Fri, 4 Feb 2011 15:58:24 -0800 Subject: [PATCH 07/20] --- HOWTO | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/HOWTO b/HOWTO index 035800e..ed98b03 100644 --- a/HOWTO +++ b/HOWTO @@ -12,7 +12,6 @@ INSTALL 12. USAGE -1. start a second terminal -2. telnet localhost 7000 -3. back to first terminal -4. ./start +./build +./start +./python_client 9000 From 79777e7b1c88c3ce073b8d00b511383ddcc1bf87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonatan=20P=C3=A5lsson?= Date: Sat, 5 Feb 2011 15:24:30 +0100 Subject: [PATCH 08/20] 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.. --- python_client | 22 +++++++++++++++---- src/ggs_backup.erl | 41 ++++++++++++++++++++++++++++++++++++ src/ggs_server.erl | 48 ++++++++++++++++++++++++++++++++---------- src/ggs_server_sup.erl | 9 +++++++- 4 files changed, 104 insertions(+), 16 deletions(-) create mode 100644 src/ggs_backup.erl diff --git a/python_client b/python_client index f8c5496..daa2a19 100755 --- a/python_client +++ b/python_client @@ -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() diff --git a/src/ggs_backup.erl b/src/ggs_backup.erl new file mode 100644 index 0000000..30c80a2 --- /dev/null +++ b/src/ggs_backup.erl @@ -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. diff --git a/src/ggs_server.erl b/src/ggs_server.erl index 4226737..2bd1aeb 100644 --- a/src/ggs_server.erl +++ b/src/ggs_server.erl @@ -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]) -> - {ok, LSock} = gen_tcp:listen(Port, [{active, true}, - {reuseaddr, true}]), - {ok, #state{port = Port, lsock = LSock}, 0}. + 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}; + {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. diff --git a/src/ggs_server_sup.erl b/src/ggs_server_sup.erl index df665d6..23d32f7 100644 --- a/src/ggs_server_sup.erl +++ b/src/ggs_server_sup.erl @@ -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.. From ebe5870d5717c28f81dce6aed47e4b3ebba3f44e Mon Sep 17 00:00:00 2001 From: Kallfaktorn Date: Sat, 5 Feb 2011 16:57:21 +0100 Subject: [PATCH 09/20] New installation notes. Conflicts: HOWTO --- HOWTO | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/HOWTO b/HOWTO index ed98b03..064d127 100644 --- a/HOWTO +++ b/HOWTO @@ -1,3 +1,6 @@ +PREREQUISITES: +python version 2.x set to default. + INSTALL 1. Cd into directory where you to have the project 2. git-clone git@github.com:jeena/GGS.git (remember to have a local key) @@ -6,12 +9,13 @@ INSTALL 5. git submodule update 6. cd erlang_js 7. make -8. make test (If not all tests are passed then you are screwed!) +8. make test (Optional. It has to work though.) 10. cd ../ 11. ./build 12. USAGE -./build -./start -./python_client 9000 +1. start a second terminal +2. in new terminal do command: ./python_client 9000 +3. back to first terminal +4. ./start From 7267781b6458bce588c8116496ccaf7513b0b285 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonatan=20P=C3=A5lsson?= Date: Sun, 6 Feb 2011 14:43:31 +0100 Subject: [PATCH 10/20] Starting erlang_js properly, and modified python_client tot start two sequential connections --- python_client | 5 +++++ src/ggs_server.erl | 5 +---- src/start_ggs.erl | 1 + start | 2 +- 4 files changed, 8 insertions(+), 5 deletions(-) diff --git a/python_client b/python_client index daa2a19..4dd82ae 100755 --- a/python_client +++ b/python_client @@ -52,7 +52,12 @@ data = fs.readline() print "Token:", token print "Data: ", ' '.join(data.split(" ")[1:]) +s.close() +HOST = 'localhost' # The remote host +PORT = int(sys.argv[1]) # The same port as used by the server +s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) +s.connect((HOST, PORT)) # Call that function! print "Calling myFun" diff --git a/src/ggs_server.erl b/src/ggs_server.erl index 2bd1aeb..dff29f3 100644 --- a/src/ggs_server.erl +++ b/src/ggs_server.erl @@ -36,10 +36,6 @@ start_link(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(?DEFAULT_PORT). @@ -125,6 +121,7 @@ do_JSCall(Socket, Data, State) -> {call, Token, Payload} -> io:format("Got call request: ~p~n", [Payload]), JSVM = getJSVM(Token, State), + erlang:display(erlang:port_info(JSVM)), {ok, Ret} = js_runner:call(JSVM, Payload, []),%Payload, []), send(Socket, Token, "JS says:", binary_to_list(Ret)); diff --git a/src/start_ggs.erl b/src/start_ggs.erl index eabdbc5..3955715 100644 --- a/src/start_ggs.erl +++ b/src/start_ggs.erl @@ -3,4 +3,5 @@ start() -> application:start(inets), + application:start(erlang_js), application:start(ggs). diff --git a/start b/start index 37040d3..6de5737 100755 --- a/start +++ b/start @@ -1,3 +1,3 @@ #!/usr/bin/env bash -erl -mnesia -boot start_sasl -pa erlang_js/ebin/ -pa ebin -pa src -s start_ggs +erl -sname ggs -mnesia -boot start_sasl -pa erlang_js/ebin/ -pa ebin -pa src -s start_ggs From e8c93893d297ea4d01f9abf7a06bf557fcb83caf Mon Sep 17 00:00:00 2001 From: Kallfaktorn Date: Sat, 5 Feb 2011 16:27:06 +0100 Subject: [PATCH 11/20] New installation notes. --- HOWTO | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/HOWTO b/HOWTO index 035800e..8fbba1f 100644 --- a/HOWTO +++ b/HOWTO @@ -1,3 +1,6 @@ +PREREQUISITES: +python version 2.x set to default. + INSTALL 1. Cd into directory where you to have the project 2. git-clone git@github.com:jeena/GGS.git (remember to have a local key) @@ -6,13 +9,13 @@ INSTALL 5. git submodule update 6. cd erlang_js 7. make -8. make test (If not all tests are passed then you are screwed!) +8. make test (Optional. It has to work though.) 10. cd ../ 11. ./build 12. USAGE 1. start a second terminal -2. telnet localhost 7000 +2. ./python_client 9000 3. back to first terminal 4. ./start From 01b7a7e4e1770b539f57e289106049e0580d3765 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonatan=20P=C3=A5lsson?= Date: Sun, 6 Feb 2011 17:59:34 +0100 Subject: [PATCH 12/20] Added our own erlang_js --- .gitignore | 3 +++ .gitmodules | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3f2a73f --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +*.swp +*.dump +*.beam diff --git a/.gitmodules b/.gitmodules index 2e9d3a7..989e33d 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,6 @@ [submodule "erlang_js"] path = erlang_js - url = https://github.com/basho/erlang_js.git + url = https://github.com/jonte/erlang_js.git [submodule "erlv8"] path = erlv8 url = https://github.com/beamjs/erlv8.git From fcc114a0879cb1c0f62d84aea6f3573e8b86f058 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonatan=20P=C3=A5lsson?= Date: Sun, 6 Feb 2011 18:28:23 +0100 Subject: [PATCH 13/20] Removed erlv8 --- .gitmodules | 3 --- erlv8 | 1 - 2 files changed, 4 deletions(-) delete mode 160000 erlv8 diff --git a/.gitmodules b/.gitmodules index 989e33d..4c56fac 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,3 @@ [submodule "erlang_js"] path = erlang_js url = https://github.com/jonte/erlang_js.git -[submodule "erlv8"] - path = erlv8 - url = https://github.com/beamjs/erlv8.git diff --git a/erlv8 b/erlv8 deleted file mode 160000 index 688e503..0000000 --- a/erlv8 +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 688e5036864eed01f7aefb6ee8b3a4c22961012f From 6166a109fc7b9c7bbb8a19f97dcc5c4259f63511 Mon Sep 17 00:00:00 2001 From: Jeena Paradies Date: Sun, 6 Feb 2011 19:17:08 +0100 Subject: [PATCH 14/20] added function to test callErlang() in js --- .gitignore | 1 + erlang_js | 2 +- python_client | 6 ++++-- start | 2 +- 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/.gitignore b/.gitignore index 3f2a73f..d176978 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ *.swp *.dump *.beam +Mnesia.* diff --git a/erlang_js b/erlang_js index 5350ed2..cbac148 160000 --- a/erlang_js +++ b/erlang_js @@ -1 +1 @@ -Subproject commit 5350ed21606606dbee5ecb07e974f2abb9106270 +Subproject commit cbac148c440a93db44bad767a43c6d8619f6871f diff --git a/python_client b/python_client index 4dd82ae..f79ff6e 100755 --- a/python_client +++ b/python_client @@ -29,9 +29,9 @@ s.send( "Token: %s\n\ Command: define\n\ Content-Type: text\n\ -Content-Length: 42\n\ +Content-Length: 49\n\ \n\ -function myFun() {return 'Hello world!' ;}" % token) +function myFun() {return callErlang('a', 'b') ;}" % token) fs = s.makefile() data = fs.readline() print "Token:", token @@ -54,6 +54,7 @@ print "Data: ", ' '.join(data.split(" ")[1:]) s.close() +""" HOST = 'localhost' # The remote host PORT = int(sys.argv[1]) # The same port as used by the server s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) @@ -74,3 +75,4 @@ print "Token:", token print "Data: ", ' '.join(data.split(" ")[1:]) s.close() +""" diff --git a/start b/start index 6de5737..7dd9673 100755 --- a/start +++ b/start @@ -1,3 +1,3 @@ #!/usr/bin/env bash -erl -sname ggs -mnesia -boot start_sasl -pa erlang_js/ebin/ -pa ebin -pa src -s start_ggs +erl -sname ggs -mnesia -boot start_sasl -pa erlang_js/ebin/ -pa ebin -pa src -s start_ggs -sname ggs From 6aad821279aa0da13539633922dd34d031318396 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonatan=20P=C3=A5lsson?= Date: Sun, 6 Feb 2011 22:32:08 +0100 Subject: [PATCH 15/20] Converted protocol -> ggs_server communication to OTP --- erlang_js | 2 +- src/ggs_protocol.erl | 32 +--------------- src/ggs_server.erl | 89 ++++++++++++++------------------------------ 3 files changed, 30 insertions(+), 93 deletions(-) diff --git a/erlang_js b/erlang_js index 5350ed2..cbac148 160000 --- a/erlang_js +++ b/erlang_js @@ -1 +1 @@ -Subproject commit 5350ed21606606dbee5ecb07e974f2abb9106270 +Subproject commit cbac148c440a93db44bad767a43c6d8619f6871f diff --git a/src/ggs_protocol.erl b/src/ggs_protocol.erl index 4d65739..ede5115 100644 --- a/src/ggs_protocol.erl +++ b/src/ggs_protocol.erl @@ -1,6 +1,3 @@ -%% This is a parser for JSON implemented using mochijson2 -%% Don't feed it anything other than valid JSON. - -module(ggs_protocol). -export([parse/1]). @@ -39,31 +36,4 @@ parse(Data) -> not_found end }, - Processed. -% case Message of -% ["__get_vms"] -> -% {vms}; -% [RefID, "__error", Size, Message ] -> -% {ok, you_said_error}; -% [_, "__boot", _ ] -> -% {ok, you_said_boot}; -% [RefID, "__stop", _] -> -% {ok, you_said_stop}; -% [RefID, "__start", _] -> -% {ok, you_said_start}; -% ["__hello", _] -> -% {hello}; -% [RefID, "__define",_, JavaScript ] -> -% {ok, you_said_define}; -% [RefID, "__echo", Length, Msg ] -> -% {Ref, _} = string:to_integer(RefID), -% {echo, Ref, Length, Msg}; -% [RefID, Command, _, Parameter ] -> -% {cmd, Command, Parameter}; -% %% Debugging tools, not for production use -% ["__crash"] -> -% {crash, 0}; -% %% End debugging tools -% Other -> -% {out_of_bounds, Other} -% end. + gen_server:cast(ggs_server, Processed). diff --git a/src/ggs_server.erl b/src/ggs_server.erl index dff29f3..68b1625 100644 --- a/src/ggs_server.erl +++ b/src/ggs_server.erl @@ -11,7 +11,6 @@ %% API -export([start_link/1, start_link/0, - get_count/0, stop/0 ]). @@ -39,16 +38,6 @@ start_link(Port) -> start_link() -> start_link(?DEFAULT_PORT). -%%----------------------------------------------------- -%% @doc Fetches the number of requests made to this server -%% @spec get_count() -> {ok, Count} -%% where -%% Count = integer() -%% @end -%%----------------------------------------------------- -get_count() -> - gen_server:call(?SERVER, get_count). - %%----------------------------------------------------- %% @doc Stops the server. %% @spec stop() -> ok @@ -73,21 +62,14 @@ init([Port]) -> {ok, State#state{lsock = LSock}, 0} end. -handle_call(get_count, _From, 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}. handle_info({tcp, Socket, RawData}, State) -> - NewState = do_JSCall(Socket, RawData, State), - OldMap = State#state.client_vm_map, - io:format("Old map: ~p NewState: ~p~n", [OldMap, NewState]), - {noreply, State#state{client_vm_map = OldMap ++ [NewState]}}; + ggs_protocol:parse(RawData), + {noreply, State#state{lsock = Socket}}; handle_info({tcp_closed, Socket}, State) -> gen_tcp:close(Socket), @@ -109,49 +91,34 @@ code_change(_OldVsn, State, _Extra) -> %%----------------------------------------------------- %% Internal functions %%----------------------------------------------------- +handle_cast(stop, State) -> + {stop, normal, State}; -do_JSCall(Socket, Data, State) -> - Parsed = ggs_protocol:parse(Data), - NewState = case Parsed of - {define, Token, Payload} -> - JSVM = getJSVM(Token, State), - js_runner:define(JSVM, Payload), - send(Socket, Token, "Okay, defined that for you!"), - []; - {call, Token, Payload} -> - io:format("Got call request: ~p~n", [Payload]), - JSVM = getJSVM(Token, State), - erlang:display(erlang:port_info(JSVM)), - {ok, Ret} = js_runner:call(JSVM, Payload, []),%Payload, []), - send(Socket, Token, "JS says:", binary_to_list(Ret)); +% Handle javascript defines +handle_cast({define, Token, Payload}, State) -> + JSVM = getJSVM(Token, State), + js_runner:define(JSVM, Payload), + send(State#state.lsock, Token, "Okay, defined that for you!"), + {noreply, State}; + +% Handle javascript calls +handle_cast({call, Token, Payload}, State) -> + io:format("Got call request: ~p~n", [Payload]), + JSVM = getJSVM(Token, State), + erlang:display(erlang:port_info(JSVM)), + {ok, Ret} = js_runner:call(JSVM, Payload, []),%Payload, []), + send(State#state.lsock, Token, "JS says:", binary_to_list(Ret)), + {noreply, State}; - % Set the new state to the reference generated, and JSVM associated - {hello, _, _} -> - 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)), - []; - {crash, Zero} -> - 10/Zero; - {vms} -> - send(Socket, "RefID", State); - % Set the new state to [] - Other -> - send(Socket, "RefID", "__error"), - [] - end, - % Return the new state - NewState. +% Set the new state to the reference generated, and JSVM associated +handle_cast({hello, _, _}, State) -> + JSVM = js_runner:boot(), + Client = getRef(), + send(State#state.lsock, Client, "This is your refID"), + OldMap = State#state.client_vm_map, + NewState = State#state{client_vm_map = OldMap ++ [{Client, JSVM}]}, + gen_server:cast(ggs_backup, {set_backup, NewState}), + {noreply, NewState}. %%----------------------------------------------------- %% Helpers %%----------------------------------------------------- From c67bcc32e7452f1064330ca1db0bfe8ce37a45f2 Mon Sep 17 00:00:00 2001 From: Jeena Paradies Date: Mon, 7 Feb 2011 01:21:51 -0800 Subject: [PATCH 16/20] removed double -sname --- start | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) mode change 100755 => 100644 start diff --git a/start b/start old mode 100755 new mode 100644 index 7dd9673..6de5737 --- a/start +++ b/start @@ -1,3 +1,3 @@ #!/usr/bin/env bash -erl -sname ggs -mnesia -boot start_sasl -pa erlang_js/ebin/ -pa ebin -pa src -s start_ggs -sname ggs +erl -sname ggs -mnesia -boot start_sasl -pa erlang_js/ebin/ -pa ebin -pa src -s start_ggs From fa63ea104bf036e2bd822260b946593847e2ad9c Mon Sep 17 00:00:00 2001 From: Jeena Paradies Date: Fri, 11 Feb 2011 12:28:34 +0100 Subject: [PATCH 17/20] can't remember --- HOWTO | 2 +- build | 2 +- client | 17 +++++++++++++++++ erlang_js | 2 +- games/tic-tac-toe-js/index.html | 12 ++++++++++-- games/tic-tac-toe-js/proxy.rb | 0 python_client | 2 +- src/key_value_store.erl | 22 ++++++++++++++++++++++ start | 0 9 files changed, 53 insertions(+), 6 deletions(-) create mode 100644 client create mode 100644 games/tic-tac-toe-js/proxy.rb create mode 100644 src/key_value_store.erl mode change 100644 => 100755 start diff --git a/HOWTO b/HOWTO index 064d127..2d28ea8 100644 --- a/HOWTO +++ b/HOWTO @@ -3,7 +3,7 @@ python version 2.x set to default. INSTALL 1. Cd into directory where you to have the project -2. git-clone git@github.com:jeena/GGS.git (remember to have a local key) +2. git clone git@github.com:jeena/GGS.git (remember to have a local key) 3. cd GGS/ 4. git submodule init 5. git submodule update diff --git a/build b/build index d468113..a9c1c79 100755 --- a/build +++ b/build @@ -3,4 +3,4 @@ for i in `find src -name "*.erl"` do erlc -o ebin $i -done +done \ No newline at end of file diff --git a/client b/client new file mode 100644 index 0000000..dff11aa --- /dev/null +++ b/client @@ -0,0 +1,17 @@ +#!/usr/bin/env ruby -wKU + +require 'socket' # Sockets are in standard library + +hostname = 'localhost' +port = 7000 + +s = TCPSocket.open(hostname, port) + + + +s.print(q.chop) + +while line = s.gets # Read lines from the socket + puts "Got Echo: " + line.chop # And print with platform line terminator +end +s.close # Close the socket when done diff --git a/erlang_js b/erlang_js index cbac148..5350ed2 160000 --- a/erlang_js +++ b/erlang_js @@ -1 +1 @@ -Subproject commit cbac148c440a93db44bad767a43c6d8619f6871f +Subproject commit 5350ed21606606dbee5ecb07e974f2abb9106270 diff --git a/games/tic-tac-toe-js/index.html b/games/tic-tac-toe-js/index.html index 97d3c4f..5bdb286 100644 --- a/games/tic-tac-toe-js/index.html +++ b/games/tic-tac-toe-js/index.html @@ -12,8 +12,16 @@ function init() { GameServer.addGame(game_name, main()); - GameServer.addClient(game_name, new TicTacToeClient(frames.player1.document.getElementById("p1"), GameServer)); - GameServer.addClient(game_name, new TicTacToeClient(frames.player2.document.getElementById("p2"), GameServer)); + GameServer.addClient( + game_name, + new TicTacToeClient(frames.player1.document.getElementById("p1"), + GameServer + )); + GameServer.addClient( + game_name, + new TicTacToeClient(frames.player2.document.getElementById("p2"), + GameServer + )); } diff --git a/games/tic-tac-toe-js/proxy.rb b/games/tic-tac-toe-js/proxy.rb new file mode 100644 index 0000000..e69de29 diff --git a/python_client b/python_client index f79ff6e..9a1f1a9 100755 --- a/python_client +++ b/python_client @@ -31,7 +31,7 @@ Command: define\n\ Content-Type: text\n\ Content-Length: 49\n\ \n\ -function myFun() {return callErlang('a', 'b') ;}" % token) +function myFun() {return 'Hello World!' ;}" % token) fs = s.makefile() data = fs.readline() print "Token:", token diff --git a/src/key_value_store.erl b/src/key_value_store.erl new file mode 100644 index 0000000..70a2dc6 --- /dev/null +++ b/src/key_value_store.erl @@ -0,0 +1,22 @@ +-module(key_value_store). +-export(start/0,stop/0,set_item/2,get_item/1,get/1,length(0,clean/0). + +start() -> + spawn_link(fun() -> loop([]) end). + +stop() -> + self() ! {stop} + +loop(Touples) -> + receive -> + {set_item, Key, Value} -> + Touple = find(Touples, Key) + {stop} -> + {'EXIT', normal} + +find([], _) -> false; +find([{Key, _}|Tuples], Match) -> + case Key == Match of + true -> true; + false -> find(Tuples, Match) + end. \ No newline at end of file diff --git a/start b/start old mode 100644 new mode 100755 From 3ccef1e7114fc1bae4a6e8d7913f910932d5e115 Mon Sep 17 00:00:00 2001 From: Jeena Paradies Date: Fri, 11 Feb 2011 13:58:59 +0100 Subject: [PATCH 18/20] removed file --- src/key_value_store.erl | 22 ---------------------- 1 file changed, 22 deletions(-) delete mode 100644 src/key_value_store.erl diff --git a/src/key_value_store.erl b/src/key_value_store.erl deleted file mode 100644 index 70a2dc6..0000000 --- a/src/key_value_store.erl +++ /dev/null @@ -1,22 +0,0 @@ --module(key_value_store). --export(start/0,stop/0,set_item/2,get_item/1,get/1,length(0,clean/0). - -start() -> - spawn_link(fun() -> loop([]) end). - -stop() -> - self() ! {stop} - -loop(Touples) -> - receive -> - {set_item, Key, Value} -> - Touple = find(Touples, Key) - {stop} -> - {'EXIT', normal} - -find([], _) -> false; -find([{Key, _}|Tuples], Match) -> - case Key == Match of - true -> true; - false -> find(Tuples, Match) - end. \ No newline at end of file From 8c1fe0b4fdd4f380edf0d7be0dd479bbc10a819f Mon Sep 17 00:00:00 2001 From: Kallfaktorn Date: Sun, 13 Feb 2011 16:44:11 +0100 Subject: [PATCH 19/20] Port to process. --- src/ggs_server.erl | 4 ++-- src/js_runner.erl | 32 +++++++++++++++++++++++++++----- 2 files changed, 29 insertions(+), 7 deletions(-) diff --git a/src/ggs_server.erl b/src/ggs_server.erl index 68b1625..91ea620 100644 --- a/src/ggs_server.erl +++ b/src/ggs_server.erl @@ -106,13 +106,13 @@ handle_cast({call, Token, Payload}, State) -> io:format("Got call request: ~p~n", [Payload]), JSVM = getJSVM(Token, State), erlang:display(erlang:port_info(JSVM)), - {ok, Ret} = js_runner:call(JSVM, Payload, []),%Payload, []), + {ok, Ret} = js_runner:call(JSVM, Payload, []), send(State#state.lsock, Token, "JS says:", binary_to_list(Ret)), {noreply, State}; % Set the new state to the reference generated, and JSVM associated handle_cast({hello, _, _}, State) -> - JSVM = js_runner:boot(), + JSVM = js_runner:boot(), Client = getRef(), send(State#state.lsock, Client, "This is your refID"), OldMap = State#state.client_vm_map, diff --git a/src/js_runner.erl b/src/js_runner.erl index ca866c4..780bfe1 100644 --- a/src/js_runner.erl +++ b/src/js_runner.erl @@ -1,13 +1,35 @@ -module(js_runner). --export([define/2,call/3, boot/0]). +-export([boot/0,define/2,call/3]). -boot() -> +%Mattias +boot() -> erlang_js:start(), {ok, Port} = js_driver:new(), + PortPid = spawn(fun() -> + port_process(Port) end ), + register(port_pid, PortPid), Port. -define(Port, Data) -> - ok = js:define(Port, list_to_binary(Data)). + +port_process(Port) -> +receive + {get_port, From} -> + From!{ok,Port}, + port_process(Port); + {define,From, JSVM, Data} -> + ok = js:define(JSVM, list_to_binary(Data)), + From!{ok}, + port_process(Port); + {call, From, JSVM, Func, Params} -> + {ok,Ret} = js:call(JSVM, list_to_binary(Func), Params), + From!{ok,Ret}, + port_process(Port) +end. + +define(Port, Data) -> + port_pid!{define,self(),Port,Data}. + + call(Port, Func, Params) -> - js:call(Port, list_to_binary(Func), Params). + port_pid!{call, self(), Port, Func, Params}. From e945bb0d31676fc3f2ec1db38df898f28cb5c26a Mon Sep 17 00:00:00 2001 From: Kallfaktorn Date: Mon, 14 Feb 2011 15:09:01 +0100 Subject: [PATCH 20/20] From one port process to many. --- src/ggs_server.erl | 36 +++++++++++++++++++++++++----------- src/js_runner.erl | 26 ++++++++++++-------------- 2 files changed, 37 insertions(+), 25 deletions(-) diff --git a/src/ggs_server.erl b/src/ggs_server.erl index 91ea620..aae268e 100644 --- a/src/ggs_server.erl +++ b/src/ggs_server.erl @@ -97,28 +97,42 @@ handle_cast(stop, State) -> % Handle javascript defines handle_cast({define, Token, Payload}, State) -> JSVM = getJSVM(Token, State), - js_runner:define(JSVM, Payload), + %js_runner:define(JSVM, Payload), + JSVM!{define,self(),Payload}, send(State#state.lsock, Token, "Okay, defined that for you!"), {noreply, State}; % Handle javascript calls handle_cast({call, Token, Payload}, State) -> + io:format("test1~n"), io:format("Got call request: ~p~n", [Payload]), - JSVM = getJSVM(Token, State), - erlang:display(erlang:port_info(JSVM)), - {ok, Ret} = js_runner:call(JSVM, Payload, []), - send(State#state.lsock, Token, "JS says:", binary_to_list(Ret)), - {noreply, State}; - + io:format("test2~n"), + JSVM = getJSVM(Token, State), + JSVM!{get_port, self()}, + receive + {ok, Port} -> erlang:display(erlang:port_info(Port)), + io:format("test1~n") + end, + %erlang:display(erlang:port_info(Port)), + %{ok, Ret} = js_runner:call(JSVM, Payload, []), + JSVM!{call, self(), Payload, []}, + receive + {ok, Ret} -> + send(State#state.lsock, Token, "JS says:", binary_to_list(Ret)), + {noreply, State} + end; % Set the new state to the reference generated, and JSVM associated handle_cast({hello, _, _}, State) -> - JSVM = js_runner:boot(), + JSVM = js_runner:boot(), Client = getRef(), send(State#state.lsock, Client, "This is your refID"), OldMap = State#state.client_vm_map, - NewState = State#state{client_vm_map = OldMap ++ [{Client, JSVM}]}, - gen_server:cast(ggs_backup, {set_backup, NewState}), - {noreply, NewState}. + JSVM!{get_port, self()}, + receive + {ok, Port} -> NewState = State#state{client_vm_map = OldMap ++ [{Client, Port}]}, + gen_server:cast(ggs_backup, {set_backup, NewState}), + {noreply, NewState} + end. %%----------------------------------------------------- %% Helpers %%----------------------------------------------------- diff --git a/src/js_runner.erl b/src/js_runner.erl index 780bfe1..65511e9 100644 --- a/src/js_runner.erl +++ b/src/js_runner.erl @@ -1,14 +1,12 @@ -module(js_runner). --export([boot/0,define/2,call/3]). +-export([boot/0]). %Mattias boot() -> erlang_js:start(), {ok, Port} = js_driver:new(), - PortPid = spawn(fun() -> - port_process(Port) end ), - register(port_pid, PortPid), - Port. + PortPid = spawn(fun() -> port_process(Port) end ), + PortPid. port_process(Port) -> @@ -16,20 +14,20 @@ receive {get_port, From} -> From!{ok,Port}, port_process(Port); - {define,From, JSVM, Data} -> - ok = js:define(JSVM, list_to_binary(Data)), + {define, From, Data} -> + ok = js:define(From, list_to_binary(Data)), From!{ok}, port_process(Port); - {call, From, JSVM, Func, Params} -> - {ok,Ret} = js:call(JSVM, list_to_binary(Func), Params), + {call, From, Func, Params} -> + {ok,Ret} = js:call(From, list_to_binary(Func), Params), %Port unsure From!{ok,Ret}, port_process(Port) end. - -define(Port, Data) -> - port_pid!{define,self(),Port,Data}. +%These two babies will be ambigiuous +%define(Port, Data) -> +% port_pid!{define,self(),Port,Data}. -call(Port, Func, Params) -> - port_pid!{call, self(), Port, Func, Params}. +%call(Port, Func, Params) -> +% port_pid!{call, self(), Port, Func, Params}.