-module(agAgencyPoolMgrIns).
|
|
-include("agHttpCli.hrl").
|
|
|
|
-compile(inline).
|
|
-compile({inline_size, 128}).
|
|
|
|
|
|
-export([
|
|
startPool/2
|
|
, startPool/3
|
|
, stopPool/1
|
|
, getOneAgency/1
|
|
|
|
%% genExm API
|
|
, init/1
|
|
, handleMsg/2
|
|
, terminate/2
|
|
]).
|
|
|
|
%% k-v缓存表
|
|
-define(ETS_AG_Pool, ets_ag_Pool).
|
|
-define(ETS_AG_Agency, ets_ag_Agency).
|
|
|
|
-spec init(Args :: term()) -> ok.
|
|
init(_Args) ->
|
|
ets:new(?ETS_AG_Pool, [named_table, set, protected]),
|
|
ets:new(?ETS_AG_Agency, [named_table, set, protected]),
|
|
agKvsToBeam:load(?agBeamPool, []),
|
|
agKvsToBeam:load(?agBeamAgency, []),
|
|
{ok, undefined}.
|
|
|
|
handleMsg({'$gen_call', From, {miStartPool, PoolName, DbCfgs, AgencyOpts}}, State) ->
|
|
dealStart(PoolName, DbCfgs, AgencyOpts),
|
|
gen_server:reply(From, ok),
|
|
{ok, State};
|
|
handleMsg({'$gen_call', From, {miStopPool, Name}}, State) ->
|
|
delaStop(Name),
|
|
gen_server:reply(From, ok),
|
|
{ok, State};
|
|
handleMsg(_Msg, State) ->
|
|
?WARN(?MODULE, "receive unexpected msg: ~p", [_Msg]),
|
|
{ok, State}.
|
|
|
|
terminate(_Reason, _State) ->
|
|
ets:delete_all_objects(?ETS_AG_Pool),
|
|
ets:delete_all_objects(?ETS_AG_Agency),
|
|
agKvsToBeam:load(?agBeamPool, []),
|
|
agKvsToBeam:load(?agBeamAgency, []),
|
|
ok.
|
|
|
|
-spec startPool(poolName(), dbCfgs()) -> ok | {error, pool_name_used}.
|
|
startPool(PoolName, DbCfgs) ->
|
|
startPool(PoolName, DbCfgs, []).
|
|
|
|
-spec startPool(poolName(), dbCfgs(), agencyCfgs()) -> ok | {error, pool_name_used}.
|
|
startPool(PoolName, DbCfgs, AgencyCfgs) ->
|
|
case ?agBeamPool:get(PoolName) of
|
|
undefined ->
|
|
gen_server:call(?agAgencyPoolMgr, {miStartPool, PoolName, DbCfgs, AgencyCfgs});
|
|
_ ->
|
|
{error, pool_name_used}
|
|
end.
|
|
|
|
-spec stopPool(poolName()) -> ok | {error, pool_not_started}.
|
|
stopPool(PoolName) ->
|
|
case ?agBeamPool:get(PoolName) of
|
|
undefined ->
|
|
{error, pool_not_started};
|
|
_ ->
|
|
gen_server:call(?agAgencyPoolMgr, {miStopPool, PoolName})
|
|
|
|
end.
|
|
|
|
dealStart(PoolName, DbCfgs, AgencyCfgs) ->
|
|
#dbOpts{poolSize = PoolSize, protocol = Protocol} = DbOpts = agMiscUtils:dbOpts(DbCfgs),
|
|
AgencyOpts = agMiscUtils:agencyOpts(AgencyCfgs),
|
|
cacheAddPool(PoolName, DbOpts),
|
|
startChildren(PoolName, Protocol, PoolSize, AgencyOpts),
|
|
cacheAddAgency(PoolName, PoolSize),
|
|
case persistent_term:get(PoolName, undefined) of
|
|
undefined ->
|
|
IndexRef = atomics:new(1, [{signed, false}]),
|
|
persistent_term:put(PoolName, IndexRef);
|
|
_ ->
|
|
ignore
|
|
end,
|
|
ok.
|
|
|
|
delaStop(PoolName) ->
|
|
case ?agBeamPool:get(PoolName) of
|
|
undefined ->
|
|
{error, pool_not_started};
|
|
#dbOpts{poolSize = PoolSize} ->
|
|
stopChildren(agencyNames(PoolName, PoolSize)),
|
|
cacheDelPool(PoolName),
|
|
cacheDelAgency(PoolName),
|
|
ok
|
|
end.
|
|
|
|
agencyName(PoolName, Index) ->
|
|
list_to_atom(atom_to_list(PoolName) ++ "_" ++ integer_to_list(Index)).
|
|
|
|
agencyNames(PoolName, PoolSize) ->
|
|
[agencyName(PoolName, N) || N <- lists:seq(1, PoolSize)].
|
|
|
|
agencyMod(tcp) ->
|
|
agTcpAgencyExm;
|
|
agencyMod(ssl) ->
|
|
agSslAgencyExm;
|
|
agencyMod(_) ->
|
|
agTcpAgencyExm.
|
|
|
|
agencySpec(ServerMod, ServerName, Args) ->
|
|
%% TODO 下面spawn_opt 参数需要调优
|
|
StartFunc = {ServerMod, start_link, [ServerName, Args, [{min_heap_size, 5000}, {min_bin_vheap_size, 100000}, {fullsweep_after, 500}]]},
|
|
{ServerName, StartFunc, transient, infinity, worker, [ServerMod]}.
|
|
|
|
-spec startChildren(atom(), protocol(), poolSize(), agencyOpts()) -> ok.
|
|
startChildren(PoolName, Protocol, PoolSize, AgencyOpts) ->
|
|
AgencyMod = agencyMod(Protocol),
|
|
AgencyNames = agencyNames(PoolName, PoolSize),
|
|
AgencySpecs = [agencySpec(AgencyMod, AgencyName, {PoolName, AgencyName, AgencyOpts}) || AgencyName <- AgencyNames],
|
|
[supervisor:start_child(agAgencyPool_sup, AgencySpec) || AgencySpec <- AgencySpecs],
|
|
ok.
|
|
|
|
stopChildren([AgencyName | T]) ->
|
|
ok = supervisor:terminate_child(agAgencyPool_sup, AgencyName),
|
|
ok = supervisor:delete_child(agAgencyPool_sup, AgencyName),
|
|
stopChildren(T);
|
|
stopChildren([]) ->
|
|
ok.
|
|
|
|
cacheAddPool(Key, Value) ->
|
|
ets:insert(?ETS_AG_Pool, {Key, Value}),
|
|
KVS = ets:tab2list(?ETS_AG_Pool),
|
|
agKvsToBeam:load(?agBeamPool, KVS),
|
|
ok.
|
|
|
|
cacheDelPool(Key) ->
|
|
ets:delete(?ETS_AG_Pool, Key),
|
|
KVS = ets:tab2list(?ETS_AG_Pool),
|
|
agKvsToBeam:load(?agBeamPool, KVS),
|
|
ok.
|
|
|
|
cacheAddAgency(PoolName, PoolSize) ->
|
|
NameList = [{{PoolName, N}, agencyName(PoolName, N)} || N <- lists:seq(1, PoolSize)],
|
|
ets:insert(?ETS_AG_Agency, NameList),
|
|
KVS = ets:tab2list(?ETS_AG_Agency),
|
|
agKvsToBeam:load(?agBeamAgency, KVS),
|
|
ok.
|
|
|
|
cacheDelAgency(PoolName) ->
|
|
ets:match_delete(?ETS_AG_Agency, {{PoolName, '_'}, '_'}),
|
|
KVS = ets:tab2list(?ETS_AG_Agency),
|
|
agKvsToBeam:load(?agBeamAgency, KVS),
|
|
ok.
|
|
|
|
-spec getOneAgency(atom()) -> atom() | {error, term()}.
|
|
getOneAgency(PoolName) ->
|
|
case ?agBeamPool:get(PoolName) of
|
|
undefined ->
|
|
{error, pool_not_found};
|
|
#dbOpts{poolSize = PoolSize} ->
|
|
Ref = persistent_term:get(PoolName),
|
|
AgencyIdx = atomics:add_get(Ref, 1, 1),
|
|
case AgencyIdx >= PoolSize of
|
|
true ->
|
|
atomics:put(Ref, 1, 0),
|
|
?agBeamAgency:get({PoolName, PoolSize});
|
|
_ ->
|
|
?agBeamAgency:get({PoolName, AgencyIdx})
|
|
end
|
|
end.
|