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