blob: 10ac2b2536c4578275987081c298ed24570851ab [file] [log] [blame]
Christopher Piro094823a2007-07-18 00:26:12 +00001%%% Copyright (c) 2007- Facebook
2%%% Distributed under the Thrift Software License
Christopher Pirode11d852007-11-18 02:10:20 +00003%%%
Christopher Piro094823a2007-07-18 00:26:12 +00004%%% See accompanying file LICENSE or visit the Thrift site at:
5%%% http://developers.facebook.com/thrift/
6
7-module(tErlServer).
8
9-include("oop.hrl").
10
11-include("thrift.hrl").
12-include("transport/tTransportException.hrl").
13-include("server/tErlServer.hrl").
14
15-behavior(oop).
16
17-export([attr/4, super/0, inspect/1]).
18
Christopher Pirode11d852007-11-18 02:10:20 +000019-export([new/6, new/5, new/4, effectful_serve/1, effectful_new_acceptor/1]).
Christopher Piro094823a2007-07-18 00:26:12 +000020
21%%%
22%%% define attributes
23%%% 'super' is required unless ?MODULE is a base class
24%%%
25
26?DEFINE_ATTR(super);
27?DEFINE_ATTR(acceptor);
28?DEFINE_ATTR(listenSocket);
29?DEFINE_ATTR(port).
Christopher Pirode11d852007-11-18 02:10:20 +000030
Christopher Piro094823a2007-07-18 00:26:12 +000031%%%
32%%% behavior callbacks
33%%%
Christopher Pirode11d852007-11-18 02:10:20 +000034
Christopher Piro094823a2007-07-18 00:26:12 +000035%%% super() -> SuperModule = atom()
36%%% | none
37
38super() ->
39 tServer.
40
41%%% inspect(This) -> string()
42
43inspect(This) ->
44 ?FORMAT_ATTR(acceptor) ++ ", " ++
45 ?FORMAT_ATTR(listenSocket) ++ ", " ++
46 ?FORMAT_ATTR(port).
47
48%%%
49%%% class methods
50%%%
51
52new(Port, Handler, Processor, ServerTransport, TransportFactory, ProtocolFactory) ->
53 Super = (super()):new(Handler, Processor, ServerTransport, TransportFactory, ProtocolFactory),
54 #?MODULE{super=Super, port=Port, listenSocket=nil, acceptor=nil}.
55
56new(Port, Handler, Processor, ServerTransport) ->
57 new(Port, Handler, Processor, ServerTransport, nil, nil).
58
59new(Port, Handler, Processor, ServerTransport, TransportFactory) ->
60 new(Port, Handler, Processor, ServerTransport, TransportFactory, nil).
61
62% listenSocket, acceptor, port
63
64effectful_serve(This) ->
65 Port = oop:get(This, port),
66
67 Options = [binary, {packet, 0}, {active, false}],
68
69 %% listen
Christopher Pirode11d852007-11-18 02:10:20 +000070 case gen_tcp:listen(Port, Options) of
71 {ok, ListenSocket} ->
72 ?INFO("thrift server listening on port ~p", [Port]),
Christopher Piro094823a2007-07-18 00:26:12 +000073
Christopher Pirode11d852007-11-18 02:10:20 +000074 This1 = oop:set(This, listenSocket, ListenSocket),
Christopher Piro094823a2007-07-18 00:26:12 +000075
Christopher Pirode11d852007-11-18 02:10:20 +000076 %% spawn acceptor
77 {_Acceptor, This2} = effectful_new_acceptor(This1),
Christopher Piro094823a2007-07-18 00:26:12 +000078
Christopher Pirode11d852007-11-18 02:10:20 +000079 {ok, This2};
Christopher Piro5b3a8f72007-08-01 22:27:37 +000080
Christopher Pirode11d852007-11-18 02:10:20 +000081 {error, eaddrinuse} ->
82 ?ERROR("thrift couldn't bind port ~p, address in use", [Port]),
83 {{error, eaddrinuse}, This} %% state before the accept
Christopher Piro094823a2007-07-18 00:26:12 +000084 end.
85
86effectful_new_acceptor(This) ->
87 ListenSocket = oop:get(This, listenSocket),
88 Processor = oop:get(This, processor), %% cpiro: generated processor, not the "actual" processor
89 Handler = oop:get(This, handler),
90
91 TF = oop:get(This, transportFactory),
92 PF = oop:get(This, protocolFactory),
93
94 tErlAcceptor = oop:get(This, serverTransport), %% cpiro: only supported ServerTransport
95
96 ServerPid = self(),
97 Acceptor = oop:start_new(tErlAcceptor, [ServerPid, TF, PF]),
98 ?C3(Acceptor, accept, ListenSocket, Processor, Handler),
99
100 This1 = oop:set(This, acceptor, Acceptor),
101
102 {Acceptor, This1}.