blob: ef512bc1e61cf1bd9aaebfc26f25bbaf9354659a [file] [log] [blame]
Christopher Piro094823a2007-07-18 00:26:12 +00001%%% Copyright (c) 2007- Facebook
2%%% Distributed under the Thrift Software License
Christopher Piro53b6ef62007-11-15 06:26:28 +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
Christopher Piro094823a2007-07-18 00:26:12 +00007-module(thrift_oop_server).
8
9-behaviour(gen_server).
Christopher Pirode11d852007-11-18 02:10:20 +000010
Christopher Piro094823a2007-07-18 00:26:12 +000011-include("oop.hrl").
12
13-include("thrift.hrl").
14
Christopher Pirode11d852007-11-18 02:10:20 +000015-include("transport/tTransportException.hrl").
16-include("protocol/tProtocolException.hrl").
17
Christopher Piro094823a2007-07-18 00:26:12 +000018-export([
Christopher Piro53b6ef62007-11-15 06:26:28 +000019 start_link/0,
20 stop/0
21 ]).
Christopher Piro094823a2007-07-18 00:26:12 +000022
Christopher Piro094823a2007-07-18 00:26:12 +000023-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]).
24
Christopher Piro094823a2007-07-18 00:26:12 +000025-define(SERVER, ?MODULE).
26
Christopher Pirode11d852007-11-18 02:10:20 +000027%%%
28%%% api
29%%%
30
Christopher Piro094823a2007-07-18 00:26:12 +000031start_link() ->
32 gen_server:start_link({local, ?SERVER}, ?MODULE, [], []).
33
Christopher Piro094823a2007-07-18 00:26:12 +000034stop() ->
35 gen_server:cast(?SERVER, stop).
36
Christopher Pirode11d852007-11-18 02:10:20 +000037%%%
38%%% init
39%%%
Christopher Piro094823a2007-07-18 00:26:12 +000040
Christopher Piro094823a2007-07-18 00:26:12 +000041init({Class, Args}) ->
42 process_flag(trap_exit, true),
Christopher Pirode11d852007-11-18 02:10:20 +000043 try %% TODO use apply_if_defined
Christopher Piro53b6ef62007-11-15 06:26:28 +000044 State = apply(Class, new, Args),
45 ?INFO("thrift ~p:new(~s) = ~s", [Class, thrift_utils:unbrack(Args), oop:inspect(State)]),
46 {ok, State}
Christopher Piro5b3a8f72007-08-01 22:27:37 +000047 catch
Christopher Piro53b6ef62007-11-15 06:26:28 +000048 E -> {stop, {new_failed, E}}
Christopher Piro094823a2007-07-18 00:26:12 +000049 end;
Christopher Piro5b3a8f72007-08-01 22:27:37 +000050
Christopher Piro094823a2007-07-18 00:26:12 +000051init(_) ->
52 {stop, invalid_params}.
53
Christopher Pirode11d852007-11-18 02:10:20 +000054%%%
55%%% call and cast
56%%%
Christopher Piro094823a2007-07-18 00:26:12 +000057
Christopher Pirode11d852007-11-18 02:10:20 +000058handle_call(Request, From, State) -> handle_call_cast(call, Request, From, State).
59handle_cast(stop, State) -> {stop, normal, State};
60handle_cast({Method, Args}, State) -> handle_call_cast(cast, {Method, Args}, undefined, State).
Christopher Piro094823a2007-07-18 00:26:12 +000061
Christopher Pirode11d852007-11-18 02:10:20 +000062reply(call, Value, State) -> {reply, Value, State};
63reply(cast, _Value, State) -> {noreply, State}.
Christopher Piro094823a2007-07-18 00:26:12 +000064
Christopher Pirode11d852007-11-18 02:10:20 +000065handle_call_cast(Type, Request, From, State) ->
66 %% ?INFO("~p: ~p", [?SERVER, oop:inspect(State)]),
67 %% ?INFO("handle_call(Request=~p, From=~p, State)", [Request, From]),
Christopher Piro094823a2007-07-18 00:26:12 +000068
Christopher Piro53b6ef62007-11-15 06:26:28 +000069 case Request of
70 {get, [Field]} ->
71 Value = oop:get(State, Field),
Christopher Pirode11d852007-11-18 02:10:20 +000072 reply(Type, Value, State);
Christopher Piro094823a2007-07-18 00:26:12 +000073
Christopher Piro53b6ef62007-11-15 06:26:28 +000074 {set, [Field, Value]} ->
75 State1 = oop:set(State, Field, Value),
Christopher Pirode11d852007-11-18 02:10:20 +000076 reply(Type, Value, State1);
Christopher Piro094823a2007-07-18 00:26:12 +000077
Christopher Piro53b6ef62007-11-15 06:26:28 +000078 {class, []} ->
Christopher Pirode11d852007-11-18 02:10:20 +000079 reply(Type, ?CLASS(State), State);
Christopher Piro5b3a8f72007-08-01 22:27:37 +000080
Christopher Piro53b6ef62007-11-15 06:26:28 +000081 {Method, Args} ->
82 handle_method(Type, State, Method, Args);
Christopher Piro094823a2007-07-18 00:26:12 +000083
Christopher Piro53b6ef62007-11-15 06:26:28 +000084 _ ->
Christopher Pirode11d852007-11-18 02:10:20 +000085 ?ERROR("thrift no match for Request = ~p", [Request]),
86 {stop, server_error, State}
87 %% {reply, server_error, State}
Christopher Piro094823a2007-07-18 00:26:12 +000088 end.
89
90handle_method(Type, State, Method, Args) ->
Christopher Piro094823a2007-07-18 00:26:12 +000091 Is_effectful = lists:prefix("effectful_", atom_to_list(Method)),
Christopher Piro53b6ef62007-11-15 06:26:28 +000092
Christopher Pirode11d852007-11-18 02:10:20 +000093 try {Is_effectful, oop:call(State, Method, Args)} of
Christopher Piro53b6ef62007-11-15 06:26:28 +000094 {true, {Retval, State1}} ->
Christopher Pirode11d852007-11-18 02:10:20 +000095 reply(Type, Retval, State1);
Christopher Piro53b6ef62007-11-15 06:26:28 +000096
97 {true, _MalformedReturn} ->
98 %% TODO(cpiro): bad match -- remove when we're done converting
Christopher Pirode11d852007-11-18 02:10:20 +000099 ?ERROR("oop:call(effectful_*,..,..) malformed return value ~p",
100 [_MalformedReturn]),
101 {stop, server_error, State};
102 %% {noreply, State};
Christopher Piro53b6ef62007-11-15 06:26:28 +0000103
104 {false, Retval} ->
Christopher Pirode11d852007-11-18 02:10:20 +0000105 reply(Type, Retval, State)
106
107 catch
108 exit:{thrift_exception, E} -> handle_exception(E, nothing);
109 exit:{{thrift_exception, E}, Stack} -> handle_exception(E, Stack);
110 exit:normal -> exit(normal);
111 exit:(X = {timeout, _}) -> exit(X);
112 exit:Other ->
113 exit(Other)
Christopher Piro094823a2007-07-18 00:26:12 +0000114 end.
115
Christopher Pirode11d852007-11-18 02:10:20 +0000116handle_exception(E, Stack) ->
117 %% ?ERROR("texception ~p", [E]),
118 case {oop:is_a(E, tException), Stack} of
119 {true, nothing} -> % good
120 exit({thrift_exception, E});
121 {true, _} -> % good
122 E1 = tException:add_backtrace_element(E, Stack),
123 exit({thrift_exception, E1});
eletuchy53e57192008-02-27 18:38:42 +0000124 {false, _} -> % shit
Christopher Pirode11d852007-11-18 02:10:20 +0000125 ?ERROR("exception wasn't really a tException ~p", [E]),
126 exit(bum)
127 end.
Christopher Piro5b3a8f72007-08-01 22:27:37 +0000128
Christopher Pirode11d852007-11-18 02:10:20 +0000129%%%
130%%% info, terminate, and code_change
131%%%
132
133handle_info({'EXIT', Pid, Except} = All, State) ->
134 case Except of
135 normal ->
136 {noreply, State};
137 {normal, _} ->
138 {noreply, State};
139 _unhandled ->
Christopher Piro53b6ef62007-11-15 06:26:28 +0000140 error_logger:format("unhandled exit ~p", [All]),
Christopher Pirode11d852007-11-18 02:10:20 +0000141 {stop, All, State}
Christopher Piro094823a2007-07-18 00:26:12 +0000142 end;
Christopher Piro5b3a8f72007-08-01 22:27:37 +0000143
Christopher Piro094823a2007-07-18 00:26:12 +0000144handle_info(Info, State) ->
Christopher Pirode11d852007-11-18 02:10:20 +0000145 ?INFO("~p", [Info]),
Christopher Piro094823a2007-07-18 00:26:12 +0000146 {noreply, State}.
147
Christopher Piro094823a2007-07-18 00:26:12 +0000148terminate(Reason, State) ->
Christopher Piro094823a2007-07-18 00:26:12 +0000149 ok.
150
Christopher Piro094823a2007-07-18 00:26:12 +0000151code_change(OldVsn, State, Extra) ->
152 {ok, State}.