瀏覽代碼

ft: 完善

master
SisMaker 3 年之前
父節點
當前提交
e981366609
共有 4 個文件被更改,包括 169 次插入17 次删除
  1. +10
    -1
      include/ranks.hrl
  2. +12
    -6
      src/rank/rankMgr.erl
  3. +134
    -2
      src/rank/rankWork.erl
  4. +13
    -8
      src/ranks.erl

+ 10
- 1
include/ranks.hrl 查看文件

@ -3,10 +3,14 @@
%%
-define(ranksCfg, ranksCfg).
-define(ranksLimit, ranksLimit).
%%
-define(workCnt, workCnt).
%%
-define(publicInfoPos, #etsRankRecord.publicInfo).
%%
-define(IIF(Cond, Ret1, Ret2), (case Cond of true -> Ret1; _ -> Ret2 end)).
@ -21,6 +25,11 @@
, rankTypeNScore :: term()
}).
-define(RankRecordFields, record_info(fields, etsRankRecord)).
-record(rankInfo, {
rank :: integer()
, key :: integer()
, publicInfo :: term()
, rankTypeScore :: term()
}).
-endif.

+ 12
- 6
src/rank/rankMgr.erl 查看文件

@ -18,7 +18,6 @@
]).
-define(SERVER, ?MODULE).
-record(state, {}).
%% ******************************************** API *******************************************************************
start_link() ->
@ -27,11 +26,18 @@ start_link() ->
%% ******************************************** callback **************************************************************
init(_Args) ->
ets:new(?etsRankInfo, [set, public, named_table, {keypos, #etsRankRecord.key}, {write_concurrency, auto}, {read_concurrency, true}]),
{ok, #state{}}.
handleCall({mInitRank, RankType}, _State, _FROM) ->
ets:new(RankType, [ordered_set, public, named_table, {write_concurrency, auto}, {read_concurrency, true}]),
{reply, ok};
{ok, #{}}.
handleCall({mInitRank, RankType, CntLimit, CntMax}, State, _FROM) ->
case State of
#{RankType := _} ->
{reply, {error, used}};
_ ->
ets:new(RankType, [ordered_set, public, named_table, {write_concurrency, auto}, {read_concurrency, true}]),
NewState = State#{RankType => {CntLimit, CntMax}},
gtKvsToBeam:load(?ranksLimit, maps:to_list(NewState)),
{reply, ok, NewState}
end;
handleCall(_Msg, _State, _FROM) ->
{reply, ok}.

+ 134
- 2
src/rank/rankWork.erl 查看文件

@ -2,8 +2,13 @@
-behavior(gen_srv).
-include("ranks.hrl").
-export([
start_link/1
, mUpdateScore/3
, mUpdateInfo/2
, mGetRankInfo/5
]).
-export([
@ -25,8 +30,6 @@ start_link(SrvName) ->
init(_Args) ->
{ok, #state{}}.
handleCall(_Msg, _State, _FROM) ->
{reply, ok};
handleCall(_Msg, _State, _FROM) ->
{reply, ok}.
@ -42,3 +45,132 @@ terminate(_Reason, _State) ->
code_change(_OldVsn, State, _Extra) ->
{ok, State}.
%% ****************************************************** logic ********************************************************
mUpdateScore(Key, RankType, Score) ->
{_RankLimit, RankMax} = ?ranksLimit:getV(RankType),
RankPos = ?ranksCfg:getV(RankType),
case ets:lookup(etsRankInfo, Key) of
[RankRecord] ->
OldScore = element(RankPos, RankRecord),
ets:delete(RankType, OldScore),
RankSize = ets:info(RankType, size),
case RankSize >= RankMax of
true ->
FirstKey = ets:first(RankType),
case Score > FirstKey of
true ->
ets:insert(RankType, Score),
ets:delete(RankType, FirstKey);
_ ->
ignore
end;
_ ->
ets:insert(RankType, Score)
end,
ets:update_element(etsRankInfo, Key, {RankPos, Score});
_ ->
%%
RankSize = ets:info(RankType, size),
case RankSize >= RankMax of
true ->
FirstKey = ets:first(RankType),
case Score > FirstKey of
true ->
ets:insert(RankType, Score),
ets:delete(RankType, FirstKey),
NewRecord = #etsRankRecord{key = Key},
RankRecord = setelement(RankPos, NewRecord, Score),
ets:insert(etsRankInfo, RankRecord);
_ ->
ignore
end;
_ ->
ets:insert(RankType, Score),
NewRecord = #etsRankRecord{key = Key},
RankRecord = setelement(RankPos, NewRecord, Score),
ets:insert(etsRankInfo, RankRecord)
end
end,
{mayReply, ok}.
mUpdateInfo(Key, RecordKvs) ->
ets:update_element(etsRankInfo, Key, RecordKvs),
{mayReply, ok}.
mGetRankInfo(RankType, MyKey, Cnt, Page, PageInfo) ->
{RankLimit, _RankMax} = ?ranksLimit:getV(RankType),
%%
SelfRank =
case Page of
0 ->
case ets:lookup_element(etsRankInfo, MyKey) of
[RankRecord] ->
RankPos = ?ranksCfg:getV(RankType),
CurScore = element(RankPos, RankRecord),
MyIndex = ets:select_count(RankType, [{{'$1', '$2'}, [{'>=', '$1', CurScore}], [true]}]),
max(RankLimit, MyIndex);
_ ->
-1
end;
_ ->
0
end,
MS =
case PageInfo == 0 orelse PageInfo of
true ->
[{'$1', [], ['$1']}];
<<"">> ->
[{'$1', [], ['$1']}];
_ ->
try binary_to_term(PageInfo) of
KeyTerm when KeyTerm == <<"">>; KeyTerm == "" ->
[{'$1', [], ['$1']}];
KeyTerm ->
% ets:fun2ms(fun({K, _V} = T) when K < KeyTerm -> T end)
[{{'$1', '$2'}, [{'<', '$1', KeyTerm}], ['$_']}]
catch _C:_R ->
[{'$1', [], ['$1']}]
end
end,
case ets:select_reverse(RankType, MS, Cnt) of
'$end_of_table' ->
{true, {<<"">>, []}};
{KeyIds, '$end_of_table'} ->
{true, SelfRank, makeRankData(KeyIds, Cnt * Page + 1)};
{KeyIds, _NextKey} ->
Length = length(KeyIds),
if
Length < Cnt ->
{true, SelfRank, makeRankData(KeyIds, Cnt * Page + 1)};
true ->
NewCurCnt = Page * Cnt + Length,
case NewCurCnt >= RankLimit of
true ->
{true, SelfRank, makeRankData(KeyIds, Cnt * Page + 1)};
_ ->
{false, SelfRank, makeRankData(KeyIds, Cnt * Page + 1)}
end
end
end.
makeRankData(KeyIds, Idx) ->
makeRankData(KeyIds, Idx, <<"">>, []).
makeRankData([], _Idx, LastKey, Acc) ->
case LastKey of
<<"">> ->
{LastKey, lists:reverse(Acc)};
_ ->
{erlang:term_to_binary(LastKey), lists:reverse(Acc)}
end;
makeRankData([{CurKey, Score} | KeyIds], Idx, LastKey, Acc) ->
case ets:lookup(ets_pub_rank_info, CurKey) of
[OneData] ->
makeRankData(KeyIds, Idx + 1, CurKey, [#rankInfo{rank = Idx, key = CurKey, publicInfo = element(?publicInfoPos, OneData), rankTypeScore = Score} | Acc]);
_ ->
makeRankData(KeyIds, Idx, LastKey, Acc)
end.

+ 13
- 8
src/ranks.erl 查看文件

@ -6,7 +6,7 @@
start/0
, stop/0
, startWork/1
, initRank/1 %%
, initRank/3 %%
, updateScore/3 %%
, updateInfo/2 %%
, getRankInfo/4 %%
@ -40,24 +40,29 @@ startWork(Cnt) when Cnt > 0 ->
{error, started}
end.
initRank(RankType) ->
gen_srv:call(rankMgr, {mInitRank, RankType}).
initRank(RankType, CntLimit, CntMax) ->
gen_srv:call(rankMgr, {mInitRank, RankType, CntLimit, CntMax}).
%% key
updateScore(RankType, Key, Score) ->
WorkName = ?ranksCfg:getV(erlang:phash2(Key, ?ranksCfg:getV(?workCnt)) + 1),
%% key
RankPos = ?ranksCfg:getV(RankType),
gen_srv:cast(WorkName, {mUpdateScore, RankPos, Score}).
%%
%%
%% gen_srv:clfn(WorkName, rank_work, mUpdateScore, [Key, RankPos, Score]),
%%
gen_srv:csfn(WorkName, rank_work, mUpdateScore, [Key, RankPos, Score]).
%% key
updateInfo(Key, RecordKvs) ->
WorkName = ?ranksCfg:getV(erlang:phash2(Key, ?ranksCfg:getV(?workCnt)) + 1),
%%
gen_srv:cast(WorkName, {mUpdateInfo, RecordKvs}).
%%
%% gen_srv:clfn(WorkName, rank_work, mUpdateInfo, [Key, RecordKvs]),
%%
gen_srv:csfn(WorkName, rank_work, mUpdateInfo, [Key, RecordKvs]).
%%
getRankInfo(RankType, Cnt, Page, PageInfo) ->
ok.
rankWork:mGetRankInfo(RankType, Cnt, Page, PageInfo).

Loading…
取消
儲存