Created
July 22, 2018 20:59
-
-
Save oltarasenko/43550fc8f8281e5ab39d96d5a77df4ca to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
loop(State) -> | |
receive | |
{From, {write, Tid, Oid}} -> | |
try_sticky_lock(Tid, write, From, Oid), | |
loop(State); | |
%% If Key == ?ALL it's a request to lock the entire table | |
%% | |
{From, {read, Tid, Oid}} -> | |
try_sticky_lock(Tid, read, From, Oid), | |
loop(State); | |
%% Really do a read, but get hold of a write lock | |
%% used by mnesia:wread(Oid). | |
{From, {read_write, Tid, Oid}} -> | |
try_sticky_lock(Tid, read_write, From, Oid), | |
loop(State); | |
%% Tid has somehow terminated, clear up everything | |
%% and pass locks on to queued processes. | |
%% This is the purpose of the mnesia_tid_locks table | |
{release_tid, Tid} -> | |
do_release_tid(Tid), | |
loop(State); | |
%% stick lock, first tries this to the where_to_read Node | |
{From, {test_set_sticky, Tid, {Tab, _} = Oid, Lock}} -> | |
case ?ets_lookup(mnesia_sticky_locks, Tab) of | |
[] -> | |
reply(From, not_stuck), | |
loop(State); | |
[{_,Node}] when Node == node() -> | |
%% Lock is stuck here, see now if we can just set | |
%% a regular write lock | |
try_lock(Tid, Lock, From, Oid), | |
loop(State); | |
[{_,Node}] -> | |
reply(From, {stuck_elsewhere, Node}), | |
loop(State) | |
end; | |
%% If test_set_sticky fails, we send this to all nodes | |
%% after aquiring a real write lock on Oid | |
{stick, {Tab, _}, N} -> | |
?ets_insert(mnesia_sticky_locks, {Tab, N}), | |
loop(State); | |
%% The caller which sends this message, must have first | |
%% aquired a write lock on the entire table | |
{unstick, Tab} -> | |
?ets_delete(mnesia_sticky_locks, Tab), | |
loop(State); | |
{From, {ix_read, Tid, Tab, IxKey, Pos}} -> | |
case ?ets_lookup(mnesia_sticky_locks, Tab) of | |
[] -> | |
set_read_lock_on_all_keys(Tid,From,Tab,IxKey,Pos), | |
loop(State); | |
[{_,N}] when N == node() -> | |
set_read_lock_on_all_keys(Tid,From,Tab,IxKey,Pos), | |
loop(State); | |
[{_,N}] -> | |
Req = {From, {ix_read, Tid, Tab, IxKey, Pos}}, | |
From ! {?MODULE, node(), {switch, N, Req}}, | |
loop(State) | |
end; | |
{From, {sync_release_tid, Tid}} -> | |
do_release_tid(Tid), | |
reply(From, {tid_released, Tid}), | |
loop(State); | |
{{From, Ref},{release_remote_non_pending, Node, Pending}} -> | |
release_remote_non_pending(Node, Pending), | |
From ! {Ref, ok}, | |
loop(State); | |
{From, {is_locked, Oid}} -> | |
Held = ?ets_lookup(mnesia_held_locks, Oid), | |
reply(From, Held), | |
loop(State); | |
{'EXIT', Pid, _} when Pid == State#state.supervisor -> | |
do_stop(); | |
{system, From, Msg} -> | |
verbose("~p got {system, ~p, ~p}~n", [?MODULE, From, Msg]), | |
Parent = State#state.supervisor, | |
sys:handle_system_msg(Msg, From, Parent, ?MODULE, [], State); | |
{get_table, From, LockTable} -> | |
From ! {LockTable, ?ets_match_object(LockTable, '_')}, | |
loop(State); | |
Msg -> | |
error("~p got unexpected message: ~p~n", [?MODULE, Msg]), | |
loop(State) | |
end. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment