erlang: Refactor the write paths of the client and protocol

TODO: squash this

git-svn-id: https://svn.apache.org/repos/asf/incubator/thrift/trunk@990980 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
David Reiss 2010-08-30 22:05:31 +00:00
parent 3f660a4266
commit c465799c1b
2 changed files with 77 additions and 72 deletions

View File

@ -62,7 +62,7 @@ close(#tclient{protocol=Protocol}) ->
%%% Internal functions
%%--------------------------------------------------------------------
-spec send_function_call(#tclient{}, atom(), list()) -> {#tclient{}, ok | {error, term()}}.
send_function_call(Client = #tclient{protocol = Proto,
send_function_call(Client = #tclient{protocol = Proto0,
service = Service,
seqid = SeqId},
Function,
@ -77,11 +77,11 @@ send_function_call(Client = #tclient{protocol = Proto,
Begin = #protocol_message_begin{name = atom_to_list(Function),
type = ?tMessageType_CALL,
seqid = SeqId},
ok = thrift_protocol:write(Proto, Begin),
ok = thrift_protocol:write(Proto, {Params, list_to_tuple([Function | Args])}),
ok = thrift_protocol:write(Proto, message_end),
ok = thrift_protocol:flush_transport(Proto),
{Client, ok}
{Proto1, ok} = thrift_protocol:write(Proto0, Begin),
{Proto2, ok} = thrift_protocol:write(Proto1, {Params, list_to_tuple([Function | Args])}),
{Proto3, ok} = thrift_protocol:write(Proto2, message_end),
{Proto4, ok} = thrift_protocol:flush_transport(Proto3),
{Client#tclient{protocol = Proto4}, ok}
end.
-spec receive_function_result(#tclient{}, atom()) -> {#tclient{}, {ok, term()} | {error, term()}}.

View File

@ -49,10 +49,11 @@ new(Module, Data) when is_atom(Module) ->
{ok, #protocol{module = Module,
data = Data}}.
-spec flush_transport(#protocol{}) -> ok.
flush_transport(#protocol{module = Module,
data = Data}) ->
Module:flush_transport(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}.
-spec close_transport(#protocol{}) -> ok.
close_transport(#protocol{module = Module,
@ -292,16 +293,16 @@ skip_list_loop(Proto, Map = #protocol_list_begin{etype = Etype,
%%
%% Description:
%%--------------------------------------------------------------------
-spec write(#protocol{}, term()) -> ok | {error, _Reason}.
-spec write(#protocol{}, term()) -> {#protocol{}, ok | {error, _Reason}}.
write(Proto, {{struct, StructDef}, Data})
write(Proto0, {{struct, StructDef}, Data})
when is_list(StructDef), is_tuple(Data), length(StructDef) == size(Data) - 1 ->
[StructName | Elems] = tuple_to_list(Data),
ok = write(Proto, #protocol_struct_begin{name = StructName}),
ok = struct_write_loop(Proto, StructDef, Elems),
ok = write(Proto, struct_end),
ok;
{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};
write(Proto, {{struct, {Module, StructureName}}, Data})
when is_atom(Module),
@ -310,70 +311,74 @@ write(Proto, {{struct, {Module, StructureName}}, Data})
StructType = Module:struct_info(StructureName),
write(Proto, {Module:struct_info(StructureName), Data});
write(Proto, {{list, Type}, Data})
write(Proto0, {{list, Type}, Data})
when is_list(Data) ->
ok = write(Proto,
{Proto1, ok} = write(Proto0,
#protocol_list_begin{
etype = term_to_typeid(Type),
size = length(Data)
}),
lists:foreach(fun(Elem) ->
ok = write(Proto, {Type, Elem})
end,
Data),
ok = write(Proto, list_end),
ok;
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(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, {{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};
write(Proto, {{set, Type}, Data}) ->
write(Proto0, {{set, Type}, Data}) ->
true = sets:is_set(Data),
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;
{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(#protocol{module = Module,
data = ModuleData}, Data) ->
Module:write(ModuleData, Data).
write(Proto = #protocol{module = Module,
data = ModuleData}, Data) ->
{NewData, Result} = Module:write(ModuleData, Data),
{Proto#protocol{data = NewData}, Result}.
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(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);
struct_write_loop(Proto, [], []) ->
ok = write(Proto, field_stop),
ok.
write(Proto, field_stop).