You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

173 lines
5.2 KiB

-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.