You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@thrift.apache.org by dr...@apache.org on 2010/08/31 00:05:01 UTC
svn commit: r990957 [2/2] - in /incubator/thrift/trunk:
compiler/cpp/src/generate/ lib/erl/ lib/erl/build/ lib/erl/include/
lib/erl/src/ test/erl/ test/erl/src/ tutorial/erl/
Modified: incubator/thrift/trunk/lib/erl/src/thrift_processor.erl
URL: http://svn.apache.org/viewvc/incubator/thrift/trunk/lib/erl/src/thrift_processor.erl?rev=990957&r1=990956&r2=990957&view=diff
==============================================================================
--- incubator/thrift/trunk/lib/erl/src/thrift_processor.erl (original)
+++ incubator/thrift/trunk/lib/erl/src/thrift_processor.erl Mon Aug 30 22:05:00 2010
@@ -24,54 +24,55 @@
-include("thrift_constants.hrl").
-include("thrift_protocol.hrl").
--record(thrift_processor, {handler, protocol, service}).
+-record(thrift_processor, {handler, in_protocol, out_protocol, service}).
-init({_Server, ProtoGen, Service, Handler}) when is_function(ProtoGen, 0) ->
- {ok, Proto} = ProtoGen(),
- loop(#thrift_processor{protocol = Proto,
+init({Server, ProtoGen, Service, Handler}) when is_function(ProtoGen, 0) ->
+ {ok, IProt, OProt} = ProtoGen(),
+ loop(#thrift_processor{in_protocol = IProt,
+ out_protocol = OProt,
service = Service,
handler = Handler}).
-loop(State0 = #thrift_processor{protocol = Proto0}) ->
- {Proto1, MessageBegin} = thrift_protocol:read(Proto0, message_begin),
- State1 = State0#thrift_processor{protocol = Proto1},
- case MessageBegin of
+loop(State = #thrift_processor{in_protocol = IProto,
+ out_protocol = OProto}) ->
+ case thrift_protocol:read(IProto, message_begin) of
#protocol_message_begin{name = Function,
type = ?tMessageType_CALL} ->
- {State2, ok} = handle_function(State1, list_to_atom(Function)),
- loop(State2);
+ ok = handle_function(State, list_to_atom(Function)),
+ loop(State);
#protocol_message_begin{name = Function,
type = ?tMessageType_ONEWAY} ->
- {State2, ok} = handle_function(State1, list_to_atom(Function)),
- loop(State2);
+ ok = handle_function(State, list_to_atom(Function)),
+ loop(State);
{error, timeout} ->
- thrift_protocol:close_transport(Proto1),
+ thrift_protocol:close_transport(OProto),
ok;
{error, closed} ->
%% error_logger:info_msg("Client disconnected~n"),
- thrift_protocol:close_transport(Proto1),
+ thrift_protocol:close_transport(OProto),
exit(shutdown)
end.
-handle_function(State0=#thrift_processor{protocol = Proto0,
- handler = Handler,
- service = Service},
+handle_function(State=#thrift_processor{in_protocol = IProto,
+ out_protocol = OProto,
+ handler = Handler,
+ service = Service},
Function) ->
InParams = Service:function_info(Function, params_type),
- {Proto1, {ok, Params}} = thrift_protocol:read(Proto0, InParams),
- State1 = State0#thrift_processor{protocol = Proto1},
+ {ok, Params} = thrift_protocol:read(IProto, InParams),
try
Result = Handler:handle_function(Function, Params),
%% {Micro, Result} = better_timer(Handler, handle_function, [Function, Params]),
%% error_logger:info_msg("Processed ~p(~p) in ~.4fms~n",
%% [Function, Params, Micro/1000.0]),
- handle_success(State1, Function, Result)
+ handle_success(State, Function, Result)
catch
- Type:Data when Type =:= throw orelse Type =:= error ->
- handle_function_catch(State1, Function, Type, Data)
- end.
+ Type:Data ->
+ handle_function_catch(State, Function, Type, Data)
+ end,
+ after_reply(OProto).
handle_function_catch(State = #thrift_processor{service = Service},
Function, ErrType, ErrData) ->
@@ -83,37 +84,39 @@ handle_function_catch(State = #thrift_pr
error_logger:warning_msg(
"oneway void ~p threw error which must be ignored: ~p",
[Function, {ErrType, ErrData, Stack}]),
- {State, ok};
+ ok;
{throw, Exception} when is_tuple(Exception), size(Exception) > 0 ->
- %error_logger:warning_msg("~p threw exception: ~p~n", [Function, Exception]),
- handle_exception(State, Function, Exception);
- % we still want to accept more requests from this client
+ error_logger:warning_msg("~p threw exception: ~p~n", [Function, Exception]),
+ handle_exception(State, Function, Exception),
+ ok; % we still want to accept more requests from this client
{error, Error} ->
- handle_error(State, Function, Error)
+ ok = handle_error(State, Function, Error)
end.
-handle_success(State = #thrift_processor{service = Service},
+handle_success(State = #thrift_processor{out_protocol = OProto,
+ service = Service},
Function,
Result) ->
ReplyType = Service:function_info(Function, reply_type),
StructName = atom_to_list(Function) ++ "_result",
- case Result of
- {reply, ReplyData} ->
- Reply = {{struct, [{0, ReplyType}]}, {StructName, ReplyData}},
- send_reply(State, Function, ?tMessageType_REPLY, Reply);
-
- ok when ReplyType == {struct, []} ->
- send_reply(State, Function, ?tMessageType_REPLY, {ReplyType, {StructName}});
-
- ok when ReplyType == oneway_void ->
- %% no reply for oneway void
- {State, ok}
- end.
+ ok = case Result of
+ {reply, ReplyData} ->
+ Reply = {{struct, [{0, ReplyType}]}, {StructName, ReplyData}},
+ send_reply(OProto, Function, ?tMessageType_REPLY, Reply);
+
+ ok when ReplyType == {struct, []} ->
+ send_reply(OProto, Function, ?tMessageType_REPLY, {ReplyType, {StructName}});
+
+ ok when ReplyType == oneway_void ->
+ %% no reply for oneway void
+ ok
+ end.
-handle_exception(State = #thrift_processor{service = Service},
+handle_exception(State = #thrift_processor{out_protocol = OProto,
+ service = Service},
Function,
Exception) ->
ExceptionType = element(1, Exception),
@@ -138,9 +141,9 @@ handle_exception(State = #thrift_process
% Make sure we got at least one defined
case lists:all(fun(X) -> X =:= undefined end, ExceptionList) of
true ->
- handle_unknown_exception(State, Function, Exception);
+ ok = handle_unknown_exception(State, Function, Exception);
false ->
- send_reply(State, Function, ?tMessageType_REPLY, {ReplySpec, ExceptionTuple})
+ ok = send_reply(OProto, Function, ?tMessageType_REPLY, {ReplySpec, ExceptionTuple})
end.
%%
@@ -151,7 +154,7 @@ handle_unknown_exception(State, Function
handle_error(State, Function, {exception_not_declared_as_thrown,
Exception}).
-handle_error(State, Function, Error) ->
+handle_error(#thrift_processor{out_protocol = OProto}, Function, Error) ->
Stack = erlang:get_stacktrace(),
error_logger:error_msg("~p had an error: ~p~n", [Function, {Error, Stack}]),
@@ -167,14 +170,19 @@ handle_error(State, Function, Error) ->
#'TApplicationException'{
message = Message,
type = ?TApplicationException_UNKNOWN}},
- send_reply(State, Function, ?tMessageType_EXCEPTION, Reply).
+ send_reply(OProto, Function, ?tMessageType_EXCEPTION, Reply).
-send_reply(State = #thrift_processor{protocol = Proto0}, Function, ReplyMessageType, Reply) ->
- {Proto1, ok} = thrift_protocol:write(Proto0, #protocol_message_begin{
- name = atom_to_list(Function),
- type = ReplyMessageType,
- seqid = 0}),
- {Proto2, ok} = thrift_protocol:write(Proto1, Reply),
- {Proto3, ok} = thrift_protocol:write(Proto2, message_end),
- {Proto4, ok} = thrift_protocol:flush_transport(Proto3),
- {State#thrift_processor{protocol = Proto4}, ok}.
+send_reply(OProto, Function, ReplyMessageType, Reply) ->
+ ok = thrift_protocol:write(OProto, #protocol_message_begin{
+ name = atom_to_list(Function),
+ type = ReplyMessageType,
+ seqid = 0}),
+ ok = thrift_protocol:write(OProto, Reply),
+ ok = thrift_protocol:write(OProto, message_end),
+ ok = thrift_protocol:flush_transport(OProto),
+ ok.
+
+after_reply(OProto) ->
+ ok = thrift_protocol:flush_transport(OProto)
+ %% ok = thrift_protocol:close_transport(OProto)
+ .
Modified: incubator/thrift/trunk/lib/erl/src/thrift_protocol.erl
URL: http://svn.apache.org/viewvc/incubator/thrift/trunk/lib/erl/src/thrift_protocol.erl?rev=990957&r1=990956&r2=990957&view=diff
==============================================================================
--- incubator/thrift/trunk/lib/erl/src/thrift_protocol.erl (original)
+++ incubator/thrift/trunk/lib/erl/src/thrift_protocol.erl Mon Aug 30 22:05:00 2010
@@ -49,13 +49,10 @@ new(Module, Data) when is_atom(Module) -
{ok, #protocol{module = Module,
data = Data}}.
--spec flush_transport(#protocol{}) -> {#protocol{}, ok}.
-flush_transport(Proto = #protocol{module = Module,
- data = Data}) ->
- {NewData, Result} = Module:flush_transport(Data),
- {Proto#protocol{data = NewData}, Result}.
+flush_transport(#protocol{module = Module,
+ data = Data}) ->
+ Module:flush_transport(Data).
--spec close_transport(#protocol{}) -> ok.
close_transport(#protocol{module = Module,
data = Data}) ->
Module:close_transport(Data).
@@ -89,8 +86,7 @@ term_to_typeid({list, _}) -> ?tType_LIST
%% Structure is like:
%% [{Fid, Type}, ...]
--spec read(#protocol{}, {struct, _StructDef}, atom()) -> {#protocol{}, {ok, tuple()}}.
-read(IProto0, {struct, Structure}, Tag)
+read(IProto, {struct, Structure}, Tag)
when is_list(Structure), is_atom(Tag) ->
% If we want a tagged tuple, we need to offset all the tuple indices
@@ -107,23 +103,14 @@ read(IProto0, {struct, Structure}, Tag)
% Fid -> {Type, Index}
SDict = dict:from_list(SWithIndices),
- {IProto1, ok} = read(IProto0, struct_begin),
+ ok = read(IProto, struct_begin),
RTuple0 = erlang:make_tuple(length(Structure) + Offset, undefined),
RTuple1 = if Tag =/= undefined -> setelement(1, RTuple0, Tag);
true -> RTuple0
end,
- {IProto2, RTuple2} = read_struct_loop(IProto1, SDict, RTuple1),
- {IProto2, {ok, RTuple2}}.
-
-
-%% NOTE: Keep this in sync with thrift_protocol_behaviour:read
--spec read
- (#protocol{}, {struct, _Info}) -> {#protocol{}, {ok, tuple()} | {error, _Reason}};
- (#protocol{}, tprot_cont_tag()) -> {#protocol{}, {ok, any()} | {error, _Reason}};
- (#protocol{}, tprot_empty_tag()) -> {#protocol{}, ok | {error, _Reason}};
- (#protocol{}, tprot_header_tag()) -> {#protocol{}, tprot_header_val() | {error, _Reason}};
- (#protocol{}, tprot_data_tag()) -> {#protocol{}, {ok, any()} | {error, _Reason}}.
+ RTuple2 = read_struct_loop(IProto, SDict, RTuple1),
+ {ok, RTuple2}.
read(IProto, {struct, {Module, StructureName}}) when is_atom(Module),
is_atom(StructureName) ->
@@ -132,165 +119,137 @@ read(IProto, {struct, {Module, Structure
read(IProto, S={struct, Structure}) when is_list(Structure) ->
read(IProto, S, undefined);
-read(IProto0, {list, Type}) ->
- {IProto1, #protocol_list_begin{etype = EType, size = Size}} =
- read(IProto0, list_begin),
- {EType, EType} = {term_to_typeid(Type), EType},
- {List, IProto2} = lists:mapfoldl(fun(_, ProtoS0) ->
- {ProtoS1, {ok, Item}} = read(ProtoS0, Type),
- {Item, ProtoS1}
- end,
- IProto1,
- lists:duplicate(Size, 0)),
- {IProto3, ok} = read(IProto2, list_end),
- {IProto3, {ok, List}};
-
-read(IProto0, {map, KeyType, ValType}) ->
- {IProto1, #protocol_map_begin{size = Size, ktype = KType, vtype = VType}} =
- read(IProto0, map_begin),
- {KType, KType} = {term_to_typeid(KeyType), KType},
- {VType, VType} = {term_to_typeid(ValType), VType},
- {List, IProto2} = lists:mapfoldl(fun(_, ProtoS0) ->
- {ProtoS1, {ok, Key}} = read(ProtoS0, KeyType),
- {ProtoS2, {ok, Val}} = read(ProtoS1, ValType),
- {{Key, Val}, ProtoS2}
- end,
- IProto1,
- lists:duplicate(Size, 0)),
- {IProto3, ok} = read(IProto2, map_end),
- {IProto3, {ok, dict:from_list(List)}};
-
-read(IProto0, {set, Type}) ->
- {IProto1, #protocol_set_begin{etype = EType, size = Size}} =
- read(IProto0, set_begin),
- {EType, EType} = {term_to_typeid(Type), EType},
- {List, IProto2} = lists:mapfoldl(fun(_, ProtoS0) ->
- {ProtoS1, {ok, Item}} = read(ProtoS0, Type),
- {Item, ProtoS1}
- end,
- IProto1,
- lists:duplicate(Size, 0)),
- {IProto3, ok} = read(IProto2, set_end),
- {IProto3, {ok, sets:from_list(List)}};
-
-read(Protocol, ProtocolType) ->
- read_specific(Protocol, ProtocolType).
-
-%% NOTE: Keep this in sync with thrift_protocol_behaviour:read
--spec read_specific
- (#protocol{}, tprot_empty_tag()) -> {#protocol{}, ok | {error, _Reason}};
- (#protocol{}, tprot_header_tag()) -> {#protocol{}, tprot_header_val() | {error, _Reason}};
- (#protocol{}, tprot_data_tag()) -> {#protocol{}, {ok, any()} | {error, _Reason}}.
-read_specific(Proto = #protocol{module = Module,
- data = ModuleData}, ProtocolType) ->
- {NewData, Result} = Module:read(ModuleData, ProtocolType),
- {Proto#protocol{data = NewData}, Result}.
-
-read_struct_loop(IProto0, SDict, RTuple) ->
- {IProto1, #protocol_field_begin{type = FType, id = Fid}} =
- thrift_protocol:read(IProto0, field_begin),
+read(IProto, {list, Type}) ->
+ #protocol_list_begin{etype = EType, size = Size} =
+ read(IProto, list_begin),
+ List = [Result || {ok, Result} <-
+ [read(IProto, Type) || _X <- lists:duplicate(Size, 0)]],
+ ok = read(IProto, list_end),
+ {ok, List};
+
+read(IProto, {map, KeyType, ValType}) ->
+ #protocol_map_begin{size = Size} =
+ read(IProto, map_begin),
+
+ List = [{Key, Val} || {{ok, Key}, {ok, Val}} <-
+ [{read(IProto, KeyType),
+ read(IProto, ValType)} || _X <- lists:duplicate(Size, 0)]],
+ ok = read(IProto, map_end),
+ {ok, dict:from_list(List)};
+
+read(IProto, {set, Type}) ->
+ #protocol_set_begin{etype = _EType,
+ size = Size} =
+ read(IProto, set_begin),
+ List = [Result || {ok, Result} <-
+ [read(IProto, Type) || _X <- lists:duplicate(Size, 0)]],
+ ok = read(IProto, set_end),
+ {ok, sets:from_list(List)};
+
+read(#protocol{module = Module,
+ data = ModuleData}, ProtocolType) ->
+ Module:read(ModuleData, ProtocolType).
+
+read_struct_loop(IProto, SDict, RTuple) ->
+ #protocol_field_begin{type = FType, id = Fid, name = Name} =
+ thrift_protocol:read(IProto, field_begin),
case {FType, Fid} of
{?tType_STOP, _} ->
- {IProto1, RTuple};
+ RTuple;
_Else ->
case dict:find(Fid, SDict) of
{ok, {Type, Index}} ->
case term_to_typeid(Type) of
FType ->
- {IProto2, {ok, Val}} = read(IProto1, Type),
- {IProto3, ok} = thrift_protocol:read(IProto2, field_end),
+ {ok, Val} = read(IProto, Type),
+ thrift_protocol:read(IProto, field_end),
NewRTuple = setelement(Index, RTuple, Val),
- read_struct_loop(IProto3, SDict, NewRTuple);
+ read_struct_loop(IProto, SDict, NewRTuple);
Expected ->
error_logger:info_msg(
"Skipping field ~p with wrong type (~p != ~p)~n",
[Fid, FType, Expected]),
- skip_field(FType, IProto1, SDict, RTuple)
+ skip_field(FType, IProto, SDict, RTuple)
end;
_Else2 ->
error_logger:info_msg("Skipping field ~p with unknown fid~n", [Fid]),
- skip_field(FType, IProto1, SDict, RTuple)
+ skip_field(FType, IProto, SDict, RTuple)
end
end.
-skip_field(FType, IProto0, SDict, RTuple) ->
+skip_field(FType, IProto, SDict, RTuple) ->
FTypeAtom = thrift_protocol:typeid_to_atom(FType),
- {IProto1, ok} = thrift_protocol:skip(IProto0, FTypeAtom),
- {IProto2, ok} = read(IProto1, field_end),
- read_struct_loop(IProto2, SDict, RTuple).
-
--spec skip(#protocol{}, any()) -> {#protocol{}, ok}.
-
-skip(Proto0, struct) ->
- {Proto1, ok} = read(Proto0, struct_begin),
- {Proto2, ok} = skip_struct_loop(Proto1),
- {Proto3, ok} = read(Proto2, struct_end),
- {Proto3, ok};
-
-skip(Proto0, map) ->
- {Proto1, Map} = read(Proto0, map_begin),
- {Proto2, ok} = skip_map_loop(Proto1, Map),
- {Proto3, ok} = read(Proto2, map_end),
- {Proto3, ok};
-
-skip(Proto0, set) ->
- {Proto1, Set} = read(Proto0, set_begin),
- {Proto2, ok} = skip_set_loop(Proto1, Set),
- {Proto3, ok} = read(Proto2, set_end),
- {Proto3, ok};
-
-skip(Proto0, list) ->
- {Proto1, List} = read(Proto0, list_begin),
- {Proto2, ok} = skip_list_loop(Proto1, List),
- {Proto3, ok} = read(Proto2, list_end),
- {Proto3, ok};
-
-skip(Proto0, Type) when is_atom(Type) ->
- {Proto1, _Ignore} = read(Proto0, Type),
- {Proto1, ok}.
+ thrift_protocol:skip(IProto, FTypeAtom),
+ read(IProto, field_end),
+ read_struct_loop(IProto, SDict, RTuple).
+
+
+skip(Proto, struct) ->
+ ok = read(Proto, struct_begin),
+ ok = skip_struct_loop(Proto),
+ ok = read(Proto, struct_end);
+
+skip(Proto, map) ->
+ Map = read(Proto, map_begin),
+ ok = skip_map_loop(Proto, Map),
+ ok = read(Proto, map_end);
+
+skip(Proto, set) ->
+ Set = read(Proto, set_begin),
+ ok = skip_set_loop(Proto, Set),
+ ok = read(Proto, set_end);
+
+skip(Proto, list) ->
+ List = read(Proto, list_begin),
+ ok = skip_list_loop(Proto, List),
+ ok = read(Proto, list_end);
+
+skip(Proto, Type) when is_atom(Type) ->
+ _Ignore = read(Proto, Type),
+ ok.
-skip_struct_loop(Proto0) ->
- {Proto1, #protocol_field_begin{type = Type}} = read(Proto0, field_begin),
+skip_struct_loop(Proto) ->
+ #protocol_field_begin{type = Type} = read(Proto, field_begin),
case Type of
?tType_STOP ->
- {Proto1, ok};
+ ok;
_Else ->
- {Proto2, ok} = skip(Proto1, Type),
- {Proto3, ok} = read(Proto2, field_end),
- skip_struct_loop(Proto3)
+ skip(Proto, Type),
+ ok = read(Proto, field_end),
+ skip_struct_loop(Proto)
end.
-skip_map_loop(Proto0, Map = #protocol_map_begin{ktype = Ktype,
- vtype = Vtype,
- size = Size}) ->
+skip_map_loop(Proto, Map = #protocol_map_begin{ktype = Ktype,
+ vtype = Vtype,
+ size = Size}) ->
case Size of
N when N > 0 ->
- {Proto1, ok} = skip(Proto0, Ktype),
- {Proto2, ok} = skip(Proto1, Vtype),
- skip_map_loop(Proto2,
+ skip(Proto, Ktype),
+ skip(Proto, Vtype),
+ skip_map_loop(Proto,
Map#protocol_map_begin{size = Size - 1});
- 0 -> {Proto0, ok}
+ 0 -> ok
end.
-skip_set_loop(Proto0, Map = #protocol_set_begin{etype = Etype,
- size = Size}) ->
+skip_set_loop(Proto, Map = #protocol_set_begin{etype = Etype,
+ size = Size}) ->
case Size of
N when N > 0 ->
- {Proto1, ok} = skip(Proto0, Etype),
- skip_set_loop(Proto1,
+ skip(Proto, Etype),
+ skip_set_loop(Proto,
Map#protocol_set_begin{size = Size - 1});
- 0 -> {Proto0, ok}
+ 0 -> ok
end.
-skip_list_loop(Proto0, Map = #protocol_list_begin{etype = Etype,
- size = Size}) ->
+skip_list_loop(Proto, Map = #protocol_list_begin{etype = Etype,
+ size = Size}) ->
case Size of
N when N > 0 ->
- {Proto1, ok} = skip(Proto0, Etype),
- skip_list_loop(Proto1,
+ skip(Proto, Etype),
+ skip_list_loop(Proto,
Map#protocol_list_begin{size = Size - 1});
- 0 -> {Proto0, ok}
+ 0 -> ok
end.
@@ -308,95 +267,90 @@ skip_list_loop(Proto0, Map = #protocol_l
%% | list() -- for list
%% | dictionary() -- for map
%% | set() -- for set
-%% | any() -- for base types
+%% | term() -- for base types
%%
%% Description:
%%--------------------------------------------------------------------
--spec write(#protocol{}, any()) -> {#protocol{}, ok | {error, _Reason}}.
-
-write(Proto0, {{struct, StructDef}, Data})
+write(Proto, {{struct, StructDef}, Data})
when is_list(StructDef), is_tuple(Data), length(StructDef) == size(Data) - 1 ->
[StructName | Elems] = tuple_to_list(Data),
- {Proto1, ok} = write(Proto0, #protocol_struct_begin{name = StructName}),
- {Proto2, ok} = struct_write_loop(Proto1, StructDef, Elems),
- {Proto3, ok} = write(Proto2, struct_end),
- {Proto3, ok};
+ ok = write(Proto, #protocol_struct_begin{name = StructName}),
+ ok = struct_write_loop(Proto, StructDef, Elems),
+ ok = write(Proto, struct_end),
+ ok;
write(Proto, {{struct, {Module, StructureName}}, Data})
when is_atom(Module),
is_atom(StructureName),
element(1, Data) =:= StructureName ->
+ StructType = Module:struct_info(StructureName),
write(Proto, {Module:struct_info(StructureName), Data});
-write(Proto0, {{list, Type}, Data})
+write(Proto, {{list, Type}, Data})
when is_list(Data) ->
- {Proto1, ok} = write(Proto0,
+ ok = write(Proto,
#protocol_list_begin{
etype = term_to_typeid(Type),
size = length(Data)
}),
- Proto2 = lists:foldl(fun(Elem, ProtoIn) ->
- {ProtoOut, ok} = write(ProtoIn, {Type, Elem}),
- ProtoOut
- end,
- Proto1,
- Data),
- {Proto3, ok} = write(Proto2, list_end),
- {Proto3, ok};
-
-write(Proto0, {{map, KeyType, ValType}, Data}) ->
- {Proto1, ok} = write(Proto0,
- #protocol_map_begin{
- ktype = term_to_typeid(KeyType),
- vtype = term_to_typeid(ValType),
- size = dict:size(Data)
- }),
- Proto2 = dict:fold(fun(KeyData, ValData, ProtoS0) ->
- {ProtoS1, ok} = write(ProtoS0, {KeyType, KeyData}),
- {ProtoS2, ok} = write(ProtoS1, {ValType, ValData}),
- ProtoS2
- end,
- Proto1,
- Data),
- {Proto3, ok} = write(Proto2, map_end),
- {Proto3, ok};
+ lists:foreach(fun(Elem) ->
+ ok = write(Proto, {Type, Elem})
+ end,
+ Data),
+ ok = write(Proto, list_end),
+ ok;
+
+write(Proto, {{map, KeyType, ValType}, Data}) ->
+ ok = write(Proto,
+ #protocol_map_begin{
+ ktype = term_to_typeid(KeyType),
+ vtype = term_to_typeid(ValType),
+ size = dict:size(Data)
+ }),
+ dict:fold(fun(KeyData, ValData, _Acc) ->
+ ok = write(Proto, {KeyType, KeyData}),
+ ok = write(Proto, {ValType, ValData})
+ end,
+ _AccO = ok,
+ Data),
+ ok = write(Proto, map_end),
+ ok;
-write(Proto0, {{set, Type}, Data}) ->
+write(Proto, {{set, Type}, Data}) ->
true = sets:is_set(Data),
- {Proto1, ok} = write(Proto0,
- #protocol_set_begin{
- etype = term_to_typeid(Type),
- size = sets:size(Data)
- }),
- Proto2 = sets:fold(fun(Elem, ProtoIn) ->
- {ProtoOut, ok} = write(ProtoIn, {Type, Elem}),
- ProtoOut
- end,
- Proto1,
- Data),
- {Proto3, ok} = write(Proto2, set_end),
- {Proto3, ok};
-
-write(Proto = #protocol{module = Module,
- data = ModuleData}, Data) ->
- {NewData, Result} = Module:write(ModuleData, Data),
- {Proto#protocol{data = NewData}, Result}.
-
-struct_write_loop(Proto0, [{Fid, Type} | RestStructDef], [Data | RestData]) ->
- NewProto = case Data of
- undefined ->
- Proto0; % null fields are skipped in response
- _ ->
- {Proto1, ok} = write(Proto0,
- #protocol_field_begin{
- type = term_to_typeid(Type),
- id = Fid
- }),
- {Proto2, ok} = write(Proto1, {Type, Data}),
- {Proto3, ok} = write(Proto2, field_end),
- Proto3
- end,
- struct_write_loop(NewProto, RestStructDef, RestData);
+ ok = write(Proto,
+ #protocol_set_begin{
+ etype = term_to_typeid(Type),
+ size = sets:size(Data)
+ }),
+ sets:fold(fun(Elem, _Acc) ->
+ ok = write(Proto, {Type, Elem})
+ end,
+ _Acc0 = ok,
+ Data),
+ ok = write(Proto, set_end),
+ ok;
+
+write(#protocol{module = Module,
+ data = ModuleData}, Data) ->
+ Module:write(ModuleData, Data).
+
+struct_write_loop(Proto, [{Fid, Type} | RestStructDef], [Data | RestData]) ->
+ case Data of
+ undefined ->
+ % null fields are skipped in response
+ skip;
+ _ ->
+ ok = write(Proto,
+ #protocol_field_begin{
+ type = term_to_typeid(Type),
+ id = Fid
+ }),
+ ok = write(Proto, {Type, Data}),
+ ok = write(Proto, field_end)
+ end,
+ struct_write_loop(Proto, RestStructDef, RestData);
struct_write_loop(Proto, [], []) ->
- write(Proto, field_stop).
+ ok = write(Proto, field_stop),
+ ok.
Modified: incubator/thrift/trunk/lib/erl/src/thrift_server.erl
URL: http://svn.apache.org/viewvc/incubator/thrift/trunk/lib/erl/src/thrift_server.erl?rev=990957&r1=990956&r2=990957&view=diff
==============================================================================
--- incubator/thrift/trunk/lib/erl/src/thrift_server.erl (original)
+++ incubator/thrift/trunk/lib/erl/src/thrift_server.erl Mon Aug 30 22:05:00 2010
@@ -126,7 +126,7 @@ handle_info({inet_async, ListenSocket, R
{stop, Reason, State}
end;
-handle_info({inet_async, _ListenSocket, _Ref, Error}, State) ->
+handle_info({inet_async, ListenSocket, Ref, Error}, State) ->
error_logger:error_msg("Error in acceptor: ~p~n", [Error]),
{stop, Error, State};
@@ -177,7 +177,7 @@ start_processor(Socket, Service, Handler
{ok, SocketTransport} = thrift_socket_transport:new(Socket),
{ok, BufferedTransport} = thrift_buffered_transport:new(SocketTransport),
{ok, Protocol} = thrift_binary_protocol:new(BufferedTransport),
- {ok, Protocol}
+ {ok, Protocol, Protocol}
end,
spawn(thrift_processor, init, [{Server, ProtoGen, Service, Handler}]).
Modified: incubator/thrift/trunk/lib/erl/src/thrift_socket_server.erl
URL: http://svn.apache.org/viewvc/incubator/thrift/trunk/lib/erl/src/thrift_socket_server.erl?rev=990957&r1=990956&r2=990957&view=diff
==============================================================================
--- incubator/thrift/trunk/lib/erl/src/thrift_socket_server.erl (original)
+++ incubator/thrift/trunk/lib/erl/src/thrift_socket_server.erl Mon Aug 30 22:05:00 2010
@@ -166,12 +166,13 @@ gen_tcp_listen(Port, Opts, State) ->
new_acceptor(State=#thrift_socket_server{max=0}) ->
error_logger:error_msg("Not accepting new connections"),
State#thrift_socket_server{acceptor=null};
-new_acceptor(State=#thrift_socket_server{listen=Listen,
+new_acceptor(State=#thrift_socket_server{acceptor=OldPid, listen=Listen,
service=Service, handler=Handler,
socket_opts=Opts, framed=Framed
}) ->
Pid = proc_lib:spawn_link(?MODULE, acceptor_loop,
[{self(), Listen, Service, Handler, Opts, Framed}]),
+%% error_logger:info_msg("Spawning new acceptor: ~p => ~p", [OldPid, Pid]),
State#thrift_socket_server{acceptor=Pid}.
acceptor_loop({Server, Listen, Service, Handler, SocketOpts, Framed})
@@ -187,7 +188,7 @@ acceptor_loop({Server, Listen, Service,
false -> thrift_buffered_transport:new(SocketTransport)
end,
{ok, Protocol} = thrift_binary_protocol:new(Transport),
- {ok, Protocol}
+ {ok, IProt=Protocol, OProt=Protocol}
end,
thrift_processor:init({Server, ProtoGen, Service, Handler});
{error, closed} ->
Modified: incubator/thrift/trunk/lib/erl/src/thrift_socket_transport.erl
URL: http://svn.apache.org/viewvc/incubator/thrift/trunk/lib/erl/src/thrift_socket_transport.erl?rev=990957&r1=990956&r2=990957&view=diff
==============================================================================
--- incubator/thrift/trunk/lib/erl/src/thrift_socket_transport.erl (original)
+++ incubator/thrift/trunk/lib/erl/src/thrift_socket_transport.erl Mon Aug 30 22:05:00 2010
@@ -29,8 +29,6 @@
-record(data, {socket,
recv_timeout=infinity}).
--type state() :: #data{}.
--include("thrift_transport_behaviour.hrl").
new(Socket) ->
new(Socket, []).
@@ -47,26 +45,25 @@ new(Socket, Opts) when is_list(Opts) ->
thrift_transport:new(?MODULE, State).
%% Data :: iolist()
-write(This = #data{socket = Socket}, Data) ->
- {This, gen_tcp:send(Socket, Data)}.
+write(#data{socket = Socket}, Data) ->
+ gen_tcp:send(Socket, Data).
-read(This = #data{socket=Socket, recv_timeout=Timeout}, Len)
+read(#data{socket=Socket, recv_timeout=Timeout}, Len)
when is_integer(Len), Len >= 0 ->
case gen_tcp:recv(Socket, Len, Timeout) of
Err = {error, timeout} ->
error_logger:info_msg("read timeout: peer conn ~p", [inet:peername(Socket)]),
gen_tcp:close(Socket),
- {This, Err};
- Data ->
- {This, Data}
+ Err;
+ Data -> Data
end.
%% We can't really flush - everything is flushed when we write
-flush(This) ->
- {This, ok}.
+flush(_) ->
+ ok.
-close(This = #data{socket = Socket}) ->
- {This, gen_tcp:close(Socket)}.
+close(#data{socket = Socket}) ->
+ gen_tcp:close(Socket).
%%%% FACTORY GENERATION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Modified: incubator/thrift/trunk/lib/erl/src/thrift_transport.erl
URL: http://svn.apache.org/viewvc/incubator/thrift/trunk/lib/erl/src/thrift_transport.erl?rev=990957&r1=990956&r2=990957&view=diff
==============================================================================
--- incubator/thrift/trunk/lib/erl/src/thrift_transport.erl (original)
+++ incubator/thrift/trunk/lib/erl/src/thrift_transport.erl Mon Aug 30 22:05:00 2010
@@ -37,42 +37,21 @@ behaviour_info(callbacks) ->
-record(transport, {module, data}).
--ifdef(transport_wrapper_module).
--define(debug_wrap(Transport),
- case Transport#transport.module of
- ?transport_wrapper_module ->
- Transport;
- _Else ->
- {ok, Result} = ?transport_wrapper_module:new(Transport),
- Result
- end).
--else.
--define(debug_wrap(Transport), Transport).
--endif.
-
new(Module, Data) when is_atom(Module) ->
- Transport0 = #transport{module = Module, data = Data},
- Transport1 = ?debug_wrap(Transport0),
- {ok, Transport1}.
+ {ok, #transport{module = Module,
+ data = Data}}.
--spec write(#transport{}, iolist() | binary()) -> {#transport{}, ok | {error, _Reason}}.
+%% Data :: iolist()
write(Transport, Data) ->
Module = Transport#transport.module,
- {NewTransData, Result} = Module:write(Transport#transport.data, Data),
- {Transport#transport{data = NewTransData}, Result}.
+ Module:write(Transport#transport.data, Data).
--spec read(#transport{}, non_neg_integer()) -> {#transport{}, {ok, binary()} | {error, _Reason}}.
read(Transport, Len) when is_integer(Len) ->
Module = Transport#transport.module,
- {NewTransData, Result} = Module:read(Transport#transport.data, Len),
- {Transport#transport{data = NewTransData}, Result}.
+ Module:read(Transport#transport.data, Len).
+
+flush(#transport{module = Module, data = Data}) ->
+ Module:flush(Data).
--spec flush(#transport{}) -> {#transport{}, ok | {error, _Reason}}.
-flush(Transport = #transport{module = Module, data = Data}) ->
- {NewTransData, Result} = Module:flush(Data),
- {Transport#transport{data = NewTransData}, Result}.
-
--spec close(#transport{}) -> {#transport{}, ok | {error, _Reason}}.
-close(Transport = #transport{module = Module, data = Data}) ->
- {NewTransData, Result} = Module:close(Data),
- {Transport#transport{data = NewTransData}, Result}.
+close(#transport{module = Module, data = Data}) ->
+ Module:close(Data).
Modified: incubator/thrift/trunk/test/erl/Makefile
URL: http://svn.apache.org/viewvc/incubator/thrift/trunk/test/erl/Makefile?rev=990957&r1=990956&r2=990957&view=diff
==============================================================================
--- incubator/thrift/trunk/test/erl/Makefile (original)
+++ incubator/thrift/trunk/test/erl/Makefile Mon Aug 30 22:05:00 2010
@@ -29,7 +29,7 @@ SRCDIR=src
ALL_INCLUDEDIR=$(GEN_INCLUDEDIR) $(INCLUDEDIR) ../../lib/erl/include
INCLUDEFLAGS=$(patsubst %,-I%, ${ALL_INCLUDEDIR})
-MODULES = stress_server test_server test_client test_disklog test_membuffer
+MODULES = stress_server test_server test_disklog test_membuffer test_tether
INCLUDES =
TARGETS = $(patsubst %,${TARGETDIR}/%.beam,${MODULES})
@@ -55,11 +55,11 @@ ${GENDIR}/: ${RPCFILE}
${GEN_TARGETDIR}/: ${GENDIR}/
rm -rf ${GEN_TARGETDIR}
mkdir -p ${GEN_TARGETDIR}
- erlc ${ERLC_FLAGS} ${INCLUDEFLAGS} -o ${GEN_TARGETDIR} ${GEN_SRCDIR}/*.erl
+ erlc ${INCLUDEFLAGS} -o ${GEN_TARGETDIR} ${GEN_SRCDIR}/*.erl
$(TARGETS): ${TARGETDIR}/%.beam: ${SRCDIR}/%.erl ${GEN_INCLUDEDIR}/ ${HEADERS}
mkdir -p ${TARGETDIR}
- erlc ${ERLC_FLAGS} ${INCLUDEFLAGS} -o ${TARGETDIR} $<
+ erlc ${INCLUDEFLAGS} -o ${TARGETDIR} $<
clean:
rm -f ${TARGETDIR}/*.beam
Modified: incubator/thrift/trunk/test/erl/src/test_disklog.erl
URL: http://svn.apache.org/viewvc/incubator/thrift/trunk/test/erl/src/test_disklog.erl?rev=990957&r1=990956&r2=990957&view=diff
==============================================================================
--- incubator/thrift/trunk/test/erl/src/test_disklog.erl (original)
+++ incubator/thrift/trunk/test/erl/src/test_disklog.erl Mon Aug 30 22:05:00 2010
@@ -29,21 +29,20 @@ t() ->
{size, {1024*1024, 10}}]),
{ok, ProtocolFactory} = thrift_binary_protocol:new_protocol_factory(
TransportFactory, []),
- {ok, Proto} = ProtocolFactory(),
- {ok, Client0} = thrift_client:new(Proto, thriftTest_thrift),
+ {ok, Client} = thrift_client:start_link(ProtocolFactory, thriftTest_thrift),
io:format("Client started~n"),
% We have to make oneway calls into this client only since otherwise it will try
% to read from the disklog and go boom.
- {Client1, {ok, ok}} = thrift_client:call(Client0, testOneway, [16#deadbeef]),
+ {ok, ok} = thrift_client:call(Client, testOneway, [16#deadbeef]),
io:format("Call written~n"),
% Use the send_call method to write a non-oneway call into the log
- {Client2, ok} = thrift_client:send_call(Client1, testString, [<<"hello world">>]),
+ ok = thrift_client:send_call(Client, testString, [<<"hello world">>]),
io:format("Non-oneway call sent~n"),
- {_Client3, ok} = thrift_client:close(Client2),
+ ok = thrift_client:close(Client),
io:format("Client closed~n"),
ok.
@@ -62,22 +61,21 @@ t_base64() ->
thrift_buffered_transport:new_transport_factory(B64Factory),
{ok, ProtocolFactory} = thrift_binary_protocol:new_protocol_factory(
BufFactory, []),
- {ok, Proto} = ProtocolFactory(),
- {ok, Client0} = thrift_client:new(Proto, thriftTest_thrift),
+ {ok, Client} = thrift_client:start_link(ProtocolFactory, thriftTest_thrift),
io:format("Client started~n"),
% We have to make oneway calls into this client only since otherwise it will try
% to read from the disklog and go boom.
- {Client1, {ok, ok}} = thrift_client:call(Client0, testOneway, [16#deadbeef]),
+ {ok, ok} = thrift_client:call(Client, testOneway, [16#deadbeef]),
io:format("Call written~n"),
% Use the send_call method to write a non-oneway call into the log
- {Client2, ok} = thrift_client:send_call(Client1, testString, [<<"hello world">>]),
+ ok = thrift_client:send_call(Client, testString, [<<"hello world">>]),
io:format("Non-oneway call sent~n"),
- {_Client3, ok} = thrift_client:close(Client2),
+ ok = thrift_client:close(Client),
io:format("Client closed~n"),
ok.
-
+
Modified: incubator/thrift/trunk/test/erl/src/test_membuffer.erl
URL: http://svn.apache.org/viewvc/incubator/thrift/trunk/test/erl/src/test_membuffer.erl?rev=990957&r1=990956&r2=990957&view=diff
==============================================================================
--- incubator/thrift/trunk/test/erl/src/test_membuffer.erl (original)
+++ incubator/thrift/trunk/test/erl/src/test_membuffer.erl Mon Aug 30 22:05:00 2010
@@ -30,12 +30,12 @@ test_data() ->
t1() ->
{ok, Transport} = thrift_memory_buffer:new(),
- {ok, Protocol0} = thrift_binary_protocol:new(Transport),
+ {ok, Protocol} = thrift_binary_protocol:new(Transport),
TestData = test_data(),
- {Protocol1, ok} = thrift_protocol:write(Protocol0,
+ ok = thrift_protocol:write(Protocol,
{{struct, element(2, thriftTest_types:struct_info('xtruct'))},
TestData}),
- {_Protocol2, {ok, Result}} = thrift_protocol:read(Protocol1,
+ {ok, Result} = thrift_protocol:read(Protocol,
{struct, element(2, thriftTest_types:struct_info('xtruct'))},
'xtruct'),
@@ -44,12 +44,12 @@ t1() ->
t2() ->
{ok, Transport} = thrift_memory_buffer:new(),
- {ok, Protocol0} = thrift_binary_protocol:new(Transport),
+ {ok, Protocol} = thrift_binary_protocol:new(Transport),
TestData = test_data(),
- {Protocol1, ok} = thrift_protocol:write(Protocol0,
+ ok = thrift_protocol:write(Protocol,
{{struct, element(2, thriftTest_types:struct_info('xtruct'))},
TestData}),
- {_Protocol2, {ok, Result}} = thrift_protocol:read(Protocol1,
+ {ok, Result} = thrift_protocol:read(Protocol,
{struct, element(2, thriftTest_types:struct_info('xtruct3'))},
'xtruct3'),
@@ -61,12 +61,12 @@ t2() ->
t3() ->
{ok, Transport} = thrift_memory_buffer:new(),
- {ok, Protocol0} = thrift_binary_protocol:new(Transport),
+ {ok, Protocol} = thrift_binary_protocol:new(Transport),
TestData = #bools{im_true = true, im_false = false},
- {Protocol1, ok} = thrift_protocol:write(Protocol0,
+ ok = thrift_protocol:write(Protocol,
{{struct, element(2, thriftTest_types:struct_info('bools'))},
TestData}),
- {_Protocol2, {ok, Result}} = thrift_protocol:read(Protocol1,
+ {ok, Result} = thrift_protocol:read(Protocol,
{struct, element(2, thriftTest_types:struct_info('bools'))},
'bools'),
@@ -74,23 +74,8 @@ t3() ->
true = TestData#bools.im_false =:= Result#bools.im_false.
-t4() ->
- {ok, Transport} = thrift_memory_buffer:new(),
- {ok, Protocol0} = thrift_binary_protocol:new(Transport),
- TestData = #insanity{xtructs=[]},
- {Protocol1, ok} = thrift_protocol:write(Protocol0,
- {{struct, element(2, thriftTest_types:struct_info('insanity'))},
- TestData}),
- {_Protocol2, {ok, Result}} = thrift_protocol:read(Protocol1,
- {struct, element(2, thriftTest_types:struct_info('insanity'))},
- 'insanity'),
-
- TestData = Result.
-
-
t() ->
t1(),
t2(),
- t3(),
- t4().
+ t3().
Modified: incubator/thrift/trunk/test/erl/src/test_server.erl
URL: http://svn.apache.org/viewvc/incubator/thrift/trunk/test/erl/src/test_server.erl?rev=990957&r1=990956&r2=990957&view=diff
==============================================================================
--- incubator/thrift/trunk/test/erl/src/test_server.erl (original)
+++ incubator/thrift/trunk/test/erl/src/test_server.erl Mon Aug 30 22:05:00 2010
@@ -19,42 +19,12 @@
-module(test_server).
--export([go/0, go/1, start_link/2, handle_function/2]).
+-export([start_link/1, handle_function/2]).
-include("thriftTest_types.hrl").
--record(options, {port = 9090,
- server_opts = []}).
-
-parse_args(Args) -> parse_args(Args, #options{}).
-parse_args([], Opts) -> Opts;
-parse_args([Head | Rest], Opts) ->
- NewOpts =
- case catch list_to_integer(Head) of
- Port when is_integer(Port) ->
- Opts#options{port = Port};
- _Else ->
- case Head of
- "framed" ->
- Opts#options{server_opts = [{framed, true} | Opts#options.server_opts]};
- "" ->
- Opts;
- _Else ->
- erlang:error({bad_arg, Head})
- end
- end,
- parse_args(Rest, NewOpts).
-
-go() -> go([]).
-go(Args) ->
- #options{port = Port, server_opts = ServerOpts} = parse_args(Args),
- spawn(fun() -> start_link(Port, ServerOpts), receive after infinity -> ok end end).
-
-start_link(Port, ServerOpts) ->
- thrift_socket_server:start([{handler, ?MODULE},
- {service, thriftTest_thrift},
- {port, Port}] ++
- ServerOpts).
+start_link(Port) ->
+ thrift_server:start_link(Port, thriftTest_thrift, ?MODULE).
handle_function(testVoid, {}) ->
@@ -154,12 +124,12 @@ handle_function(testInsanity, {Insanity}
{?thriftTest_THREE, Crazy}]),
SecondMap = dict:from_list([{?thriftTest_SIX, Looney}]),
-
+
Insane = dict:from_list([{1, FirstMap},
{2, SecondMap}]),
-
+
io:format("Return = ~p~n", [Insane]),
-
+
{reply, Insane};
handle_function(testMulti, Args = {Arg0, Arg1, Arg2, _Arg3, Arg4, Arg5})
@@ -180,7 +150,7 @@ handle_function(testException, {String})
case String of
<<"Xception">> ->
throw(#xception{errorCode = 1001,
- message = String});
+ message = <<"This is an Xception">>});
_ ->
ok
end;
Added: incubator/thrift/trunk/test/erl/src/test_tether.erl
URL: http://svn.apache.org/viewvc/incubator/thrift/trunk/test/erl/src/test_tether.erl?rev=990957&view=auto
==============================================================================
--- incubator/thrift/trunk/test/erl/src/test_tether.erl (added)
+++ incubator/thrift/trunk/test/erl/src/test_tether.erl Mon Aug 30 22:05:00 2010
@@ -0,0 +1,186 @@
+%%
+%% Licensed to the Apache Software Foundation (ASF) under one
+%% or more contributor license agreements. See the NOTICE file
+%% distributed with this work for additional information
+%% regarding copyright ownership. The ASF licenses this file
+%% to you under the Apache License, Version 2.0 (the
+%% "License"); you may not use this file except in compliance
+%% with the License. You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing,
+%% software distributed under the License is distributed on an
+%% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+%% KIND, either express or implied. See the License for the
+%% specific language governing permissions and limitations
+%% under the License.
+%%
+%% Tests the behavior of clients in the face of transport errors.
+%% Makes sure start, start_linked, and start_tethered work as expected.
+
+-module(test_tether).
+
+-compile(export_all).
+
+
+t() ->
+ io:format("Beginning transport error test.~n"),
+ Pid1 = erlang:spawn(?MODULE, t_sub, [2]),
+ wait_for(Pid1),
+ io:format("Beginning protocol error test.~n"),
+ Pid2 = erlang:spawn(?MODULE, t_sub, [22]),
+ wait_for(Pid2),
+ ok.
+
+t_sub(Port) ->
+ io:format("Starting.~n", []),
+ register(tester, self()),
+
+ Pid1 = erlang:spawn(?MODULE, test_start, [Port]),
+ receive after 200 -> ok end, % Wait for completion.
+ case is_up(Pid1) of
+ true ->
+ io:format("PASS. Unlinked owner still alive.~n");
+ false ->
+ io:format("FAIL. Unlinked owner is dead.~n")
+ end,
+
+ Pid2 = erlang:spawn(?MODULE, test_linked, [Port]),
+ receive after 200 -> ok end, % Wait for completion.
+ case is_up(Pid2) of
+ true ->
+ io:format("FAIL. Linked owner still alive.~n");
+ false ->
+ io:format("PASS. Linked owner is dead.~n")
+ end,
+
+ Pid3 = erlang:spawn(?MODULE, test_tethered, [Port]),
+ receive after 200 -> ok end, % Wait for completion.
+ case is_up(Pid3) of
+ true ->
+ io:format("PASS. Tethered owner still alive.~n");
+ false ->
+ io:format("FAIL. Tethered owner is dead.~n")
+ end,
+
+ check_extras(3).
+
+is_up(Pid) ->
+ MonitorRef = erlang:monitor(process, Pid),
+ receive
+ {'DOWN', MonitorRef, process, Pid, _Info} ->
+ false
+ after
+ 50 ->
+ erlang:demonitor(MonitorRef),
+ true
+ end.
+
+wait_for(Pid) ->
+ MonitorRef = erlang:monitor(process, Pid),
+ receive
+ {'DOWN', MonitorRef, process, Pid, _Info} ->
+ ok
+ end.
+
+check_extras(0) -> ok;
+check_extras(N) ->
+ receive
+ {client, Type, Pid} ->
+ case {Type, is_up(Pid)} of
+ {unlinked, true} ->
+ io:format("PASS. Unlinked client still alive.~n");
+ {unlinked, false} ->
+ io:format("FAIL. Unlinked client dead.~n");
+ {linked, true} ->
+ io:format("FAIL. Linked client still alive.~n");
+ {linked, false} ->
+ io:format("PASS. Linked client dead.~n");
+ {tethered, true} ->
+ io:format("FAIL. Tethered client still alive.~n");
+ {tethered, false} ->
+ io:format("PASS. Tethered client dead.~n")
+ end,
+ check_extras(N-1)
+ after
+ 500 ->
+ io:format("FAIL. Expected ~p more clients.~n", [N])
+ end.
+
+make_thrift_client(Opts) ->
+ thrift_client:start(fun()->ok end, thriftTest_thrift, Opts).
+
+make_protocol_factory(Port) ->
+ {ok, TransportFactory} =
+ thrift_socket_transport:new_transport_factory(
+ "127.0.0.1", Port, []),
+ {ok, ProtocolFactory} =
+ thrift_binary_protocol:new_protocol_factory(
+ TransportFactory, []),
+ ProtocolFactory.
+
+
+test_start(Port) ->
+ {ok, Client1} = make_thrift_client([{connect, false}]),
+ tester ! {client, unlinked, Client1},
+ {ok, Client2} = make_thrift_client([{connect, false}]),
+ io:format("PASS. Unlinked clients created.~n"),
+ try
+ gen_server:call(Client2, {connect, make_protocol_factory(Port)}),
+ thrift_client:call(Client2, testVoid, []),
+ io:format("FAIL. Unlinked client connected and called.~n", [])
+ catch
+ Kind:Info ->
+ io:format("PASS. Caught unlinked error. ~p:~p~n", [Kind, Info])
+ end,
+ receive after 100 ->
+ io:format("PASS. Still alive after unlinked death.~n"),
+ %% Hang around a little longer so our parent can verify.
+ receive after 200 -> ok end
+ end,
+ %% Exit abnormally to not kill our unlinked extra client.
+ exit(die).
+
+test_linked(Port) ->
+ {ok, Client1} = make_thrift_client([{connect, false}, {monitor, link}]),
+ tester ! {client, linked, Client1},
+ {ok, Client2} = make_thrift_client([{connect, false}, {monitor, link}]),
+ io:format("PASS. Linked clients created.~n"),
+ try
+ gen_server:call(Client2, {connect, make_protocol_factory(Port)}),
+ thrift_client:call(Client2, testVoid, []),
+ io:format("FAIL. Linked client connected and called.~n", [])
+ catch
+ Kind:Info ->
+ io:format("FAIL. Caught linked error. ~p:~p~n", [Kind, Info])
+ end,
+ receive after 100 ->
+ io:format("FAIL. Still alive after linked death.~n"),
+ % Hang around a little longer so our parent can verify.
+ receive after 200 -> ok end
+ end,
+ %% Exit abnormally to kill our linked extra client.
+ %% But we should never get here.
+ exit(die).
+
+test_tethered(Port) ->
+ {ok, Client1} = make_thrift_client([{connect, false}, {monitor, tether}]),
+ tester ! {client, tethered, Client1},
+ {ok, Client2} = make_thrift_client([{connect, false}, {monitor, tether}]),
+ io:format("PASS. Tethered clients created.~n"),
+ try
+ gen_server:call(Client2, {connect, make_protocol_factory(Port)}),
+ thrift_client:call(Client2, testVoid, []),
+ io:format("FAIL. Tethered client connected and called.~n", [])
+ catch
+ Kind:Info ->
+ io:format("PASS. Caught tethered error. ~p:~p~n", [Kind, Info])
+ end,
+ receive after 100 ->
+ io:format("PASS. Still alive after tethered death.~n"),
+ % Hang around a little longer so our parent can verify.
+ receive after 200 -> ok end
+ end,
+ %% Exit abnormally to kill our tethered extra client.
+ exit(die).
Modified: incubator/thrift/trunk/tutorial/erl/client.erl
URL: http://svn.apache.org/viewvc/incubator/thrift/trunk/tutorial/erl/client.erl?rev=990957&r1=990956&r2=990957&view=diff
==============================================================================
--- incubator/thrift/trunk/tutorial/erl/client.erl (original)
+++ incubator/thrift/trunk/tutorial/erl/client.erl Mon Aug 30 22:05:00 2010
@@ -29,50 +29,46 @@ p(X) ->
t() ->
Port = 9999,
+
+ {ok, Client} = thrift_client:start_link("127.0.0.1",
+ Port,
+ calculator_thrift),
- {ok, Client0} = thrift_client_util:new("127.0.0.1",
- Port,
- calculator_thrift,
- []),
-
- {Client1, {ok, ok}} = thrift_client:call(Client0, ping, []),
+ thrift_client:call(Client, ping, []),
io:format("ping~n", []),
- {Client2, {ok, Sum}} = thrift_client:call(Client1, add, [1, 1]),
+ {ok, Sum} = thrift_client:call(Client, add, [1, 1]),
io:format("1+1=~p~n", [Sum]),
- {Client3, {ok, Sum1}} = thrift_client:call(Client2, add, [1, 4]),
+ {ok, Sum1} = thrift_client:call(Client, add, [1, 4]),
io:format("1+4=~p~n", [Sum1]),
Work = #work{op=?tutorial_SUBTRACT,
num1=15,
num2=10},
- {Client4, {ok, Diff}} = thrift_client:call(Client3, calculate, [1, Work]),
+ {ok, Diff} = thrift_client:call(Client, calculate, [1, Work]),
io:format("15-10=~p~n", [Diff]),
- {Client5, {ok, Log}} = thrift_client:call(Client4, getStruct, [1]),
+ {ok, Log} = thrift_client:call(Client, getStruct, [1]),
io:format("Log: ~p~n", [Log]),
- Client6 =
- try
- Work1 = #work{op=?tutorial_DIVIDE,
- num1=1,
- num2=0},
- {ClientS1, {ok, _Quot}} = thrift_client:call(Client5, calculate, [2, Work1]),
-
- io:format("LAME: exception handling is broken~n", []),
- ClientS1
- catch
- throw:{ClientS2, Z} ->
- io:format("Got exception where expecting - the " ++
- "following is NOT a problem!!!~n"),
- p(Z),
- ClientS2
- end,
+ try
+ Work1 = #work{op=?tutorial_DIVIDE,
+ num1=1,
+ num2=0},
+ {ok, _Quot} = thrift_client:call(Client, calculate, [2, Work1]),
+
+ io:format("LAME: exception handling is broken~n", [])
+ catch
+ Z ->
+ io:format("Got exception where expecting - the " ++
+ "following is NOT a problem!!!~n"),
+ p(Z)
+ end,
- {Client7, {ok, ok}} = thrift_client:call(Client6, zip, []),
+ {ok, ok} = thrift_client:call(Client, zip, []),
io:format("zip~n", []),
- {_Client8, ok} = thrift_client:close(Client7),
+ ok = thrift_client:close(Client),
ok.