dev client pool
diff --git a/include/dubbo.hrl b/include/dubbo.hrl
index ad2277a..727c71e 100644
--- a/include/dubbo.hrl
+++ b/include/dubbo.hrl
@@ -102,7 +102,7 @@
-record(interface_list, {interface, pid, connection_info}).
--record(provider_node_list, {host_flag, connection_info}).
+-record(provider_node_list, {host_flag, pid, weight, readonly = false}).
-record(connection_info, {connection_id, pid, weight, host_flag, readonly = false}).
-type dubbo_request() :: #dubbo_request{}.
diff --git a/src/dubbo_client_default.erl b/src/dubbo_client_default.erl
new file mode 100644
index 0000000..220c30f
--- /dev/null
+++ b/src/dubbo_client_default.erl
@@ -0,0 +1,431 @@
+%%------------------------------------------------------------------------------
+%% 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.
+%%------------------------------------------------------------------------------
+-module(dubbo_client_default).
+
+-behaviour(gen_server).
+
+
+-include("dubbo.hrl").
+
+%% gen_server callbacks
+-export([init/1,
+ handle_call/3,
+ handle_cast/2,
+ handle_info/2,
+ terminate/2,
+ code_change/3]).
+-export([start_link/1]).
+
+-export([check_recv_data/2]).
+
+-define(SERVER, ?MODULE).
+
+-record(heartbeat, {last_write = 0, last_read = 0, timeout = 60000, max_timeout = 180000}).
+-record(state, {provider_config, socket = undefined,
+ heartbeat = #heartbeat{},
+ recv_buffer = <<>>, %%从服务端接收的数据
+ host_flag,
+ reconnection_timer,
+ handler
+}).
+
+%%%===================================================================
+%%% API
+%%%===================================================================
+
+%%--------------------------------------------------------------------
+%% @doc
+%% Starts the server
+%%
+%% @end
+%%--------------------------------------------------------------------
+-spec(start_link(Name :: binary(), ProviderConfig :: #provider_config{}) ->
+ {ok, Pid :: pid()} | ignore | {error, Reason :: term()}).
+start_link(ProviderConfig) ->
+ gen_server:start_link(?MODULE, [ProviderConfig], []).
+
+%%%===================================================================
+%%% gen_server callbacks
+%%%===================================================================
+
+%%--------------------------------------------------------------------
+%% @private
+%% @doc
+%% Initializes the server
+%%
+%% @spec init(Args) -> {ok, State} |
+%% {ok, State, Timeout} |
+%% ignore |
+%% {stop, Reason}
+%% @end
+%%--------------------------------------------------------------------
+-spec(init(Args :: term()) ->
+ {ok, State :: #state{}} | {ok, State :: #state{}, timeout() | hibernate} |
+ {stop, Reason :: term()} | ignore).
+init([HostFlag, ProviderConfig]) ->
+ #provider_config{host = Host, port = Port} = ProviderConfig,
+ State = case open(Host, Port) of
+ {ok, Socket} ->
+ #state{socket = Socket};
+ {error, _Reason} ->
+ #state{}
+ end,
+ NowStamp = dubbo_time_util:timestamp_ms(),
+ HeartBeatInfo = #heartbeat{last_read = NowStamp, last_write = NowStamp},
+ logger:info("netty client start ~p", [HostFlag]),
+ start_heartbeat_timer(HeartBeatInfo),
+ {ok, State#state{provider_config = ProviderConfig, heartbeat = HeartBeatInfo, host_flag = HostFlag}}.
+
+%%--------------------------------------------------------------------
+%% @private
+%% @doc
+%% Handling call messages
+%%
+%% @end
+%%--------------------------------------------------------------------
+-spec(handle_call(Request :: term(), From :: {pid(), Tag :: term()},
+ State :: #state{}) ->
+ {reply, Reply :: term(), NewState :: #state{}} |
+ {reply, Reply :: term(), NewState :: #state{}, timeout() | hibernate} |
+ {noreply, NewState :: #state{}} |
+ {noreply, NewState :: #state{}, timeout() | hibernate} |
+ {stop, Reason :: term(), Reply :: term(), NewState :: #state{}} |
+ {stop, Reason :: term(), NewState :: #state{}}).
+handle_call(_Request, _From, State) ->
+ {reply, ok, State}.
+
+%%--------------------------------------------------------------------
+%% @private
+%% @doc
+%% Handling cast messages
+%%
+%% @end
+%%--------------------------------------------------------------------
+-spec(handle_cast(Request :: term(), State :: #state{}) ->
+ {noreply, NewState :: #state{}} |
+ {noreply, NewState :: #state{}, timeout() | hibernate} |
+ {stop, Reason :: term(), NewState :: #state{}}).
+
+handle_cast({send_request, Ref, Request, Data, SourcePid, RequestState}, State) ->
+ logger:debug("[send_request begin] send data to provider consumer mid ~p pid ~p sourcePid ~p", [Request#dubbo_request.mid, self(), SourcePid]),
+ NewState = case send_msg(Data, State) of
+ ok ->
+ save_request_info(Request, SourcePid, Ref, RequestState),
+ logger:debug("[send_request end] send data to provider consumer pid ~p state ok", [self()]),
+ State;
+ {error, closed} ->
+ logger:warning("send request error, connection is closed"),
+ State2 = reconnect(State),
+ State2;
+ {error, R1} ->
+ logger:error("[send_request end] send data to provider consumer pid error ~p ~p", [self(), R1]),
+ State
+ end,
+ HeartbeatInfo = update_heartbeat(write, NewState#state.heartbeat),
+ {noreply, NewState#state{heartbeat = HeartbeatInfo}};
+
+handle_cast(_Request, State) ->
+ {noreply, State}.
+
+%%--------------------------------------------------------------------
+%% @private
+%% @doc
+%% Handling all non call/cast messages
+%%
+%% @spec handle_info(Info, State) -> {noreply, State} |
+%% {noreply, State, Timeout} |
+%% {stop, Reason, State}
+%% @end
+%%--------------------------------------------------------------------
+-spec(handle_info(Info :: timeout() | term(), State :: #state{}) ->
+ {noreply, NewState :: #state{}} |
+ {noreply, NewState :: #state{}, timeout() | hibernate} |
+ {stop, Reason :: term(), NewState :: #state{}}).
+
+
+handle_info({tcp, _Port, Data}, #state{recv_buffer = RecvBuffer} = State) ->
+%% inet:setopts(State#state.socket, [{active, once}]),
+%% logger:debug("[INFO] recv one data ~w",[Data]),
+ {ok, NextBuffer, NewState} = case check_recv_data(<<RecvBuffer/binary, Data/binary>>, State) of
+ {next_buffer, NextBuffer2, State3} ->
+ logger:debug("[INFO] recv one data state wait next_buffer"),
+ {ok, NextBuffer2, State3}
+ end,
+%% HeartbeatInfo =update_heartbeat(write,NewState#state.heartbeat),
+ {noreply, NewState#state{recv_buffer = NextBuffer}};
+handle_info({tcp_closed, Port}, State) ->
+ logger:info("dubbo connection closed ~p", [Port]),
+ NewState = reconnect(State),
+ {noreply, NewState};
+handle_info({timeout, _TimerRef, {reconnect}}, State) ->
+ NewState = reconnect(State#state{reconnection_timer = undefined}),
+ {noreply, NewState};
+handle_info({timeout, _TimerRef, {heartbeat_timer}}, State) ->
+ {ok, NewState} = case check_heartbeat_state(State) of
+ {normal} -> {ok, State};
+ {send_heart} ->
+ send_heartbeat_msg(undefined, true, State);
+ {reconnect} ->
+ %% @todo reconnect
+ {ok, State}
+ end,
+ HeartbeatInfo = update_heartbeat(write, NewState#state.heartbeat),
+ start_heartbeat_timer(HeartbeatInfo),
+ {noreply, NewState#state{heartbeat = HeartbeatInfo}};
+handle_info(_Info, State) ->
+ logger:warning("[INFO] get one info:~p", [_Info]),
+%% inet:setopts(State#state.socket, [{active, once}]),
+%% case State#state.tmp_pid of
+%% undefined ->ok;
+%% Pid ->
+%% gen_server:cast(Pid,{msg_back})
+%% end,
+ HeartbeatInfo = update_heartbeat(write, State#state.heartbeat),
+ {noreply, State#state{heartbeat = HeartbeatInfo}}.
+
+%%--------------------------------------------------------------------
+%% @private
+%% @doc
+%% 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.
+%%
+%% @spec terminate(Reason, State) -> void()
+%% @end
+%%--------------------------------------------------------------------
+-spec(terminate(Reason :: (normal | shutdown | {shutdown, term()} | term()),
+ State :: #state{}) -> term()).
+terminate(_Reason, _State) ->
+ logger:warning("terminate reason:~p", [_Reason]),
+ ok.
+
+%%--------------------------------------------------------------------
+%% @private
+%% @doc
+%% Convert process state when code is changed
+%%
+%% @spec code_change(OldVsn, State, Extra) -> {ok, NewState}
+%% @end
+%%--------------------------------------------------------------------
+-spec(code_change(OldVsn :: term() | {down, term()}, State :: #state{},
+ Extra :: term()) ->
+ {ok, NewState :: #state{}} | {error, Reason :: term()}).
+code_change(_OldVsn, State, _Extra) ->
+ {ok, State}.
+
+%%%===================================================================
+%%% Internal functions
+%%%===================================================================
+
+open(Host, Port) ->
+ logger:debug("will connect to provider ~p ~p", [Host, Port]),
+ %
+ case gen_tcp:connect(Host, Port, [
+ binary,
+ {packet, 0}, {active, false},
+ {reuseaddr, true},
+ {delay_send, true},
+ {nodelay, true},
+ {high_watermark, 512 * 1024},
+ {low_watermark, 256 * 1024},
+ {sndbuf, 512 * 1024},
+ {recbuf, 512 * 1024}
+ ]) of
+ {ok, Sockets} ->
+ inet:setopts(Sockets, [{active, true}]),
+ {ok, Sockets};
+ Info ->
+ logger:error("start client connection error ~p", [Info]),
+ {error, Info}
+ end.
+
+reconnect(#state{reconnection_timer = Timer} = State) when Timer /= undefined ->
+ State;
+reconnect(State) ->
+ #provider_config{host = Host, port = Port} = State#state.provider_config,
+ case State#state.socket of
+ undefined -> ok;
+ Socket ->
+ gen_tcp:close(Socket)
+ end,
+ case open(Host, Port) of
+ {ok, Socket2} ->
+ logger:warning("reconnect to provider ~p ~p success", [Host, Port]),
+ State#state{socket = Socket2, recv_buffer = <<>>};
+ {error, Reason} ->
+ logger:warning("connect to provider error ~p", [Reason]),
+ TimerRef = erlang:start_timer(2000, self(), {reconnect}),
+ State#state{socket = undefined, reconnection_timer = TimerRef}
+ end.
+
+send_msg(Msg, State) ->
+ case State#state.socket of
+ undefined ->
+ {error, closed};
+ Socket ->
+ case gen_tcp:send(Socket, Msg) of
+ ok ->
+ ok;
+ {error, Reason} ->
+ logger:error("send to server error,reason:~p", [Reason]),
+ {error, Reason}
+ end
+ end.
+
+%%%=================================================================
+%%% 心跳检测
+%%%=================================================================
+start_heartbeat_timer(HeartbeatInfo) ->
+ erlang:start_timer(HeartbeatInfo#heartbeat.timeout, self(), {heartbeat_timer}),
+ ok.
+update_heartbeat(write, Info) ->
+ Info#heartbeat{last_write = dubbo_time_util:timestamp_ms()};
+update_heartbeat(read, Info) ->
+ Info#heartbeat{last_read = dubbo_time_util:timestamp_ms()}.
+
+
+check_heartbeat_state(#state{heartbeat = HeartBeatInfo} = _State) ->
+ Now = dubbo_time_util:timestamp_ms(),
+ #heartbeat{last_read = LastRead, last_write = LastWrite, timeout = Timeout, max_timeout = MaxTimeout} = HeartBeatInfo,
+ if
+ (Now - LastRead) > Timeout ->
+ {send_heart};
+ (Now - LastWrite) > Timeout ->
+ {send_heart};
+ (Now - LastRead) > MaxTimeout ->
+ {reconnect};
+ true ->
+ {normal}
+ end.
+
+
+send_heartbeat_msg(Mid, NeedResponse, State) ->
+ {ok, Bin} = dubbo_heartbeat:generate_request(Mid, NeedResponse),
+ NewState = case send_msg(Bin, State) of
+ ok ->
+ logger:info("send one heartbeat to server"),
+ State;
+ {error, Reason} ->
+ logger:warning("dubbo connection send heartbeat error ~p", [Reason]),
+ State2 = reconnect(State),
+ State2
+ end,
+ {ok, NewState}.
+
+%%%=================================================================
+%%% 接收数据处理
+%%%=================================================================
+-spec check_recv_data(Data :: binary(), State :: #state{}) -> {ready, ReadyData :: binary()} | {ready, ReadyData :: binary(), NextBuffer :: binary()}.
+check_recv_data(<<?DUBBO_MEGIC_HIGH, ?DUBBO_MEGIC_LOW, Rest/binary>> = Data, State) when byte_size(Rest) < 14 ->
+ {next_buffer, Data, State};
+check_recv_data(<<?DUBBO_MEGIC_HIGH, ?DUBBO_MEGIC_LOW, _OtherFlag:80, DataLen:32, Rest/binary>> = Data, State) ->
+ RestSize = byte_size(Rest),
+ if
+ DataLen == RestSize ->
+ {ok, State2} = process_data(Data, State),
+ {next_buffer, <<>>, State2};
+ DataLen > RestSize ->
+ logger:warning("need wait next buffer data ~p", [Data]),
+ {next_buffer, Data, State};
+ DataLen < RestSize ->
+ <<ReadyData:DataLen/binary, NextBuffer/binary>> = Rest,
+ OneData = <<?DUBBO_MEGIC_HIGH:8, ?DUBBO_MEGIC_LOW:8, _OtherFlag:80, DataLen:32, ReadyData/binary>>,
+ {ok, State3} = process_data(OneData, State),
+%% logger:warning("recevi more data ~w ",[NextBuffer]),
+ check_recv_data(NextBuffer, State3)
+ end;
+check_recv_data(<<Error/integer, Data/binary>>, State) ->
+ logger:error("recv bad header data,Begin Byte:~p", [Error]),
+ check_recv_data(Data, State);
+check_recv_data(<<>>, State) ->
+ {next_buffer, <<>>, State}.
+
+
+process_data(Data, State) ->
+ <<Header:16/binary, RestData/binary>> = Data,
+ case dubbo_codec:decode_header(Header) of
+ {ok, response, ResponseInfo} ->
+ process_response(ResponseInfo#dubbo_response.is_event, ResponseInfo, RestData, State),
+%% dubbo_traffic_control:decr_count(State#state.host_flag),
+%% case get_earse_request_info(ResponseInfo#dubbo_response.mid) of
+%% undefined->
+%% logger:error("dubbo response can't find request data,response ~p",[ResponseInfo]);
+%% {SourcePid,Ref,_RequestState} ->
+%% {ok,Res} = dubbo_codec:decode_response(ResponseInfo,RestData),
+%%
+%% logger:info("got one response mid ~p, is_event ~p state ~p",[Res#dubbo_response.mid,Res#dubbo_response.is_event,Res#dubbo_response.state]),
+%% case Res#dubbo_response.is_event of
+%% false ->
+%% %% todo rpccontent need merge response with request
+%% RpcContent=[],
+%% ResponseData = dubbo_type_transfer:response_to_native(Res),
+%% gen_server:cast(SourcePid,{response_process,Ref,RpcContent,ResponseData});
+%% _->
+%% ok
+%% end
+%% end,
+ {ok, State};
+ {ok, request, RequestInfo} ->
+ {ok, Req} = dubbo_codec:decode_request(RequestInfo, RestData),
+ logger:info("get one request mid ~p, is_event ~p", [Req#dubbo_request.mid, Req#dubbo_request.is_event]),
+ {ok, State2} = process_request(Req#dubbo_request.is_event, Req, State),
+ {ok, State2};
+ {error, Type, RelData} ->
+ logger:error("process_data error type ~p RelData ~p", [Type, RelData]),
+ {ok, State}
+ end.
+
+
+%% @doc process event
+-spec process_response(IsEvent :: boolean(), #dubbo_response{}, #state{}, term()) -> ok.
+process_response(false, ResponseInfo, RestData, State) ->
+ dubbo_traffic_control:decr_count(State#state.host_flag),
+ case get_earse_request_info(ResponseInfo#dubbo_response.mid) of
+ undefined ->
+ logger:error("dubbo response can't find request data,response ~p", [ResponseInfo]);
+ {SourcePid, Ref, _RequestState} ->
+ {ok, Res} = dubbo_codec:decode_response(ResponseInfo, RestData),
+ logger:info("got one response mid ~p, is_event ~p state ~p", [Res#dubbo_response.mid, Res#dubbo_response.is_event, Res#dubbo_response.state]),
+ case Res#dubbo_response.is_event of
+ false ->
+ %% todo rpccontent need merge response with request
+ RpcContent = [],
+ ResponseData = dubbo_type_transfer:response_to_native(Res),
+ gen_server:cast(SourcePid, {response_process, Ref, RpcContent, ResponseData});
+ _ ->
+ ok
+ end
+ end,
+ {ok, State};
+process_response(true, _ResponseInfo, _RestData, State) ->
+ {ok, State}.
+
+process_request(true, #dubbo_request{data = <<"R">>}, State) ->
+ {ok, _} = dubbo_provider_consumer_reg_table:update_connection_readonly(self(), true),
+ {ok, State};
+process_request(true, Request, State) ->
+ {ok, NewState} = send_heartbeat_msg(Request#dubbo_request.mid, false, State),
+ {ok, NewState};
+process_request(false, Request, State) ->
+ {ok, State}.
+
+
+save_request_info(Request, SourcePid, Ref, RequestState) ->
+ put(Request#dubbo_request.mid, {SourcePid, Ref, RequestState}).
+get_earse_request_info(Mid) ->
+ erase(Mid).
\ No newline at end of file
diff --git a/src/dubbo_consumer_pool.erl b/src/dubbo_consumer_pool.erl
deleted file mode 100644
index 0a01d38..0000000
--- a/src/dubbo_consumer_pool.erl
+++ /dev/null
@@ -1,305 +0,0 @@
-%%------------------------------------------------------------------------------
-%% 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.
-%%------------------------------------------------------------------------------
--module(dubbo_consumer_pool).
-
--behaviour(gen_server).
-
-%% API
--export([start_link/0, start_consumer/2]).
-
-%% gen_server callbacks
--export([init/1,
- handle_call/3,
- handle_cast/2,
- handle_info/2,
- terminate/2,
- code_change/3]).
-
--export([select_connection/1, select_connection/2, update_connection_readonly/2]).
-
--include("dubbo.hrl").
--define(SERVER, ?MODULE).
-
--define(INTERFCE_LIST_TABLE, interface_list).
--define(PROVIDER_NODE_LIST_TABLE, provider_node_list).
-
--record(state, {}).
-
--ifdef(TEST).
--compile([export_all]).
--endif.
-
-
-%%%===================================================================
-%%% API
-%%%===================================================================
-
-%%--------------------------------------------------------------------
-%% @doc
-%% Starts the server
-%%
-%% @end
-%%--------------------------------------------------------------------
--spec(start_link() ->
- {ok, Pid :: pid()} | ignore | {error, Reason :: term()}).
-start_link() ->
- gen_server:start_link({local, ?SERVER}, ?MODULE, [], []).
-
-%%%===================================================================
-%%% gen_server callbacks
-%%%===================================================================
-
-%%--------------------------------------------------------------------
-%% @private
-%% @doc
-%% Initializes the server
-%%
-%% @spec init(Args) -> {ok, State} |
-%% {ok, State, Timeout} |
-%% ignore |
-%% {stop, Reason}
-%% @end
-%%--------------------------------------------------------------------
--spec(init(Args :: term()) ->
- {ok, State :: #state{}} | {ok, State :: #state{}, timeout() | hibernate} |
- {stop, Reason :: term()} | ignore).
-init([]) ->
- init_ets_table(),
- {ok, #state{}}.
-init_ets_table() ->
- try ets:new(?INTERFCE_LIST_TABLE, [bag, public, named_table, {keypos, 2}]) of
- ?INTERFCE_LIST_TABLE ->
- ok
- catch
- _Type:Reason ->
- logger:error("new ets table error ~p", [Reason]),
- error
- end,
- try ets:new(?PROVIDER_NODE_LIST_TABLE, [bag, public, named_table, {keypos, 2}]) of
- ?PROVIDER_NODE_LIST_TABLE ->
- ok
- catch
- _Type1:Reason1 ->
- logger:error("new ets table error ~p", [Reason1]),
- error
- end,
- ok.
-%%--------------------------------------------------------------------
-%% @private
-%% @doc
-%% Handling call messages
-%%
-%% @end
-%%--------------------------------------------------------------------
--spec(handle_call(Request :: term(), From :: {pid(), Tag :: term()},
- State :: #state{}) ->
- {reply, Reply :: term(), NewState :: #state{}} |
- {reply, Reply :: term(), NewState :: #state{}, timeout() | hibernate} |
- {noreply, NewState :: #state{}} |
- {noreply, NewState :: #state{}, timeout() | hibernate} |
- {stop, Reason :: term(), Reply :: term(), NewState :: #state{}} |
- {stop, Reason :: term(), NewState :: #state{}}).
-
-handle_call({add_consumer, Interface, ProviderNodeList}, _From, State) ->
-
- OldProviderList = get_interface_provider_node(Interface),
- NewProviderList = add_consumer(ProviderNodeList, []),
- DeleteProverList = OldProviderList -- NewProviderList,
- clean_invalid_provider(DeleteProverList),
- {reply, ok, State};
-handle_call(_Request, _From, State) ->
- {reply, ok, State}.
-
-%%--------------------------------------------------------------------
-%% @private
-%% @doc
-%% Handling cast messages
-%%
-%% @end
-%%--------------------------------------------------------------------
--spec(handle_cast(Request :: term(), State :: #state{}) ->
- {noreply, NewState :: #state{}} |
- {noreply, NewState :: #state{}, timeout() | hibernate} |
- {stop, Reason :: term(), NewState :: #state{}}).
-handle_cast(_Request, State) ->
- {noreply, State}.
-
-%%--------------------------------------------------------------------
-%% @private
-%% @doc
-%% Handling all non call/cast messages
-%%
-%% @spec handle_info(Info, State) -> {noreply, State} |
-%% {noreply, State, Timeout} |
-%% {stop, Reason, State}
-%% @end
-%%--------------------------------------------------------------------
--spec(handle_info(Info :: timeout() | term(), State :: #state{}) ->
- {noreply, NewState :: #state{}} |
- {noreply, NewState :: #state{}, timeout() | hibernate} |
- {stop, Reason :: term(), NewState :: #state{}}).
-handle_info(_Info, State) ->
- {noreply, State}.
-
-%%--------------------------------------------------------------------
-%% @private
-%% @doc
-%% 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.
-%%
-%% @spec terminate(Reason, State) -> void()
-%% @end
-%%--------------------------------------------------------------------
--spec(terminate(Reason :: (normal | shutdown | {shutdown, term()} | term()),
- State :: #state{}) -> term()).
-terminate(_Reason, _State) ->
- ok.
-
-%%--------------------------------------------------------------------
-%% @private
-%% @doc
-%% Convert process state when code is changed
-%%
-%% @spec code_change(OldVsn, State, Extra) -> {ok, NewState}
-%% @end
-%%--------------------------------------------------------------------
--spec(code_change(OldVsn :: term() | {down, term()}, State :: #state{},
- Extra :: term()) ->
- {ok, NewState :: #state{}} | {error, Reason :: term()}).
-code_change(_OldVsn, State, _Extra) ->
- {ok, State}.
-
-start_consumer(Interface, ProviderNodeInfo) ->
- gen_server:call(?SERVER, {add_consumer, Interface, ProviderNodeInfo}).
-
-
-%%%===================================================================
-%%% Internal functions
-%%%===================================================================
-add_consumer([], RegisterList) ->
- RegisterList;
-add_consumer([ProviderNodeInfo | ProviderList], RegisterList) ->
- case dubbo_node_config_util:parse_provider_info(ProviderNodeInfo) of
- {ok, ProviderConfig} ->
- HostFlag = get_host_flag(ProviderConfig),
- case ets:lookup(?PROVIDER_NODE_LIST_TABLE, HostFlag) of
- [] ->
- ConnectionList = start_provider_process(HostFlag, 30, ProviderConfig),
- ok = update_connection_info(ProviderConfig#provider_config.interface, HostFlag, ConnectionList, true),
- ok;
- List ->
- List2 = lists:map(fun(#provider_node_list{connection_info = ConnectionItem}) ->
- ConnectionItem
- end, List),
- ok = update_connection_info(ProviderConfig#provider_config.interface, HostFlag, List2, false),
- ok
- end,
- add_consumer(ProviderList, [HostFlag] ++ RegisterList);
- {error, R1} ->
- logger:error("parse provider info error reason ~p", [R1]),
- add_consumer(ProviderList, RegisterList)
- end.
-
-start_provider_process(HostFlag, Weight, ProviderConfig) ->
- ExecutesList = lists:seq(1, ProviderConfig#provider_config.executes),
- ConnectionList = lists:map(fun(Item) ->
- ConnectionFlag = <<HostFlag/binary, (integer_to_binary(Item))/binary>>,
- ConnectionFlagTerm = binary_to_atom(ConnectionFlag, utf8),
- AChild = {ConnectionFlagTerm, {dubbo_netty_client, start_link, [ConnectionFlagTerm, HostFlag, ProviderConfig, Item]}, permanent, 2000, worker, [dubbo_netty_client]},
- {ok, Pid} = dubbo_consumer_pool_sup:add_children(AChild),
- logger:info("start provider ~p pid info ~p~n", [HostFlag, Pid]),
- #connection_info{connection_id = ConnectionFlagTerm, pid = Pid, weight = Weight, host_flag = HostFlag}
- end, ExecutesList),
- ConnectionList.
-get_host_flag(ProviderConfig) ->
- HostFlag = <<(list_to_binary(ProviderConfig#provider_config.host))/binary, <<"_">>/binary, (integer_to_binary(ProviderConfig#provider_config.port))/binary>>,
- HostFlag.
-
-update_connection_info(Interface, HostFlag, ConnectionList, IsUpdateProvideNode) ->
- lists:map(fun(Item) ->
- I1 = ets:insert(?INTERFCE_LIST_TABLE, #interface_list{interface = Interface, pid = Item#connection_info.pid, connection_info = Item}),
- logger:debug("insert interface conection info ~p ~p ~p", [Interface, Item#connection_info.pid, I1]),
- case IsUpdateProvideNode of
- true ->
- I2 = ets:insert(?PROVIDER_NODE_LIST_TABLE, #provider_node_list{host_flag = HostFlag, connection_info = Item}),
- logger:debug("insert PROVIDER_NODE_LIST_TABLE ~p info:~p", [HostFlag, I2]);
- false ->
- ok
- end,
- ok
- end, ConnectionList),
- ok.
-
-get_interface_provider_node(Interface) ->
- case ets:lookup(?INTERFCE_LIST_TABLE, Interface) of
- [] ->
- [];
- List ->
- ListRet = [Item#interface_list.connection_info#connection_info.host_flag || Item <- List],
- dubbo_lists_util:del_duplicate(ListRet)
- end.
-
-select_connection(Interface) ->
- RandNum = rand:uniform(2048),
- select_connection(Interface, RandNum).
-select_connection(Interface, RandNum) ->
- case ets:lookup(?INTERFCE_LIST_TABLE, Interface) of
- [] ->
- {error, none};
- List ->
- Len = length(List),
- RemNum = (RandNum rem Len) + 1,
- InterfaceListItem = lists:nth(RemNum, List),
- {ok, InterfaceListItem#interface_list.connection_info}
- end.
-
--spec(update_connection_readonly(pid(), boolean()) -> ok).
-update_connection_readonly(ConnectionPid, Readonly) ->
- Pattern = #interface_list{pid = ConnectionPid, _ = '_'},
- Objects = ets:match_object(?INTERFCE_LIST_TABLE, Pattern),
- lists:map(fun(#interface_list{interface = Interface, pid = Pid, connection_info = ConnectionInfo} = InterferConnection) ->
- logger:debug("[dubbo] update interface ~p ~p readonly", [Interface, Pid]),
- NewConnectionInfo = ConnectionInfo#connection_info{readonly = Readonly},
- NewObject = InterferConnection#interface_list{connection_info = NewConnectionInfo},
- ets:delete_object(?INTERFCE_LIST_TABLE, InterferConnection),
- ets:insert(?INTERFCE_LIST_TABLE, NewObject)
- end, Objects),
- {ok, length(Objects)}.
-
-clean_invalid_provider([]) ->
- ok;
-clean_invalid_provider([HostFlag | DeleteProverList]) ->
- case ets:lookup(?PROVIDER_NODE_LIST_TABLE, HostFlag) of
- [] ->
- ok;
- ProviderNodeList ->
- ProviderNodeList1 = dubbo_lists_util:del_duplicate(ProviderNodeList),
- clean_connection_info(ProviderNodeList1)
- end,
- clean_invalid_provider(DeleteProverList).
-
-clean_connection_info(ProviderNodeList) ->
- lists:map(fun(Item) ->
- Pid = Item#provider_node_list.connection_info#connection_info.pid,
- ConnectionId = Item#provider_node_list.connection_info#connection_info.connection_id,
- Pattern = #interface_list{pid = Pid, _ = '_'},
- ets:delete_object(?INTERFCE_LIST_TABLE, Pattern),
- dubbo_consumer_pool_sup:stop_children(ConnectionId)
- end, ProviderNodeList),
- ok.
\ No newline at end of file
diff --git a/src/dubbo_exchanger.erl b/src/dubbo_exchanger.erl
new file mode 100644
index 0000000..09a4833
--- /dev/null
+++ b/src/dubbo_exchanger.erl
@@ -0,0 +1,40 @@
+%%------------------------------------------------------------------------------
+%% 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.
+%%------------------------------------------------------------------------------
+-module(dubbo_exchanger).
+
+-include("dubbo.hrl").
+
+%% API
+-export([connect/2]).
+
+connect(Url,Handler) ->
+ case dubbo_node_config_util:parse_provider_info(Url) of
+ {ok, ProviderConfig} ->
+ HostFlag= dubbo_provider_consumer_reg_table:get_host_flag(ProviderConfig),
+ {ok, Pid} = dubbo_transport_pool_sup:add_children(ProviderConfig,Handler),
+ logger:info("start provider ~p pid info ~p~n", [HostFlag, Pid]),
+ {ok,#connection_info{ pid = Pid, weight = get_weight(ProviderConfig), host_flag = HostFlag}};
+ {error, R1} ->
+ logger:error("parse provider info error reason ~p", [R1]),
+ {error,R1}
+ end.
+
+
+
+get_weight(_ProviderConfig)->
+ %% todo get weight from provider info
+ 30.
\ No newline at end of file
diff --git a/src/dubbo_invoker_old.erl b/src/dubbo_invoker_old.erl
index c878656..354cef9 100644
--- a/src/dubbo_invoker_old.erl
+++ b/src/dubbo_invoker_old.erl
@@ -40,7 +40,7 @@
{ok, reference(), Data :: any(), RpcContent :: list()}|
{error, Reason :: timeout|no_provider|request_full|any()}.
invoke_request(Interface, Request, RpcContext, RequestState, CallBackPid) ->
- case dubbo_consumer_pool:select_connection(Interface, Request#dubbo_request.mid) of
+ case dubbo_provider_consumer_reg_table:select_connection(Interface, Request#dubbo_request.mid) of
{ok, #connection_info{pid = Pid, host_flag = HostFlag}} ->
case dubbo_traffic_control:check_goon(HostFlag, 199) of
ok ->
diff --git a/src/dubbo_netty_client.erl b/src/dubbo_netty_client.erl
index 0181d33..06f9d1e 100644
--- a/src/dubbo_netty_client.erl
+++ b/src/dubbo_netty_client.erl
@@ -415,7 +415,7 @@
{ok, State}.
process_request(true, #dubbo_request{data = <<"R">>}, State) ->
- {ok, _} = dubbo_consumer_pool:update_connection_readonly(self(), true),
+ {ok, _} = dubbo_provider_consumer_reg_table:update_connection_readonly(self(), true),
{ok, State};
process_request(true, Request, State) ->
{ok, NewState} = send_heartbeat_msg(Request#dubbo_request.mid, false, State),
diff --git a/src/dubbo_protocol_dubbo.erl b/src/dubbo_protocol_dubbo.erl
index 06c36e6..1ede1d8 100644
--- a/src/dubbo_protocol_dubbo.erl
+++ b/src/dubbo_protocol_dubbo.erl
@@ -17,19 +17,61 @@
-module(dubbo_protocol_dubbo).
-include("dubboerl.hrl").
+-include("dubbo.hrl").
%% API
-export([refer/2]).
-refer(Url,Acc)->
- {ok,UrlInfo} = dubbo_common_fun:parse_url(Url),
+refer(Url, Acc) ->
+ {ok, UrlInfo} = dubbo_common_fun:parse_url(Url),
case UrlInfo#dubbo_url.scheme of
<<"dubbo">> ->
- {ok,todo};
+ do_refer(UrlInfo),
+ {ok, todo};
_ ->
- {skip,Acc}
+ {skip, Acc}
end.
-do_refer(UrlInfo)->
+do_refer(UrlInfo) ->
- ok.
\ No newline at end of file
+ ok.
+
+
+getClients(ProviderUrl) ->
+ case new_transport(ProviderUrl) of
+ {ok,ConnectionInfoList} ->
+ ConnectionList = start_provider_process(HostFlag, 30, ProviderConfig),
+ ok;
+ {error,Reason} ->
+ {error,Reason}
+ end.
+
+
+
+%%ok = update_connection_info(ProviderConfig#provider_config.interface, HostFlag, ConnectionList, true),
+
+
+new_transport(ProviderUrl)->
+ case dubbo_node_config_util:parse_provider_info(ProviderUrl) of
+ {ok, ProviderConfig} ->
+ HostFlag = get_host_flag(ProviderConfig),
+ case dubbo_provider_consumer_reg_table:get_host_connections(ProviderConfig#provider_config) of
+ [] ->
+ case dubbo_exchanger:connect(ProviderUrl,?MODULE) of
+ {ok,ConnectionInfo} ->
+ {ok,[ConnectionInfo]};
+ {error,Reason} ->
+ logger:warning("start client fail ~p ~p",[Reason,HostFlag]),
+ {error,Reason}
+ end;
+ ConnectionInfoList ->
+ {ok,ConnectionInfoList}
+ end;
+ {error, R1} ->
+ logger:error("parse provider info error reason ~p", [R1]),
+ {error,R1}
+ end.
+
+
+
+
diff --git a/src/dubbo_provider_consumer_reg_table.erl b/src/dubbo_provider_consumer_reg_table.erl
index 3386cdc..c7a8dfa 100644
--- a/src/dubbo_provider_consumer_reg_table.erl
+++ b/src/dubbo_provider_consumer_reg_table.erl
@@ -15,7 +15,323 @@
%% limitations under the License.
%%------------------------------------------------------------------------------
-module(dubbo_provider_consumer_reg_table).
--author("dlive").
+
+-behaviour(gen_server).
%% API
--export([]).
+-export([start_link/0, start_consumer/2]).
+
+%% gen_server callbacks
+-export([init/1,
+ handle_call/3,
+ handle_cast/2,
+ handle_info/2,
+ terminate/2,
+ code_change/3]).
+
+-export([update_consumer_connections/2,get_host_connections/2, select_connection/1, select_connection/2, update_connection_readonly/2, get_host_flag/1, get_host_flag/2]).
+
+-include("dubbo.hrl").
+-define(SERVER, ?MODULE).
+
+-define(INTERFCE_LIST_TABLE, interface_list).
+-define(PROVIDER_NODE_LIST_TABLE, provider_node_list).
+
+-record(state, {}).
+
+-ifdef(TEST).
+-compile([export_all]).
+-endif.
+
+
+%%%===================================================================
+%%% API
+%%%===================================================================
+
+%%--------------------------------------------------------------------
+%% @doc
+%% Starts the server
+%%
+%% @end
+%%--------------------------------------------------------------------
+-spec(start_link() ->
+ {ok, Pid :: pid()} | ignore | {error, Reason :: term()}).
+start_link() ->
+ gen_server:start_link({local, ?SERVER}, ?MODULE, [], []).
+
+%%%===================================================================
+%%% gen_server callbacks
+%%%===================================================================
+
+%%--------------------------------------------------------------------
+%% @private
+%% @doc
+%% Initializes the server
+%%
+%% @spec init(Args) -> {ok, State} |
+%% {ok, State, Timeout} |
+%% ignore |
+%% {stop, Reason}
+%% @end
+%%--------------------------------------------------------------------
+-spec(init(Args :: term()) ->
+ {ok, State :: #state{}} | {ok, State :: #state{}, timeout() | hibernate} |
+ {stop, Reason :: term()} | ignore).
+init([]) ->
+ init_ets_table(),
+ {ok, #state{}}.
+init_ets_table() ->
+ try ets:new(?INTERFCE_LIST_TABLE, [bag, public, named_table, {keypos, 2}]) of
+ ?INTERFCE_LIST_TABLE ->
+ ok
+ catch
+ _Type:Reason ->
+ logger:error("new ets table error ~p", [Reason]),
+ error
+ end,
+ try ets:new(?PROVIDER_NODE_LIST_TABLE, [bag, public, named_table, {keypos, 2}]) of
+ ?PROVIDER_NODE_LIST_TABLE ->
+ ok
+ catch
+ _Type1:Reason1 ->
+ logger:error("new ets table error ~p", [Reason1]),
+ error
+ end,
+ ok.
+%%--------------------------------------------------------------------
+%% @private
+%% @doc
+%% Handling call messages
+%%
+%% @end
+%%--------------------------------------------------------------------
+-spec(handle_call(Request :: term(), From :: {pid(), Tag :: term()},
+ State :: #state{}) ->
+ {reply, Reply :: term(), NewState :: #state{}} |
+ {reply, Reply :: term(), NewState :: #state{}, timeout() | hibernate} |
+ {noreply, NewState :: #state{}} |
+ {noreply, NewState :: #state{}, timeout() | hibernate} |
+ {stop, Reason :: term(), Reply :: term(), NewState :: #state{}} |
+ {stop, Reason :: term(), NewState :: #state{}}).
+
+handle_call({add_consumer, Interface, ProviderNodeList}, _From, State) ->
+
+ OldProviderList = get_interface_provider_node(Interface),
+ NewProviderList = add_consumer(ProviderNodeList, []),
+ DeleteProverList = OldProviderList -- NewProviderList,
+ clean_invalid_provider(DeleteProverList),
+ {reply, ok, State};
+handle_call(_Request, _From, State) ->
+ {reply, ok, State}.
+
+%%--------------------------------------------------------------------
+%% @private
+%% @doc
+%% Handling cast messages
+%%
+%% @end
+%%--------------------------------------------------------------------
+-spec(handle_cast(Request :: term(), State :: #state{}) ->
+ {noreply, NewState :: #state{}} |
+ {noreply, NewState :: #state{}, timeout() | hibernate} |
+ {stop, Reason :: term(), NewState :: #state{}}).
+handle_cast(_Request, State) ->
+ {noreply, State}.
+
+%%--------------------------------------------------------------------
+%% @private
+%% @doc
+%% Handling all non call/cast messages
+%%
+%% @spec handle_info(Info, State) -> {noreply, State} |
+%% {noreply, State, Timeout} |
+%% {stop, Reason, State}
+%% @end
+%%--------------------------------------------------------------------
+-spec(handle_info(Info :: timeout() | term(), State :: #state{}) ->
+ {noreply, NewState :: #state{}} |
+ {noreply, NewState :: #state{}, timeout() | hibernate} |
+ {stop, Reason :: term(), NewState :: #state{}}).
+handle_info(_Info, State) ->
+ {noreply, State}.
+
+%%--------------------------------------------------------------------
+%% @private
+%% @doc
+%% 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.
+%%
+%% @spec terminate(Reason, State) -> void()
+%% @end
+%%--------------------------------------------------------------------
+-spec(terminate(Reason :: (normal | shutdown | {shutdown, term()} | term()),
+ State :: #state{}) -> term()).
+terminate(_Reason, _State) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% @private
+%% @doc
+%% Convert process state when code is changed
+%%
+%% @spec code_change(OldVsn, State, Extra) -> {ok, NewState}
+%% @end
+%%--------------------------------------------------------------------
+-spec(code_change(OldVsn :: term() | {down, term()}, State :: #state{},
+ Extra :: term()) ->
+ {ok, NewState :: #state{}} | {error, Reason :: term()}).
+code_change(_OldVsn, State, _Extra) ->
+ {ok, State}.
+
+start_consumer(Interface, ProviderNodeInfo) ->
+ gen_server:call(?SERVER, {add_consumer, Interface, ProviderNodeInfo}).
+
+
+
+get_host_connections(Host, Port) ->
+ HostFlag = get_host_flag(Host, Port),
+ List = ets:lookup(?PROVIDER_NODE_LIST_TABLE, HostFlag),
+ List2 = lists:map(
+ fun(#provider_node_list{host_flag = HostFlag,pid = Pid,readonly = Readonly}) ->
+ #connection_info{host_flag = HostFlag,pid = Pid,readonly = Readonly}
+ end, List),
+ List2.
+
+
+%%%===================================================================
+%%% Internal functions
+%%%===================================================================
+%%add_consumer([], RegisterList) ->
+%% RegisterList;
+%%add_consumer([ProviderNodeInfo | ProviderList], RegisterList) ->
+%% case dubbo_node_config_util:parse_provider_info(ProviderNodeInfo) of
+%% {ok, ProviderConfig} ->
+%% HostFlag = get_host_flag(ProviderConfig),
+%% case ets:lookup(?PROVIDER_NODE_LIST_TABLE, HostFlag) of
+%% [] ->
+%% ConnectionList = start_provider_process(HostFlag, 30, ProviderConfig),
+%% ok = update_connection_info(ProviderConfig#provider_config.interface, HostFlag, ConnectionList, true),
+%% ok;
+%% List ->
+%% List2 = lists:map(fun(#provider_node_list{connection_info = ConnectionItem}) ->
+%% ConnectionItem
+%% end, List),
+%% ok = update_connection_info(ProviderConfig#provider_config.interface, HostFlag, List2, false),
+%% ok
+%% end,
+%% add_consumer(ProviderList, [HostFlag] ++ RegisterList);
+%% {error, R1} ->
+%% logger:error("parse provider info error reason ~p", [R1]),
+%% add_consumer(ProviderList, RegisterList)
+%% end.
+%%
+%%start_provider_process(HostFlag, Weight, ProviderConfig) ->
+%% ExecutesList = lists:seq(1, ProviderConfig#provider_config.executes),
+%% ConnectionList = lists:map(fun(Item) ->
+%% ConnectionFlag = <<HostFlag/binary, (integer_to_binary(Item))/binary>>,
+%% ConnectionFlagTerm = binary_to_atom(ConnectionFlag, utf8),
+%% AChild = {ConnectionFlagTerm, {dubbo_netty_client, start_link, [ConnectionFlagTerm, HostFlag, ProviderConfig, Item]}, permanent, 2000, worker, [dubbo_netty_client]},
+%% {ok, Pid} = dubbo_transport_pool_sup:add_children(AChild),
+%% logger:info("start provider ~p pid info ~p~n", [HostFlag, Pid]),
+%% #connection_info{connection_id = ConnectionFlagTerm, pid = Pid, weight = Weight, host_flag = HostFlag}
+%% end, ExecutesList),
+%% ConnectionList.
+
+update_consumer_connections(Interface, Connections) ->
+ lists:map(
+ fun(Item) ->
+ HostFlag= Item#connection_info.host_flag,
+
+ case ets:lookup_element(?PROVIDER_NODE_LIST_TABLE,#provider_node_list{host_flag = HostFlag,pid = Item#connection_info.pid,_="_"}) of
+ '$end_of_table' ->
+ I2 = ets:insert(?PROVIDER_NODE_LIST_TABLE, #provider_node_list{host_flag = HostFlag,pid = Item#connection_info.pid}),
+ logger:debug("insert PROVIDER_NODE_LIST_TABLE ~p info:~p", [HostFlag, I2]);
+ {_ObjectList,_Continuation} ->
+ ok
+ end,
+ I1 = ets:insert(?INTERFCE_LIST_TABLE, #interface_list{interface = Interface, pid = Item#connection_info.pid, connection_info = Item}),
+ logger:debug("insert interface conection info ~p ~p ~p", [Interface, Item#connection_info.pid, I1]),
+ ok
+ end, Connections),
+ ok.
+
+get_host_flag(ProviderConfig) ->
+ HostFlag = <<(list_to_binary(ProviderConfig#provider_config.host))/binary, <<"_">>/binary, (integer_to_binary(ProviderConfig#provider_config.port))/binary>>,
+ HostFlag.
+get_host_flag(Host, Port) ->
+ <<(list_to_binary(Host))/binary, <<"_">>/binary, (integer_to_binary(Port))/binary>>.
+
+update_connection_info(Interface, HostFlag, ConnectionList, IsUpdateProvideNode) ->
+ lists:map(fun(Item) ->
+ I1 = ets:insert(?INTERFCE_LIST_TABLE, #interface_list{interface = Interface, pid = Item#connection_info.pid, connection_info = Item}),
+ logger:debug("insert interface conection info ~p ~p ~p", [Interface, Item#connection_info.pid, I1]),
+ case IsUpdateProvideNode of
+ true ->
+ I2 = ets:insert(?PROVIDER_NODE_LIST_TABLE, #provider_node_list{host_flag = HostFlag, connection_info = Item}),
+ logger:debug("insert PROVIDER_NODE_LIST_TABLE ~p info:~p", [HostFlag, I2]);
+ false ->
+ ok
+ end,
+ ok
+ end, ConnectionList),
+ ok.
+
+get_interface_provider_node(Interface) ->
+ case ets:lookup(?INTERFCE_LIST_TABLE, Interface) of
+ [] ->
+ [];
+ List ->
+ ListRet = [Item#interface_list.connection_info#connection_info.host_flag || Item <- List],
+ dubbo_lists_util:del_duplicate(ListRet)
+ end.
+
+select_connection(Interface) ->
+ RandNum = rand:uniform(2048),
+ select_connection(Interface, RandNum).
+select_connection(Interface, RandNum) ->
+ case ets:lookup(?INTERFCE_LIST_TABLE, Interface) of
+ [] ->
+ {error, none};
+ List ->
+ Len = length(List),
+ RemNum = (RandNum rem Len) + 1,
+ InterfaceListItem = lists:nth(RemNum, List),
+ {ok, InterfaceListItem#interface_list.connection_info}
+ end.
+
+-spec(update_connection_readonly(pid(), boolean()) -> ok).
+update_connection_readonly(ConnectionPid, Readonly) ->
+ Pattern = #interface_list{pid = ConnectionPid, _ = '_'},
+ Objects = ets:match_object(?INTERFCE_LIST_TABLE, Pattern),
+ lists:map(fun(#interface_list{interface = Interface, pid = Pid, connection_info = ConnectionInfo} = InterferConnection) ->
+ logger:debug("[dubbo] update interface ~p ~p readonly", [Interface, Pid]),
+ NewConnectionInfo = ConnectionInfo#connection_info{readonly = Readonly},
+ NewObject = InterferConnection#interface_list{connection_info = NewConnectionInfo},
+ ets:delete_object(?INTERFCE_LIST_TABLE, InterferConnection),
+ ets:insert(?INTERFCE_LIST_TABLE, NewObject)
+ end, Objects),
+ {ok, length(Objects)}.
+
+clean_invalid_provider([]) ->
+ ok;
+clean_invalid_provider([HostFlag | DeleteProverList]) ->
+ case ets:lookup(?PROVIDER_NODE_LIST_TABLE, HostFlag) of
+ [] ->
+ ok;
+ ProviderNodeList ->
+ ProviderNodeList1 = dubbo_lists_util:del_duplicate(ProviderNodeList),
+ clean_connection_info(ProviderNodeList1)
+ end,
+ clean_invalid_provider(DeleteProverList).
+
+clean_connection_info(ProviderNodeList) ->
+ lists:map(fun(Item) ->
+ Pid = Item#provider_node_list.connection_info#connection_info.pid,
+ ConnectionId = Item#provider_node_list.connection_info#connection_info.connection_id,
+ Pattern = #interface_list{pid = Pid, _ = '_'},
+ ets:delete_object(?INTERFCE_LIST_TABLE, Pattern),
+ dubbo_transport_pool_sup:stop_children(ConnectionId)
+ end, ProviderNodeList),
+ ok.
\ No newline at end of file
diff --git a/src/dubbo_registry_zookeeper.erl b/src/dubbo_registry_zookeeper.erl
index 0b5b3f5..5d14588 100644
--- a/src/dubbo_registry_zookeeper.erl
+++ b/src/dubbo_registry_zookeeper.erl
@@ -311,4 +311,4 @@
%%dubbo_zookeeper:register_consumer(<<"com.ifcoder.abcd">>,[]).
start_provider_process(Interface, ProviderList) ->
- dubbo_consumer_pool:start_consumer(Interface, ProviderList).
\ No newline at end of file
+ dubbo_provider_consumer_reg_table:start_consumer(Interface, ProviderList).
\ No newline at end of file
diff --git a/src/dubbo_consumer_pool_sup.erl b/src/dubbo_transport_pool_sup.erl
similarity index 87%
rename from src/dubbo_consumer_pool_sup.erl
rename to src/dubbo_transport_pool_sup.erl
index 77a6dbe..019c57d 100644
--- a/src/dubbo_consumer_pool_sup.erl
+++ b/src/dubbo_transport_pool_sup.erl
@@ -14,12 +14,12 @@
%% See the License for the specific language governing permissions and
%% limitations under the License.
%%------------------------------------------------------------------------------
--module(dubbo_consumer_pool_sup).
+-module(dubbo_transport_pool_sup).
-behaviour(supervisor).
%% API
--export([start_link/0, add_children/1, stop_children/1]).
+-export([start_link/0, add_children/2, stop_children/1]).
%% Supervisor callbacks
-export([init/1]).
@@ -63,17 +63,18 @@
ignore |
{error, Reason :: term()}).
init([]) ->
- RestartStrategy = one_for_one,
+ RestartStrategy = simple_one_for_one,
MaxRestarts = 1000,
MaxSecondsBetweenRestarts = 3600,
SupFlags = {RestartStrategy, MaxRestarts, MaxSecondsBetweenRestarts},
-
- {ok, {SupFlags, []}}.
+ Child = {dubbo_client_default, {dubbo_client_default, start_link, []}, permanent, 2000, worker, [dubbo_client_default]},
+ {ok, {SupFlags, [Child]}}.
-add_children(ChildSpec) ->
- supervisor:start_child(?SERVER, ChildSpec).
+add_children(ProvideConfig, Handler) ->
+ supervisor:start_child(?SERVER, [ProvideConfig, Handler]).
+
stop_children(ChildID) ->
supervisor:terminate_child(?SERVER, ChildID).
%%%===================================================================
diff --git a/src/dubbo_zookeeper.erl b/src/dubbo_zookeeper.erl
index f62ace1..84a95d6 100644
--- a/src/dubbo_zookeeper.erl
+++ b/src/dubbo_zookeeper.erl
@@ -272,5 +272,5 @@
%%dubbo_zookeeper:register_consumer(<<"com.ifcoder.abcd">>,[]).
start_provider_process(Interface, ProviderList) ->
- dubbo_consumer_pool:start_consumer(Interface, ProviderList).
+ dubbo_provider_consumer_reg_table:start_consumer(Interface, ProviderList).
diff --git a/src/dubboerl_sup.erl b/src/dubboerl_sup.erl
index a829015..a0d2fb0 100644
--- a/src/dubboerl_sup.erl
+++ b/src/dubboerl_sup.erl
@@ -45,8 +45,8 @@
%% NettySer = {dubbo_netty_client,{dubbo_netty_client, start_link, []},transient,5000,worker,[dubbo_netty_client]},
Id_count = {dubbo_id_generator, {dubbo_id_generator, start_link, []}, transient, 5000, worker, [dubbo_id_generator]},
ProviderPoolSup = {dubbo_provider_worker_sup, {dubbo_provider_worker_sup, start_link, []}, transient, 5000, supervisor, [dubbo_provider_worker_sup]},
- ConsumerPoolSup = {dubbo_consumer_pool_sup, {dubbo_consumer_pool_sup, start_link, []}, transient, 5000, supervisor, [dubbo_consumer_pool_sup]},
- ConsumerPool = {dubbo_consumer_pool, {dubbo_consumer_pool, start_link, []}, transient, 5000, worker, [dubbo_consumer_pool]},
+ ConsumerPoolSup = {dubbo_transport_pool_sup, {dubbo_transport_pool_sup, start_link, []}, transient, 5000, supervisor, [dubbo_transport_pool_sup]},
+ ConsumerPool = {dubbo_provider_consumer_reg_table, {dubbo_provider_consumer_reg_table, start_link, []}, transient, 5000, worker, [dubbo_provider_consumer_reg_table]},
ListNew1 =
case application:get_env(dubboerl, registry, false) of
true ->
diff --git a/test/dubbo_consumer_pool_tests.erl b/test/dubbo_consumer_pool_tests.erl
index 740ed84..0a67f1a 100644
--- a/test/dubbo_consumer_pool_tests.erl
+++ b/test/dubbo_consumer_pool_tests.erl
@@ -21,13 +21,13 @@
-include("dubbo.hrl").
update_readonly_test() ->
- dubbo_consumer_pool:start_link(),
+ dubbo_provider_consumer_reg_table:start_link(),
InterfaceName= <<"testinterfacename">>,
HostFalg= <<"127.0.0.1/20880">>,
ConnectionList = [
#connection_info{connection_id=1,pid= testpid,weight = 30,host_flag = HostFalg},
#connection_info{connection_id=2,pid= testpid2,weight = 30,host_flag = HostFalg}
],
- dubbo_consumer_pool:update_connection_info(InterfaceName,HostFalg,ConnectionList,true),
- {ok,Size} = dubbo_consumer_pool:update_connection_readonly(testpid,false),
+ dubbo_provider_consumer_reg_table:update_connection_info(InterfaceName,HostFalg,ConnectionList,true),
+ {ok,Size} = dubbo_provider_consumer_reg_table:update_connection_readonly(testpid,false),
?assertEqual(1,Size).