/node/apps/mzbench/src/mzb_interconnect_server.erl

https://github.com/machinezone/mzbench · Erlang · 93 lines · 69 code · 22 blank · 2 comment · 0 complexity · 34d6a2a8f39ec3074ff30b251bc7a380 MD5 · raw file

  1. -module(mzb_interconnect_server).
  2. -behaviour(ranch_protocol).
  3. -behaviour(gen_server).
  4. %% API
  5. -export([start_link/4]).
  6. %% gen_server
  7. -export([init/1,
  8. init/4,
  9. handle_call/3,
  10. handle_cast/2,
  11. handle_info/2,
  12. terminate/2,
  13. code_change/3]).
  14. -record(state, {
  15. socket,
  16. transport,
  17. init_timer
  18. }).
  19. -define(INIT_WAIT_MSEC, 5000).
  20. start_link(Ref, Socket, Transport, Opts) ->
  21. proc_lib:start_link(?MODULE, init, [Ref, Socket, Transport, Opts]).
  22. init([State]) -> {ok, State}.
  23. init(Ref, Socket, Transport, _Opts) ->
  24. ok = proc_lib:init_ack({ok, self()}),
  25. ok = ranch:accept_ack(Ref),
  26. ok = Transport:setopts(Socket, [{active, once}, {packet, 4}, {keepalive, true}, binary]),
  27. Timer = erlang:send_after(?INIT_WAIT_MSEC, self(), init_timer_expired),
  28. gen_server:enter_loop(?MODULE, [], #state{socket=Socket, transport=Transport, init_timer = Timer}).
  29. dispatch({init, NodeName, Role}, #state{socket = Socket, transport = Transport, init_timer = Timer} = State) ->
  30. system_log:info("Received init from ~p ~p", [Role, NodeName]),
  31. Sender = fun (Msg) -> send(Transport, Socket, Msg) end,
  32. case mzb_interconnect:accept_connection(NodeName, Role, self(), Sender) of
  33. {ok, MyRole} ->
  34. erlang:cancel_timer(Timer),
  35. send(Transport, Socket, {init, node(), MyRole}),
  36. {noreply, State#state{init_timer = undefined}};
  37. {error, _} ->
  38. Transport:close(Socket),
  39. {stop, normal, State}
  40. end;
  41. dispatch(Msg, State) ->
  42. mzb_interconnect:handle(Msg),
  43. {noreply, State}.
  44. handle_info(init_timer_expired, #state{socket = Socket, transport = Transport} = State) ->
  45. Transport:close(Socket),
  46. {stop, normal, State};
  47. handle_info({tcp_closed, _Socket}, State) ->
  48. {stop, normal, State};
  49. handle_info(timeout, State) ->
  50. {stop, normal, State};
  51. handle_info({tcp, Socket, Msg}, State = #state{socket = Socket}) ->
  52. inet:setopts(Socket, [{active,once}]),
  53. dispatch(erlang:binary_to_term(Msg), State);
  54. handle_info({tcp_error, _, Reason}, State) ->
  55. system_log:warning("~p was closed with reason: ~p", [?MODULE, Reason]),
  56. {stop, Reason, State};
  57. handle_info(Info, State) ->
  58. system_log:error("~p has received unexpected info: ~p", [?MODULE, Info]),
  59. {stop, normal, State}.
  60. handle_cast(Msg, State) ->
  61. system_log:error("~p has received unexpected cast: ~p", [?MODULE, Msg]),
  62. {noreply, State}.
  63. handle_call(Request, _From, State) ->
  64. system_log:error("~p has received unexpected call: ~p", [?MODULE, Request]),
  65. {reply, ignore, State}.
  66. terminate(_Reason, #state{} = _State) ->
  67. ok.
  68. code_change(_OldVsn, State, _Extra) ->
  69. {ok, State}.
  70. send(Transport, Socket, Msg) ->
  71. Transport:send(Socket, erlang:term_to_binary(Msg)).