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_transport_state_test). 21 22-behaviour(gen_server). 23-behaviour(thrift_transport). 24 25%% API 26-export([new/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(trans, {wrapped, % #thrift_transport{} 36 version :: integer(), 37 counter :: pid() 38 }). 39-type state() :: #trans{}. 40-include("thrift_transport_behaviour.hrl"). 41 42-record(state, {cversion :: integer()}). 43 44 45new(WrappedTransport) -> 46 case gen_server:start_link(?MODULE, [], []) of 47 {ok, Pid} -> 48 Trans = #trans{wrapped = WrappedTransport, 49 version = 0, 50 counter = Pid}, 51 thrift_transport:new(?MODULE, Trans); 52 Else -> 53 Else 54 end. 55 56%%==================================================================== 57%% thrift_transport callbacks 58%%==================================================================== 59 60write(Transport0 = #trans{wrapped = Wrapped0}, Data) -> 61 Transport1 = check_version(Transport0), 62 {Wrapped1, Result} = thrift_transport:write(Wrapped0, Data), 63 Transport2 = Transport1#trans{wrapped = Wrapped1}, 64 {Transport2, Result}. 65 66flush(Transport0 = #trans{wrapped = Wrapped0}) -> 67 Transport1 = check_version(Transport0), 68 {Wrapped1, Result} = thrift_transport:flush(Wrapped0), 69 Transport2 = Transport1#trans{wrapped = Wrapped1}, 70 {Transport2, Result}. 71 72close(Transport0 = #trans{wrapped = Wrapped0}) -> 73 Transport1 = check_version(Transport0), 74 shutdown_counter(Transport1), 75 {Wrapped1, Result} = thrift_transport:close(Wrapped0), 76 Transport2 = Transport1#trans{wrapped = Wrapped1}, 77 {Transport2, Result}. 78 79read(Transport0 = #trans{wrapped = Wrapped0}, Len) -> 80 Transport1 = check_version(Transport0), 81 {Wrapped1, Result} = thrift_transport:read(Wrapped0, Len), 82 Transport2 = Transport1#trans{wrapped = Wrapped1}, 83 {Transport2, Result}. 84 85 86%%==================================================================== 87%% gen_server callbacks 88%%==================================================================== 89 90init([]) -> 91 {ok, #state{cversion = 0}}. 92 93handle_call(check_version, _From, State = #state{cversion = Version}) -> 94 {reply, Version, State#state{cversion = Version+1}}. 95 96handle_cast(shutdown, State) -> 97 {stop, normal, State}. 98 99handle_info(_Info, State) -> {noreply, State}. 100code_change(_OldVsn, State, _Extra) -> {ok, State}. 101terminate(_Reason, _State) -> ok. 102 103%%-------------------------------------------------------------------- 104%% Internal functions 105%%-------------------------------------------------------------------- 106 107check_version(Transport = #trans{version = Version, counter = Counter}) -> 108 case gen_server:call(Counter, check_version) of 109 Version -> 110 Transport#trans{version = Version+1}; 111 _Else -> 112 % State wasn't propagated properly. Die. 113 erlang:error(state_not_propagated) 114 end. 115 116shutdown_counter(#trans{counter = Counter}) -> 117 gen_server:cast(Counter, shutdown). 118