David Reiss | ac54955 | 2008-06-10 22:56:59 +0000 | [diff] [blame] | 1 | %%%------------------------------------------------------------------- |
| 2 | %%% File : thrift_server.erl |
| 3 | %%% Author : <todd@lipcon.org> |
| 4 | %%% Description : |
| 5 | %%% |
| 6 | %%% Created : 28 Jan 2008 by <todd@lipcon.org> |
| 7 | %%%------------------------------------------------------------------- |
| 8 | -module(thrift_server). |
| 9 | |
| 10 | -behaviour(gen_server). |
| 11 | |
| 12 | %% API |
| 13 | -export([start_link/3]). |
| 14 | |
| 15 | %% gen_server callbacks |
| 16 | -export([init/1, handle_call/3, handle_cast/2, handle_info/2, |
| 17 | terminate/2, code_change/3]). |
| 18 | |
| 19 | -define(SERVER, ?MODULE). |
| 20 | |
| 21 | -record(state, {listen_socket, acceptor, service}). |
David Reiss | ac54955 | 2008-06-10 22:56:59 +0000 | [diff] [blame] | 22 | |
| 23 | %%==================================================================== |
| 24 | %% API |
| 25 | %%==================================================================== |
| 26 | %%-------------------------------------------------------------------- |
| 27 | %% Function: start_link() -> {ok,Pid} | ignore | {error,Error} |
| 28 | %% Description: Starts the server |
| 29 | %%-------------------------------------------------------------------- |
| 30 | start_link(Port, Service, HandlerModule) when is_integer(Port), is_atom(HandlerModule) -> |
| 31 | gen_server:start_link({local, ?SERVER}, ?MODULE, {Port, Service, HandlerModule}, []). |
| 32 | |
| 33 | %%==================================================================== |
| 34 | %% gen_server callbacks |
| 35 | %%==================================================================== |
| 36 | |
| 37 | %%-------------------------------------------------------------------- |
| 38 | %% Function: init(Args) -> {ok, State} | |
| 39 | %% {ok, State, Timeout} | |
| 40 | %% ignore | |
| 41 | %% {stop, Reason} |
| 42 | %% Description: Initiates the server |
| 43 | %%-------------------------------------------------------------------- |
David Reiss | 1c1ca74 | 2008-06-10 22:57:21 +0000 | [diff] [blame^] | 44 | init({Port, Service, Handler}) -> |
David Reiss | ac54955 | 2008-06-10 22:56:59 +0000 | [diff] [blame] | 45 | {ok, Socket} = gen_tcp:listen(Port, |
| 46 | [binary, |
| 47 | {packet, 0}, |
| 48 | {active, false}, |
| 49 | {nodelay, true}, |
| 50 | {reuseaddr, true}]), |
| 51 | Acceptor = spawn_link(fun () -> acceptor(Socket, Service, Handler) end), |
| 52 | {ok, #state{listen_socket = Socket, |
| 53 | acceptor = Acceptor, |
| 54 | service = Service}}. |
| 55 | |
| 56 | %%-------------------------------------------------------------------- |
| 57 | %% Function: %% handle_call(Request, From, State) -> {reply, Reply, State} | |
| 58 | %% {reply, Reply, State, Timeout} | |
| 59 | %% {noreply, State} | |
| 60 | %% {noreply, State, Timeout} | |
| 61 | %% {stop, Reason, Reply, State} | |
| 62 | %% {stop, Reason, State} |
| 63 | %% Description: Handling call messages |
| 64 | %%-------------------------------------------------------------------- |
| 65 | handle_call(_Request, _From, State) -> |
| 66 | Reply = ok, |
| 67 | {reply, Reply, State}. |
| 68 | |
| 69 | %%-------------------------------------------------------------------- |
| 70 | %% Function: handle_cast(Msg, State) -> {noreply, State} | |
| 71 | %% {noreply, State, Timeout} | |
| 72 | %% {stop, Reason, State} |
| 73 | %% Description: Handling cast messages |
| 74 | %%-------------------------------------------------------------------- |
| 75 | handle_cast(_Msg, State) -> |
| 76 | {noreply, State}. |
| 77 | |
| 78 | %%-------------------------------------------------------------------- |
| 79 | %% Function: handle_info(Info, State) -> {noreply, State} | |
| 80 | %% {noreply, State, Timeout} | |
| 81 | %% {stop, Reason, State} |
| 82 | %% Description: Handling all non call/cast messages |
| 83 | %%-------------------------------------------------------------------- |
| 84 | handle_info(_Info, State) -> |
| 85 | {noreply, State}. |
| 86 | |
| 87 | %%-------------------------------------------------------------------- |
| 88 | %% Function: terminate(Reason, State) -> void() |
| 89 | %% Description: This function is called by a gen_server when it is about to |
| 90 | %% terminate. It should be the opposite of Module:init/1 and do any necessary |
| 91 | %% cleaning up. When it returns, the gen_server terminates with Reason. |
| 92 | %% The return value is ignored. |
| 93 | %%-------------------------------------------------------------------- |
| 94 | terminate(_Reason, _State) -> |
| 95 | ok. |
| 96 | |
| 97 | %%-------------------------------------------------------------------- |
| 98 | %% Func: code_change(OldVsn, State, Extra) -> {ok, NewState} |
| 99 | %% Description: Convert process state when code is changed |
| 100 | %%-------------------------------------------------------------------- |
| 101 | code_change(_OldVsn, State, _Extra) -> |
| 102 | State#state.acceptor ! refresh, |
| 103 | {ok, State}. |
| 104 | |
| 105 | %%-------------------------------------------------------------------- |
| 106 | %%% Internal functions |
| 107 | %%-------------------------------------------------------------------- |
| 108 | |
| 109 | acceptor(ListenSocket, Service, Handler) |
David Reiss | 1c1ca74 | 2008-06-10 22:57:21 +0000 | [diff] [blame^] | 110 | when is_port(ListenSocket), is_atom(Handler) -> |
David Reiss | ac54955 | 2008-06-10 22:56:59 +0000 | [diff] [blame] | 111 | {ok, Socket} = gen_tcp:accept(ListenSocket), |
| 112 | error_logger:info_msg("Accepted client"), |
| 113 | |
| 114 | {ok, Transport} = thrift_socket_transport:new(Socket), |
| 115 | {ok, Protocol} = thrift_binary_protocol:new(Transport), |
| 116 | |
| 117 | thrift_processor:start(Protocol, Protocol, Service, Handler), |
| 118 | receive |
| 119 | refresh -> |
| 120 | error_logger:info_msg("Acceptor refreshing~n"), |
| 121 | ?MODULE:acceptor(ListenSocket, Service, Handler) |
| 122 | after 0 -> acceptor(ListenSocket, Service, Handler) |
| 123 | end. |