blob: c21c434d3f24b40eb83b444651cdc77be8c39f1b [file] [log] [blame]
Christopher Piro094823a2007-07-18 00:26:12 +00001%%% Copyright (c) 2007- Facebook
2%%% Distributed under the Thrift Software License
3%%%
4%%% See accompanying file LICENSE or visit the Thrift site at:
5%%% http://developers.facebook.com/thrift/
6
7%%%-------------------------------------------------------------------
8%%% @doc
9%%% @end
10%%%-------------------------------------------------------------------
11-module(thrift_oop_server).
12
13-behaviour(gen_server).
14%%--------------------------------------------------------------------
15%% Include files
16%%--------------------------------------------------------------------
17-include("oop.hrl").
18
19-include("thrift.hrl").
20
21%%--------------------------------------------------------------------
22%% External exports
23%%--------------------------------------------------------------------
24-export([
25 start_link/0,
26 stop/0
27 ]).
28
29%%--------------------------------------------------------------------
30%% gen_server callbacks
31%%--------------------------------------------------------------------
32-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]).
33
34%%--------------------------------------------------------------------
35%% record definitions
36%%--------------------------------------------------------------------
37
38%%--------------------------------------------------------------------
39%% macro definitions
40%%--------------------------------------------------------------------
41-define(SERVER, ?MODULE).
42
43%%====================================================================
44%% External functions
45%%====================================================================
46%%--------------------------------------------------------------------
47%% @doc Starts the server.
48%% @spec start_link() -> {ok, pid()} | {error, Reason}
49%% @end
50%%--------------------------------------------------------------------
51start_link() ->
52 gen_server:start_link({local, ?SERVER}, ?MODULE, [], []).
53
54%%--------------------------------------------------------------------
55%% @doc Stops the server.
56%% @spec stop() -> ok
57%% @end
58%%--------------------------------------------------------------------
59stop() ->
60 gen_server:cast(?SERVER, stop).
61
62%%====================================================================
63%% Server functions
64%%====================================================================
65
66%%--------------------------------------------------------------------
67%% Function: init/1
68%% Description: Initiates the server
69%% Returns: {ok, State} |
70%% {ok, State, Timeout} |
71%% ignore |
72%% {stop, Reason}
73%%--------------------------------------------------------------------
74
Christopher Piro094823a2007-07-18 00:26:12 +000075init({Class, Args}) ->
76 process_flag(trap_exit, true),
Christopher Piro5b3a8f72007-08-01 22:27:37 +000077 try
78 State = apply(Class, new, Args),
79 ?INFO(oop_new, {Args, Class, State}),
80 {ok, State}
81 catch
82 E -> {stop, {new_failed, E}}
Christopher Piro094823a2007-07-18 00:26:12 +000083 end;
Christopher Piro5b3a8f72007-08-01 22:27:37 +000084
Christopher Piro094823a2007-07-18 00:26:12 +000085init(_) ->
86 {stop, invalid_params}.
87
88%%--------------------------------------------------------------------
89%% Function: handle_call/3
90%% Description: Handling call messages
91%% Returns: {reply, Reply, State} |
92%% {reply, Reply, State, Timeout} |
93%% {noreply, State} |
94%% {noreply, State, Timeout} |
95%% {stop, Reason, Reply, State} | (terminate/2 is called)
96%% {stop, Reason, State} (terminate/2 is called)
97%%--------------------------------------------------------------------
98
99handle_call(Request, From, State) ->
100 handle_either(call, Request, From, State).
101
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%%--------------------------------------------------------------------
109
110handle_cast(stop, State) ->
111 {stop, normal, State};
112
113handle_cast({Method, Args}, State) ->
114 handle_either(cast, {Method, Args}, undefined, State).
115
116-define(REPLY(Value, State),
117 case Type of
118 call -> {reply, Value, State};
119 cast -> {noreply, State}
120 end
121).
122
123handle_either(Type, Request, From, State) ->
Christopher Piro5b3a8f72007-08-01 22:27:37 +0000124 %% error_logger:info_msg("~p: ~p", [?SERVER, oop:inspect(State)]),
125 %% error_logger:info_msg("handle_call(Request=~p, From=~p, State)", [Request, From]),
Christopher Piro094823a2007-07-18 00:26:12 +0000126
127 case Request of
128 {get, [Field]} ->
129 Value = oop:get(State, Field),
130 ?REPLY(Value, State);
131
132 {set, [Field, Value]} ->
133 State1 = oop:set(State, Field, Value),
134 ?REPLY(Value, State1);
135
Christopher Piro5b3a8f72007-08-01 22:27:37 +0000136 {class, []} ->
137 ?REPLY(?CLASS(State), State);
138
Christopher Piro094823a2007-07-18 00:26:12 +0000139 {Method, Args} ->
140 handle_method(Type, State, Method, Args);
141
142 _ ->
Christopher Piro5b3a8f72007-08-01 22:27:37 +0000143 error_logger:format("no match for Request = ~p", [Request]),
Christopher Piro094823a2007-07-18 00:26:12 +0000144 %% {stop, server_error, State}
145 {reply, server_error, State}
146 end.
147
148handle_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),
152
153 %% TODO(cpiro): maybe add error handling here? = catch oop:call?
154
155 case {Is_effectful, Call} of
156 {true, {Retval, State1}} ->
157 ?REPLY(Retval, State1);
158
159 {true, _MalformedReturn} ->
160 %% TODO(cpiro): bad match -- remove when we're done converting
Christopher Piro5b3a8f72007-08-01 22:27:37 +0000161 error_logger:format("oop:call(effectful_*,..,..) malformed return value ~p",
162 [_MalformedReturn]),
Christopher Piro094823a2007-07-18 00:26:12 +0000163 %% {stop, server_error, State}
164 {noreply, State};
165
166 {false, Retval} ->
167 ?REPLY(Retval, State)
168 end.
169
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%%--------------------------------------------------------------------
177handle_info({'EXIT', Pid, Except} = All, State) ->
Christopher Piro5b3a8f72007-08-01 22:27:37 +0000178 Result = try
179 oop:call(State, catches, [Pid, Except])
180 catch
181 exit:{missing_method, _} ->
182 unhandled
183 end,
184
185 case Result of
186 unhandled ->
187 error_logger:format("unhandled exit ~p", [All]),
Christopher Piro094823a2007-07-18 00:26:12 +0000188 {stop, All, State};
Christopher Piro5b3a8f72007-08-01 22:27:37 +0000189 _WasHandled ->
Christopher Piro094823a2007-07-18 00:26:12 +0000190 {noreply, State}
191 end;
Christopher Piro5b3a8f72007-08-01 22:27:37 +0000192
Christopher Piro094823a2007-07-18 00:26:12 +0000193handle_info(Info, State) ->
Christopher Piro5b3a8f72007-08-01 22:27:37 +0000194 error_logger:info_msg("~p", [Info]),
Christopher Piro094823a2007-07-18 00:26:12 +0000195 {noreply, State}.
196
197%%--------------------------------------------------------------------
198%% Function: terminate/2
199%% Description: Shutdown the server
200%% Returns: any (ignored by gen_server)
201%%--------------------------------------------------------------------
202terminate(Reason, State) ->
Christopher Piro5b3a8f72007-08-01 22:27:37 +0000203 %%error_logger:format("~p terminated!: ~p", [self(), Reason]),
Christopher Piro094823a2007-07-18 00:26:12 +0000204 ok.
205
206%%--------------------------------------------------------------------
207%% Func: code_change/3
208%% Purpose: Convert process state when code is changed
209%% Returns: {ok, NewState}
210 %%--------------------------------------------------------------------
211code_change(OldVsn, State, Extra) ->
212 {ok, State}.
213
214%%====================================================================
215%%% Internal functions
216%%====================================================================