Subversion Repositories SmartDukaan

Rev

Rev 30 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
30 ashish 1
%%
2
%% Licensed to the Apache Software Foundation (ASF) under one
3
%% or more contributor license agreements. See the NOTICE file
4
%% distributed with this work for additional information
5
%% regarding copyright ownership. The ASF licenses this file
6
%% to you under the Apache License, Version 2.0 (the
7
%% "License"); you may not use this file except in compliance
8
%% with the License. You may obtain a copy of the License at
9
%%
10
%%   http://www.apache.org/licenses/LICENSE-2.0
11
%%
12
%% Unless required by applicable law or agreed to in writing,
13
%% software distributed under the License is distributed on an
14
%% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15
%% KIND, either express or implied. See the License for the
16
%% specific language governing permissions and limitations
17
%% under the License.
18
%%
19
 
20
-module(thrift_buffered_transport).
21
 
22
-behaviour(gen_server).
23
-behaviour(thrift_transport).
24
 
25
%% API
26
-export([new/1, new_transport_factory/1]).
27
 
28
%% gen_server callbacks
29
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
30
         terminate/2, code_change/3]).
31
 
32
%% thrift_transport callbacks
33
-export([write/2, read/2, flush/1, close/1]).
34
 
35
-record(buffered_transport, {wrapped, % a thrift_transport
36
                             write_buffer % iolist()
37
                            }).
38
 
39
%%====================================================================
40
%% API
41
%%====================================================================
42
%%--------------------------------------------------------------------
43
%% Function: start_link() -> {ok,Pid} | ignore | {error,Error}
44
%% Description: Starts the server
45
%%--------------------------------------------------------------------
46
new(WrappedTransport) ->
47
    case gen_server:start_link(?MODULE, [WrappedTransport], []) of
48
        {ok, Pid} ->
49
            thrift_transport:new(?MODULE, Pid);
50
        Else ->
51
            Else
52
    end.
53
 
54
 
55
 
56
%%--------------------------------------------------------------------
57
%% Function: write(Transport, Data) -> ok
58
%%
59
%% Data = iolist()
60
%%
61
%% Description: Writes data into the buffer
62
%%--------------------------------------------------------------------
63
write(Transport, Data) ->
64
    gen_server:call(Transport, {write, Data}).
65
 
66
%%--------------------------------------------------------------------
67
%% Function: flush(Transport) -> ok
68
%%
69
%% Description: Flushes the buffer through to the wrapped transport
70
%%--------------------------------------------------------------------
71
flush(Transport) ->
72
    gen_server:call(Transport, flush).
73
 
74
%%--------------------------------------------------------------------
75
%% Function: close(Transport) -> ok
76
%%
77
%% Description: Closes the transport and the wrapped transport
78
%%--------------------------------------------------------------------
79
close(Transport) ->
80
    gen_server:cast(Transport, close).
81
 
82
%%--------------------------------------------------------------------
83
%% Function: Read(Transport, Len) -> {ok, Data}
84
%%
85
%% Data = binary()
86
%%
87
%% Description: Reads data through from the wrapped transoprt
88
%%--------------------------------------------------------------------
89
read(Transport, Len) when is_integer(Len) ->
90
    gen_server:call(Transport, {read, Len}, _Timeout=10000).
91
 
92
%%====================================================================
93
%% gen_server callbacks
94
%%====================================================================
95
 
96
%%--------------------------------------------------------------------
97
%% Function: init(Args) -> {ok, State} |
98
%%                         {ok, State, Timeout} |
99
%%                         ignore               |
100
%%                         {stop, Reason}
101
%% Description: Initiates the server
102
%%--------------------------------------------------------------------
103
init([Wrapped]) ->
104
    {ok, #buffered_transport{wrapped = Wrapped,
105
                             write_buffer = []}}.
106
 
107
%%--------------------------------------------------------------------
108
%% Function: %% handle_call(Request, From, State) -> {reply, Reply, State} |
109
%%                                      {reply, Reply, State, Timeout} |
110
%%                                      {noreply, State} |
111
%%                                      {noreply, State, Timeout} |
112
%%                                      {stop, Reason, Reply, State} |
113
%%                                      {stop, Reason, State}
114
%% Description: Handling call messages
115
%%--------------------------------------------------------------------
116
handle_call({write, Data}, _From, State = #buffered_transport{write_buffer = WBuf}) ->
117
    {reply, ok, State#buffered_transport{write_buffer = [WBuf, Data]}};
118
 
119
handle_call({read, Len}, _From, State = #buffered_transport{wrapped = Wrapped}) ->
120
    Response = thrift_transport:read(Wrapped, Len),
121
    {reply, Response, State};
122
 
123
handle_call(flush, _From, State = #buffered_transport{write_buffer = WBuf,
124
                                                      wrapped = Wrapped}) ->
125
    Response = thrift_transport:write(Wrapped, WBuf),
126
    thrift_transport:flush(Wrapped),
127
    {reply, Response, State#buffered_transport{write_buffer = []}}.
128
 
129
%%--------------------------------------------------------------------
130
%% Function: handle_cast(Msg, State) -> {noreply, State} |
131
%%                                      {noreply, State, Timeout} |
132
%%                                      {stop, Reason, State}
133
%% Description: Handling cast messages
134
%%--------------------------------------------------------------------
135
handle_cast(close, State = #buffered_transport{write_buffer = WBuf,
136
                                               wrapped = Wrapped}) ->
137
    thrift_transport:write(Wrapped, WBuf),
138
    %% Wrapped is closed by terminate/2
139
    %%  error_logger:info_msg("thrift_buffered_transport ~p: closing", [self()]),
140
    {stop, normal, State};
141
handle_cast(Msg, State=#buffered_transport{}) ->
142
    {noreply, State}.
143
 
144
%%--------------------------------------------------------------------
145
%% Function: handle_info(Info, State) -> {noreply, State} |
146
%%                                       {noreply, State, Timeout} |
147
%%                                       {stop, Reason, State}
148
%% Description: Handling all non call/cast messages
149
%%--------------------------------------------------------------------
150
handle_info(_Info, State) ->
151
    {noreply, State}.
152
 
153
%%--------------------------------------------------------------------
154
%% Function: terminate(Reason, State) -> void()
155
%% Description: This function is called by a gen_server when it is about to
156
%% terminate. It should be the opposite of Module:init/1 and do any necessary
157
%% cleaning up. When it returns, the gen_server terminates with Reason.
158
%% The return value is ignored.
159
%%--------------------------------------------------------------------
160
terminate(_Reason, State = #buffered_transport{wrapped=Wrapped}) ->
161
    thrift_transport:close(Wrapped),
162
    ok.
163
 
164
%%--------------------------------------------------------------------
165
%% Func: code_change(OldVsn, State, Extra) -> {ok, NewState}
166
%% Description: Convert process state when code is changed
167
%%--------------------------------------------------------------------
168
code_change(_OldVsn, State, _Extra) ->
169
    {ok, State}.
170
 
171
%%--------------------------------------------------------------------
172
%%% Internal functions
173
%%--------------------------------------------------------------------
174
%%%% FACTORY GENERATION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
175
new_transport_factory(WrapFactory) ->
176
    F = fun() ->
177
                {ok, Wrapped} = WrapFactory(),
178
                new(Wrapped)
179
        end,
180
    {ok, F}.