From bfc57a04026d9f5b3436baf4452eb262883b7310 Mon Sep 17 00:00:00 2001 From: David Reiss Date: Mon, 30 Mar 2009 20:46:37 +0000 Subject: [PATCH] THRIFT-126. erlang: TMemoryBuffer for Erlang git-svn-id: https://svn.apache.org/repos/asf/incubator/thrift/trunk@760160 13f79535-47bb-0310-9956-ffa450edef68 --- lib/erl/src/thrift_memory_buffer.erl | 152 +++++++++++++++++++++++++++ test/erl/Makefile | 2 +- test/erl/src/test_membuffer.erl | 28 +++++ 3 files changed, 181 insertions(+), 1 deletion(-) create mode 100644 lib/erl/src/thrift_memory_buffer.erl create mode 100644 test/erl/src/test_membuffer.erl diff --git a/lib/erl/src/thrift_memory_buffer.erl b/lib/erl/src/thrift_memory_buffer.erl new file mode 100644 index 00000000..7bfd6ac2 --- /dev/null +++ b/lib/erl/src/thrift_memory_buffer.erl @@ -0,0 +1,152 @@ +%%%------------------------------------------------------------------- +%%% File : thrift_memory_buffer.erl +%%% Author : +%%% Description : In-memory transport for thrift +%%% +%%% Created : 27 Aug 2008 by +%%%------------------------------------------------------------------- +-module(thrift_memory_buffer). + +-behaviour(gen_server). +-behaviour(thrift_transport). + +%% API +-export([new/0, new_transport_factory/0]). + +%% gen_server callbacks +-export([init/1, handle_call/3, handle_cast/2, handle_info/2, + terminate/2, code_change/3]). + +%% thrift_transport callbacks +-export([write/2, read/2, flush/1, close/1]). + +-record(memory_buffer, {buffer}). + +%%==================================================================== +%% API +%%==================================================================== +new() -> + case gen_server:start_link(?MODULE, [], []) of + {ok, Pid} -> + thrift_transport:new(?MODULE, Pid); + Else -> + Else + end. + +new_transport_factory() -> + {ok, fun() -> new() end}. + +%%-------------------------------------------------------------------- +%% Function: write(Transport, Data) -> ok +%% +%% Data = iolist() +%% +%% Description: Writes data into the buffer +%%-------------------------------------------------------------------- +write(Transport, Data) -> + gen_server:call(Transport, {write, Data}). + +%%-------------------------------------------------------------------- +%% Function: flush(Transport) -> ok +%% +%% Description: Flushes the buffer through to the wrapped transport +%%-------------------------------------------------------------------- +flush(Transport) -> + gen_server:call(Transport, flush). + +%%-------------------------------------------------------------------- +%% Function: close(Transport) -> ok +%% +%% Description: Closes the transport and the wrapped transport +%%-------------------------------------------------------------------- +close(Transport) -> + gen_server:cast(Transport, close). + +%%-------------------------------------------------------------------- +%% Function: Read(Transport, Len) -> {ok, Data} +%% +%% Data = binary() +%% +%% Description: Reads data through from the wrapped transoprt +%%-------------------------------------------------------------------- +read(Transport, Len) when is_integer(Len) -> + gen_server:call(Transport, {read, Len}). + +%%==================================================================== +%% gen_server callbacks +%%==================================================================== + +%%-------------------------------------------------------------------- +%% Function: init(Args) -> {ok, State} | +%% {ok, State, Timeout} | +%% ignore | +%% {stop, Reason} +%% Description: Initiates the server +%%-------------------------------------------------------------------- +init([]) -> + {ok, #memory_buffer{buffer = []}}. + +%%-------------------------------------------------------------------- +%% Function: %% handle_call(Request, From, State) -> {reply, Reply, State} | +%% {reply, Reply, State, Timeout} | +%% {noreply, State} | +%% {noreply, State, Timeout} | +%% {stop, Reason, Reply, State} | +%% {stop, Reason, State} +%% Description: Handling call messages +%%-------------------------------------------------------------------- +handle_call({write, Data}, _From, State = #memory_buffer{buffer = Buf}) -> + {reply, ok, State#memory_buffer{buffer = [Buf, Data]}}; + +handle_call({read, Len}, _From, State = #memory_buffer{buffer = Buf}) -> + Binary = iolist_to_binary(Buf), + Give = min(iolist_size(Binary), Len), + {Result, Remaining} = split_binary(Binary, Give), + {reply, {ok, Result}, State#memory_buffer{buffer = Remaining}}; + +handle_call(flush, _From, State) -> + {reply, ok, State}. + +%%-------------------------------------------------------------------- +%% Function: handle_cast(Msg, State) -> {noreply, State} | +%% {noreply, State, Timeout} | +%% {stop, Reason, State} +%% Description: Handling cast messages +%%-------------------------------------------------------------------- +handle_cast(close, State) -> + {stop, normal, State}; +handle_cast(Msg, State=#memory_buffer{}) -> + {noreply, State}. + +%%-------------------------------------------------------------------- +%% Function: handle_info(Info, State) -> {noreply, State} | +%% {noreply, State, Timeout} | +%% {stop, Reason, State} +%% Description: Handling all non call/cast messages +%%-------------------------------------------------------------------- +handle_info(_Info, State) -> + {noreply, State}. + +%%-------------------------------------------------------------------- +%% Function: terminate(Reason, State) -> void() +%% Description: This function is called by a gen_server when it is about to +%% terminate. It should be the opposite of Module:init/1 and do any necessary +%% cleaning up. When it returns, the gen_server terminates with Reason. +%% The return value is ignored. +%%-------------------------------------------------------------------- +terminate(_Reason, _State) -> + ok. + +%%-------------------------------------------------------------------- +%% Func: code_change(OldVsn, State, Extra) -> {ok, NewState} +%% Description: Convert process state when code is changed +%%-------------------------------------------------------------------- +code_change(_OldVsn, State, _Extra) -> + {ok, State}. + +%%-------------------------------------------------------------------- +%%% Internal functions +%%-------------------------------------------------------------------- +min(A,B) when A A; +min(_,B) -> B. + diff --git a/test/erl/Makefile b/test/erl/Makefile index 037e6fff..992d78cf 100644 --- a/test/erl/Makefile +++ b/test/erl/Makefile @@ -10,7 +10,7 @@ SRCDIR=src ALL_INCLUDEDIR=$(GEN_INCLUDEDIR) $(INCLUDEDIR) ../../lib/erl/include INCLUDEFLAGS=$(patsubst %,-I%, ${ALL_INCLUDEDIR}) -MODULES = stress_server test_server test_disklog +MODULES = stress_server test_server test_disklog test_membuffer INCLUDES = TARGETS = $(patsubst %,${TARGETDIR}/%.beam,${MODULES}) diff --git a/test/erl/src/test_membuffer.erl b/test/erl/src/test_membuffer.erl new file mode 100644 index 00000000..dd900c61 --- /dev/null +++ b/test/erl/src/test_membuffer.erl @@ -0,0 +1,28 @@ +-module(test_membuffer). +-export([t/0]). + +-include("thriftTest_types.hrl"). + +test_data() -> + #xtruct{string_thing = <<"foobar">>, + byte_thing = 123, + i32_thing = 1234567, + i64_thing = 12345678900}. + +t1() -> + {ok, Transport} = thrift_memory_buffer:new(), + {ok, Protocol} = thrift_binary_protocol:new(Transport), + TestData = test_data(), + ok = thrift_protocol:write(Protocol, + {{struct, element(2, thriftTest_types:struct_info('xtruct'))}, + TestData}), + {ok, Result} = thrift_protocol:read(Protocol, + {struct, element(2, thriftTest_types:struct_info('xtruct'))}, + 'xtruct'), + + Result = TestData. + + +t() -> + t1(). + -- 2.17.1