1 %%% Copyright (c) 2007- Facebook
2 %%% Distributed under the Thrift Software License
4 %%% See accompanying file LICENSE or visit the Thrift site at:
5 %%% http://developers.facebook.com/thrift/
7 %%%-------------------------------------------------------------------
10 %%%-------------------------------------------------------------------
11 -module(thrift_oop_server
).
13 -behaviour(gen_server
).
14 %%--------------------------------------------------------------------
16 %%--------------------------------------------------------------------
19 -include("thrift.hrl").
21 %%--------------------------------------------------------------------
23 %%--------------------------------------------------------------------
29 %%--------------------------------------------------------------------
30 %% gen_server callbacks
31 %%--------------------------------------------------------------------
32 -export([init
/1, handle_call
/3, handle_cast
/2, handle_info
/2, terminate
/2, code_change
/3]).
34 %%--------------------------------------------------------------------
36 %%--------------------------------------------------------------------
38 %%--------------------------------------------------------------------
40 %%--------------------------------------------------------------------
41 -define(SERVER
, ?MODULE
).
43 %%====================================================================
45 %%====================================================================
46 %%--------------------------------------------------------------------
47 %% @doc Starts the server.
48 %% @spec start_link() -> {ok, pid()} | {error, Reason}
50 %%--------------------------------------------------------------------
52 gen_server:start_link({local
, ?SERVER
}, ?MODULE
, [], []).
54 %%--------------------------------------------------------------------
55 %% @doc Stops the server.
58 %%--------------------------------------------------------------------
60 gen_server:cast(?SERVER
, stop
).
62 %%====================================================================
64 %%====================================================================
66 %%--------------------------------------------------------------------
68 %% Description: Initiates the server
69 %% Returns: {ok, State} |
70 %% {ok, State, Timeout} |
73 %%--------------------------------------------------------------------
75 init({Class
, Args
}) ->
76 process_flag(trap_exit
, true
),
78 State
= apply(Class
, new
, Args
),
79 ?
INFO("thrift ~p:new(~s) = ~s", [Class
, thrift_utils:unbrack(Args
), oop:inspect(State
)]),
82 E
-> {stop
, {new_failed
, E
}}
86 {stop
, invalid_params
}.
88 %%--------------------------------------------------------------------
89 %% Function: handle_call/3
90 %% Description: Handling call messages
91 %% Returns: {reply, Reply, State} |
92 %% {reply, Reply, State, Timeout} |
94 %% {noreply, State, Timeout} |
95 %% {stop, Reason, Reply, State} | (terminate/2 is called)
96 %% {stop, Reason, State} (terminate/2 is called)
97 %%--------------------------------------------------------------------
99 handle_call(Request
, From
, State
) ->
100 handle_either(call
, Request
, From
, State
).
102 %%--------------------------------------------------------------------
103 %% Function: handle_cast/2
104 %% Description: Handling cast messages
105 %% Returns: {noreply, State} |
106 %% {noreply, State, Timeout} |
107 %% {stop, Reason, State} (terminate/2 is called)
108 %%--------------------------------------------------------------------
110 handle_cast(stop
, State
) ->
111 {stop
, normal
, State
};
113 handle_cast({Method
, Args
}, State
) ->
114 handle_either(cast
, {Method
, Args
}, undefined
, State
).
116 -define(REPLY(Value
, State
),
118 call
-> {reply
, Value
, State
};
119 cast
-> {noreply
, State
}
123 handle_either(Type
, Request
, From
, State
) ->
124 %% error_logger:info_msg("~p: ~p", [?SERVER, oop:inspect(State)]),
125 %% error_logger:info_msg("handle_call(Request=~p, From=~p, State)", [Request, From]),
129 Value
= oop:get(State
, Field
),
130 ?
REPLY(Value
, State
);
132 {set
, [Field
, Value
]} ->
133 State1
= oop:set(State
, Field
, Value
),
134 ?
REPLY(Value
, State1
);
137 ?
REPLY(?
CLASS(State
), State
);
140 handle_method(Type
, State
, Method
, Args
);
143 error_logger:format("no match for Request = ~p", [Request
]),
144 %% {stop, server_error, State}
145 {reply
, server_error
, State
}
148 handle_method(Type
, State
, Method
, Args
) ->
149 %% is an effectful call?
150 Is_effectful
= lists:prefix("effectful_", atom_to_list(Method
)),
151 Call
= oop:call(State
, Method
, Args
),
153 %% TODO(cpiro): maybe add error handling here? = catch oop:call?
155 case {Is_effectful
, Call
} of
156 {true
, {Retval
, State1
}} ->
157 ?
REPLY(Retval
, State1
);
159 {true
, _MalformedReturn
} ->
160 %% TODO(cpiro): bad match -- remove when we're done converting
161 error_logger:format("oop:call(effectful_*,..,..) malformed return value ~p",
163 %% {stop, server_error, State}
167 ?
REPLY(Retval
, State
)
170 %%--------------------------------------------------------------------
171 %% Function: handle_info/2
172 %% Description: Handling all non call/cast messages
173 %% Returns: {noreply, State} |
174 %% {noreply, State, Timeout} |
175 %% {stop, Reason, State} (terminate/2 is called)
176 %%--------------------------------------------------------------------
177 handle_info({'EXIT', Pid
, Except
} = All
, State
) ->
179 oop:call(State
, catches
, [Pid
, Except
])
181 exit:{missing_method
, _
} ->
187 error_logger:format("unhandled exit ~p", [All
]),
193 handle_info(Info
, State
) ->
194 error_logger:info_msg("~p", [Info
]),
197 %%--------------------------------------------------------------------
198 %% Function: terminate/2
199 %% Description: Shutdown the server
200 %% Returns: any (ignored by gen_server)
201 %%--------------------------------------------------------------------
202 terminate(Reason
, State
) ->
203 %%error_logger:format("~p terminated!: ~p", [self(), Reason]),
206 %%--------------------------------------------------------------------
207 %% Func: code_change/3
208 %% Purpose: Convert process state when code is changed
209 %% Returns: {ok, NewState}
210 %%--------------------------------------------------------------------
211 code_change(OldVsn
, State
, Extra
) ->
214 %%====================================================================
215 %%% Internal functions
216 %%====================================================================