瀏覽代碼

ft: 添加transaction 事务执行

master
SisMaker 5 月之前
父節點
當前提交
a11fb37fce
共有 1 個檔案被更改,包括 72 行新增20 行删除
  1. +72
    -20
      src/eGLock.erl

+ 72
- 20
src/eGLock.erl 查看文件

@ -10,6 +10,9 @@
%%
-define(eGLockSize, 2097152).
%% ets key
-define(undefTab, undefTab).
-export([
tryLock/1
, tryLock/2
@ -19,13 +22,11 @@
, lockApply/3
]).
-export([
lockGet/1
, lockGet/2
, transaction/2
, transaction/3
]).
-spec tryLock(KeyOrKeys :: term() | [term()]) -> true | lockTimeout.
@ -162,6 +163,21 @@ lockGet(KeyOrKeys) ->
lockGet(KeyOrKeys, ?LockTimeOut).
-spec lockGet(KeyOrKeys :: term() | [term()], TimeOut :: integer() | infinity) -> ok.
lockGet({?undefTab, Key = GetKey}, TimeOut) ->
KeyIx = erlang:phash2(GetKey, ?eGLockSize),
case doTryLock(KeyIx, TimeOut) of
true ->
try
#{{?undefTab, GetKey} => undefined}
catch C:R:S ->
{error, {lockGetError, {?undefTab, Key}, {C, R, S}}}
after
eNifLock:releaseLock(KeyIx),
ok
end;
lockTimeout ->
{error, lockTimeout}
end;
lockGet({EtsTab, Key} = GetKey, TimeOut) ->
KeyIx = erlang:phash2(GetKey, ?eGLockSize),
case doTryLock(KeyIx, TimeOut) of
@ -177,6 +193,21 @@ lockGet({EtsTab, Key} = GetKey, TimeOut) ->
lockTimeout ->
{error, lockTimeout}
end;
lockGet({?undefTab, Key = GetKey, DefValue}, TimeOut) ->
KeyIx = erlang:phash2(GetKey, ?eGLockSize),
case doTryLock(KeyIx, TimeOut) of
true ->
try
#{{?undefTab, GetKey} => getDefValue(DefValue)}
catch C:R:S ->
{error, {lockGetError, {?undefTab, Key, DefValue}, {C, R, S}}}
after
eNifLock:releaseLock(KeyIx),
ok
end;
lockTimeout ->
{error, lockTimeout}
end;
lockGet({EtsTab, Key, DefValue}, TimeOut) ->
GetKey = {EtsTab, Key},
KeyIx = erlang:phash2(GetKey, ?eGLockSize),
@ -194,9 +225,7 @@ lockGet({EtsTab, Key, DefValue}, TimeOut) ->
{error, lockTimeout}
end;
lockGet(EtsTabKeys, TimeOut) ->
KeysMap = #{{EtsTab, Key} => DefValue || OneEtsTabKey <- EtsTabKeys, case OneEtsTabKey of {EtsTab, Key} -> DefValue = undefined, true; {EtsTab, Key, DefValue} -> true end},
KeyOrKeys = maps:keys(KeysMap),
KeyIxs = getKexIxs(KeyOrKeys, []),
{KeyIxs, KeysMap} = getKeyIxAndMaps(EtsTabKeys, [], #{}),
case doTryLocks(KeyIxs, TimeOut) of
true ->
try
@ -211,6 +240,28 @@ lockGet(EtsTabKeys, TimeOut) ->
{error, lockTimeout}
end.
getKeyIxAndMaps([], IxAcc, KeysMap) -> {IxAcc, KeysMap};
getKeyIxAndMaps([Key | Keys], IxAcc, KeysMap) ->
case Key of
{?undefTab, JustKey} ->
GetKey = Key,
LDefValue = undefined,
KeyIx = erlang:phash2(Key, ?eGLockSize);
{?undefTab, JustKey, DefValue} ->
GetKey = {?undefTab, JustKey},
LDefValue = DefValue,
KeyIx = erlang:phash2(Key, ?eGLockSize);
{EtsTab, TabKey} ->
GetKey = Key,
LDefValue = undefined,
KeyIx = erlang:phash2(Key, ?eGLockSize);
{EtsTab, TabKey, DefValue} ->
GetKey = {EtsTab, TabKey},
LDefValue = DefValue,
KeyIx = erlang:phash2(Key, ?eGLockSize)
end,
getKeyIxAndMaps(Keys, ?CASE(lists:member(KeyIx, IxAcc), IxAcc, [KeyIx | IxAcc]), KeysMap#{GetKey => LDefValue}).
transactionApply({M, F, Args}, EtsTabValue) ->
apply(M, F, [EtsTabValue | Args]);
transactionApply({Fun, Args}, EtsTabValue) ->
@ -222,22 +273,22 @@ transaction(EtsTabKeys, MFAOrFun) ->
-spec transaction(KeyOrKeys :: term() | [term()], MFAOrFun :: {M :: atom(), F :: atom(), Args :: list()} | {Fun :: function(), Args :: list()}, TimeOut :: integer() | infinity) -> term().
transaction(EtsTabKeys, MFAOrFun, TimeOut) ->
KeysMap = #{{EtsTab, Key} => DefValue || OneEtsTabKey <- EtsTabKeys, case OneEtsTabKey of {EtsTab, Key} -> DefValue = undefined, true; {EtsTab, Key, DefValue} -> true end},
KeyOrKeys = maps:keys(KeysMap),
KeyIxs = getKexIxs(KeyOrKeys, []),
{KeyIxs, KeysMap} = getKeyIxAndMaps(EtsTabKeys, [], #{}),
case doTryLocks(KeyIxs, TimeOut) of
true ->
try
EtsTabValue = #{OneGetKey => getEtsTabValue(OneEtsTab, OneKey, OneDefValue) || {OneEtsTab, OneKey} = OneGetKey := OneDefValue <- KeysMap},
case transactionApply(MFAOrFun, EtsTabValue) of
{Ret, ChangeEtsTab} ->
{ok, Ret, ChangeEtsTab} ->
[changeEtsTabValue(OneEtsTab, OneKey, ChangeValue) || {OneEtsTab, OneKey} := ChangeValue <- ChangeEtsTab],
Ret;
Ret ->
Ret
{ok, Ret} ->
Ret;
{error, Err} ->
Err
end
catch
throw:Throw-> Throw;
throw:Throw -> Throw;
C:R:S ->
{error, {lockTransactionError, {MFAOrFun, EtsTabKeys}, {C, R, S}}}
after
@ -248,22 +299,23 @@ transaction(EtsTabKeys, MFAOrFun, TimeOut) ->
{error, lockTimeout}
end.
getEtsTabValue(undefined, _Key, DefValue) ->
DefValue;
getDefValue(undefined) -> undefined;
getDefValue({DefFun, Args}) when is_function(DefFun) -> erlang:apply(DefFun, Args);
getDefValue(DefValue) -> DefValue.
getEtsTabValue(?undefTab, _Key, DefValue) ->
getDefValue(DefValue);
getEtsTabValue(Ets, Key, DefValue) ->
case ets:lookup(Ets, Key) of
[] ->
DefValue;
getDefValue(DefValue);
[OneValue] ->
OneValue
end.
changeEtsTabValue(undefined, _Key, _Value) ->
changeEtsTabValue(?undefTab, _Key, _Value) ->
ok;
changeEtsTabValue(Ets, Key, delete) ->
ets:delete(Ets, Key);
changeEtsTabValue(Ets, _Key, Value) ->
ets:insert(Ets, Value).
ets:insert(Ets, Value).

Loading…
取消
儲存