332
333
case element(3, Lock) of
334
335
check_lock(Tid, Oid, Locks, TabLocks, X, AlreadyQ, Type);
335
WaitForTid when WaitForTid > Tid -> % Important order
336
check_lock(Tid, Oid, Locks, TabLocks, {queue, WaitForTid}, AlreadyQ, Type);
337
WaitForTid when Tid#tid.pid == WaitForTid#tid.pid ->
338
dbg_out("Spurious lock conflict ~w ~w: ~w -> ~w~n",
339
[Oid, Lock, Tid, WaitForTid]),
340
%% check_lock(Tid, Oid, Locks, TabLocks, {queue, WaitForTid}, AlreadyQ);
341
%% BUGBUG Fix this if possible
337
Queue = allowed_to_be_queued(WaitForTid,Tid),
339
check_lock(Tid, Oid, Locks, TabLocks, {queue, WaitForTid}, AlreadyQ, Type);
340
Tid#tid.pid == WaitForTid#tid.pid ->
341
dbg_out("Spurious lock conflict ~w ~w: ~w -> ~w~n",
342
[Oid, Lock, Tid, WaitForTid]),
345
HaveQ = (ets:lookup(mnesia_lock_queue, Oid) /= [])
346
orelse (ets:lookup(mnesia_lock_queue,{Tab,?ALL}) /= []),
351
check_lock(Tid,Oid,Locks,TabLocks,{queue,WaitForTid},AlreadyQ,Type)
353
%%{no, WaitForTid}; Safe solution
347
359
check_lock(_, _, [], [], X, {queue, bad_luck}, _) ->
788
add_debug(Node) -> % Use process dictionary for debug info
789
case get(mnesia_wlock_nodes) of
791
put(mnesia_wlock_nodes, [Node]);
793
put(mnesia_wlock_nodes, [Node|NodeList])
797
case get(mnesia_wlock_nodes) of
798
undefined -> % Shouldn't happen
801
erase(mnesia_wlock_nodes);
803
put(mnesia_wlock_nodes, lists:delete(Node, List))
806
%% We first send lock requests to the lockmanagers on all
819
add_debug(Nodes) -> % Use process dictionary for debug info
820
put(mnesia_wlock_nodes, Nodes).
823
erase(mnesia_wlock_nodes).
825
%% We first send lock request to the local node if it is part of the lockers
826
%% then the first sorted node then to the rest of the lockmanagers on all
807
827
%% nodes holding a copy of the table
809
829
get_wlocks_on_nodes([Node | Tail], Orig, Store, Request, Oid) ->
810
830
{?MODULE, Node} ! Request,
811
831
?ets_insert(Store, {nodes, Node}),
813
get_wlocks_on_nodes(Tail, Orig, Store, Request, Oid);
814
get_wlocks_on_nodes([], Orig, Store, _Request, Oid) ->
815
receive_wlocks(Orig, Orig, Store, Oid).
817
receive_wlocks([Node | Tail], Res, Store, Oid) ->
832
receive_wlocks([Node], undefined, Store, Oid),
834
Node -> %% Local done try one more
835
get_wlocks_on_nodes(Tail, Orig, Store, Request, Oid);
836
_ -> %% The first succeded cont with the rest
837
get_wlocks_on_nodes(Tail, Store, Request),
838
receive_wlocks(Tail, Orig, Store, Oid)
840
get_wlocks_on_nodes([], Orig, _Store, _Request, _Oid) ->
843
get_wlocks_on_nodes([Node | Tail], Store, Request) ->
844
{?MODULE, Node} ! Request,
845
?ets_insert(Store,{nodes, Node}),
846
get_wlocks_on_nodes(Tail, Store, Request);
847
get_wlocks_on_nodes([], _, _) ->
850
get_rwlocks_on_nodes([ReadNode|Tail], _Res, ReadNode, Store, Tid, Oid) ->
851
Op = {self(), {read_write, Tid, Oid}},
852
{?MODULE, ReadNode} ! Op,
853
?ets_insert(Store, {nodes, ReadNode}),
854
Res = receive_wlocks([ReadNode], undefined, Store, Oid),
857
get_rwlocks_on_nodes(Tail, Res, ReadNode, Store, Tid, Oid);
859
get_wlocks_on_nodes(Tail, Store, {self(), {write, Tid, Oid}}),
860
receive_wlocks(Tail, Res, Store, Oid)
862
get_rwlocks_on_nodes([Node | Tail], Res, ReadNode, Store, Tid, Oid) ->
863
Op = {self(), {write, Tid, Oid}},
864
{?MODULE, Node} ! Op,
865
?ets_insert(Store, {nodes, Node}),
866
receive_wlocks([Node], undefined, Store, Oid),
868
get_rwlocks_on_nodes(Tail, Res, ReadNode, Store, Tid, Oid);
869
Res == rwlock -> %% Hmm
870
Rest = lists:delete(ReadNode, Tail),
871
Op2 = {self(), {read_write, Tid, Oid}},
872
{?MODULE, ReadNode} ! Op2,
873
?ets_insert(Store, {nodes, ReadNode}),
874
get_wlocks_on_nodes(Rest, Store, {self(), {write, Tid, Oid}}),
875
receive_wlocks([ReadNode|Rest], undefined, Store, Oid);
877
get_wlocks_on_nodes(Tail, Store, {self(), {write, Tid, Oid}}),
878
receive_wlocks(Tail, Res, Store, Oid)
880
get_rwlocks_on_nodes([],Res,_,_,_,_) ->
883
receive_wlocks([], Res, _Store, _Oid) ->
886
receive_wlocks(Nodes = [This|Ns], Res, Store, Oid) ->
819
889
{?MODULE, Node, granted} ->
821
receive_wlocks(Tail, Res, Store, Oid);
890
receive_wlocks(lists:delete(Node,Nodes), Res, Store, Oid);
822
891
{?MODULE, Node, {granted, Val}} -> %% for rwlocks
824
892
case opt_lookup_in_client(Val, Oid, write) of
825
893
C when record(C, cyclic) ->
826
flush_remaining(Tail, Node, {aborted, C});
894
flush_remaining(Nodes, Node, {aborted, C});
828
receive_wlocks(Tail, Val2, Store, Oid)
896
receive_wlocks(lists:delete(Node,Nodes), Val2, Store, Oid)
830
898
{?MODULE, Node, {not_granted, Reason}} ->
832
899
Reason1 = {aborted, Reason},
833
flush_remaining(Tail, Node, Reason1);
900
flush_remaining(Nodes,Node,Reason1);
901
{?MODULE, Node, {switch, Sticky, _Req}} -> %% for rwlocks
902
Tail = lists:delete(Node,Nodes),
903
Nonstuck = lists:delete(Sticky,Tail),
904
[?ets_insert(Store, {nodes, NSNode}) || NSNode <- Nonstuck],
905
case lists:member(Sticky,Tail) of
907
sticky_flush(Nonstuck,Store),
908
receive_wlocks([Sticky], Res, Store, Oid);
910
sticky_flush(Nonstuck,Store),
913
{mnesia_down, This} -> % Only look for down from Nodes in list
914
Reason1 = {aborted, {node_not_running, This}},
915
flush_remaining(Ns, This, Reason1)
918
sticky_flush([], _) ->
921
sticky_flush(Ns=[Node | Tail], Store) ->
924
{?MODULE, Node, _} ->
925
sticky_flush(Tail, Store);
834
926
{mnesia_down, Node} ->
836
Reason1 = {aborted, {node_not_running, Node}},
837
flush_remaining(Tail, Node, Reason1);
838
{?MODULE, Node, {switch, Node2, Req}} -> %% for rwlocks
841
?ets_insert(Store, {nodes, Node2}),
842
{?MODULE, Node2} ! Req,
843
receive_wlocks([Node2 | Tail], Res, Store, Oid)
846
receive_wlocks([], Res, _Store, _Oid) ->
927
?ets_delete(Store, {nodes, Node}),
928
sticky_flush(Tail, Store)
849
931
flush_remaining([], _SkipNode, Res) ->
851
934
flush_remaining([SkipNode | Tail ], SkipNode, Res) ->
853
935
flush_remaining(Tail, SkipNode, Res);
854
flush_remaining([Node | Tail], SkipNode, Res) ->
936
flush_remaining(Ns=[Node | Tail], SkipNode, Res) ->
856
939
{?MODULE, Node, _} ->
858
940
flush_remaining(Tail, SkipNode, Res);
859
941
{mnesia_down, Node} ->
861
942
flush_remaining(Tail, SkipNode, {aborted, {node_not_running, Node}})
1022
1102
system_code_change(State, _Module, _OldVsn, _Extra) ->
1106
%%%%%%%%%%%%%%%%%%%%%%%%%%%
1107
%% AXD301 patch sort pids according to R9B sort order
1108
%%%%%%%%%%%%%%%%%%%%%%%%%%%
1110
%% Om R9B == true, g�rs j�mf�relsen som i R9B plain.
1111
%% Om R9B == false, g�rs j�mf�relsen som i alla andra releaser.
1112
%% cmp_tid(T1, T2) returnerar -1 om T1 < T2, 0 om T1 = T2 och 1 om T1 > T2.
1114
-define(VERSION_MAGIC, 131).
1115
-define(ATOM_EXT, 100).
1116
-define(PID_EXT, 103).
1118
-record(pid_info, {serial, number, nodename, creation}).
1122
#tid{} = T) when R9B == true; R9B == false ->
1125
#tid{counter = C, pid = Pid1},
1126
#tid{counter = C, pid = Pid2}) when R9B == true; R9B == false ->
1127
cmp_pid_info(R9B, pid_to_pid_info(Pid1), pid_to_pid_info(Pid2));
1130
#tid{counter = C2}) when R9B == true; R9B == false ->
1133
cmp_pid_info(_, #pid_info{} = PI, #pid_info{} = PI) ->
1136
#pid_info{serial = S, number = N, nodename = NN, creation = C1},
1137
#pid_info{serial = S, number = N, nodename = NN, creation = C2}) ->
1140
#pid_info{serial = S, number = N, nodename = NN1},
1141
#pid_info{serial = S, number = N, nodename = NN2}) ->
1144
#pid_info{serial = S, number = N1},
1145
#pid_info{serial = S, number = N2}) ->
1147
cmp_pid_info(false, #pid_info{serial = S1}, #pid_info{serial = S2}) ->
1150
#pid_info{nodename = NN, creation = C, serial = S, number = N1},
1151
#pid_info{nodename = NN, creation = C, serial = S, number = N2}) ->
1154
#pid_info{nodename = NN, creation = C, serial = S1},
1155
#pid_info{nodename = NN, creation = C, serial = S2}) ->
1158
#pid_info{nodename = NN, creation = C1},
1159
#pid_info{nodename = NN, creation = C2}) ->
1161
cmp_pid_info(true, #pid_info{nodename = NN1}, #pid_info{nodename = NN2}) ->
1165
cmp(X1, X2) when X1 < X2 -> -1;
1168
pid_to_pid_info(Pid) when pid(Pid) ->
1169
[?VERSION_MAGIC, ?PID_EXT, ?ATOM_EXT, NNL1, NNL0 | Rest]
1170
= binary_to_list(term_to_binary(Pid)),
1171
[N3, N2, N1, N0, S3, S2, S1, S0, Creation] = drop(bytes2int(NNL1, NNL0),
1173
#pid_info{serial = bytes2int(S3, S2, S1, S0),
1174
number = bytes2int(N3, N2, N1, N0),
1175
nodename = node(Pid),
1176
creation = Creation}.
1179
drop(N, [_|L]) when integer(N), N > 0 -> drop(N-1, L);
1180
drop(N, []) when integer(N), N > 0 -> [].
1182
bytes2int(N1, N0) when 0 =< N1, N1 =< 255,
1183
0 =< N0, N0 =< 255 ->
1185
bytes2int(N3, N2, N1, N0) when 0 =< N3, N3 =< 255,
1188
0 =< N0, N0 =< 255 ->
1189
(N3 bsl 24) bor (N2 bsl 16) bor (N1 bsl 8) bor N0.