Skip to content

Commit 022287f

Browse files
committed
Move Mnesia-specific code to rabbit_db* modules
The idea is to isolate in those modules the code to handle the records in the database. For now, we only support Mnesia, but there is work in progress to move to another database engine. Doing this reorganization of the code will also isolate the changes of this upcoming database engine switch, making them easier to rebase and review. In the end, the `rabbit_db*` modules should export functions for each operations we want to perform. Things like "add this record", "list records matching that", "update a record using an anonymous function inside a transaction", etc. Only the following subsystems are impacted in this commit: * virtual vhosts * internal users * runtime parameters They were modified together because they depend on each other.
1 parent b251755 commit 022287f

File tree

9 files changed

+1431
-483
lines changed

9 files changed

+1431
-483
lines changed

deps/rabbit/src/rabbit_auth_backend_internal.erl

Lines changed: 105 additions & 217 deletions
Large diffs are not rendered by default.

deps/rabbit/src/rabbit_db.erl

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
%% This Source Code Form is subject to the terms of the Mozilla Public
2+
%% License, v. 2.0. If a copy of the MPL was not distributed with this
3+
%% file, You can obtain one at https://mozilla.org/MPL/2.0/.
4+
%%
5+
%% Copyright (c) 2007-2022 VMware, Inc. or its affiliates. All rights reserved.
6+
%%
7+
8+
-module(rabbit_db).
9+
10+
-include_lib("kernel/include/logger.hrl").
11+
-include_lib("stdlib/include/assert.hrl").
12+
13+
-export([run/1]).
14+
15+
%% -------------------------------------------------------------------
16+
%% run().
17+
%% -------------------------------------------------------------------
18+
19+
-spec run(Funs) -> Ret when
20+
Funs :: #{mnesia := Fun},
21+
Fun :: fun(() -> Ret),
22+
Ret :: any().
23+
%% @doc Runs the function corresponding to the used database engine.
24+
%%
25+
%% @returns the return value of `Fun'.
26+
27+
run(Funs)
28+
when is_map(Funs) andalso is_map_key(mnesia, Funs) ->
29+
#{mnesia := MnesiaFun} = Funs,
30+
run_with_mnesia(MnesiaFun).
31+
32+
run_with_mnesia(Fun) ->
33+
Fun().
Lines changed: 249 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,249 @@
1+
%% This Source Code Form is subject to the terms of the Mozilla Public
2+
%% License, v. 2.0. If a copy of the MPL was not distributed with this
3+
%% file, You can obtain one at https://mozilla.org/MPL/2.0/.
4+
%%
5+
%% Copyright (c) 2007-2022 VMware, Inc. or its affiliates. All rights reserved.
6+
%%
7+
8+
-module(rabbit_db_rtparams).
9+
10+
-include_lib("rabbit_common/include/rabbit.hrl").
11+
12+
-export([set/2, set/4,
13+
lookup/1,
14+
lookup_or_set/2,
15+
get_all/0, get_all/2,
16+
remove/1, remove/3]).
17+
18+
-define(MNESIA_TABLE, rabbit_runtime_parameters).
19+
20+
%% -------------------------------------------------------------------
21+
%% set().
22+
%% -------------------------------------------------------------------
23+
24+
-spec set(Key, Term) -> Ret when
25+
Key :: atom(),
26+
Term :: any(),
27+
Ret :: new | {old, Term}.
28+
%% @doc Sets the new value of the global runtime parameter named `Key'.
29+
%%
30+
%% @returns `new' if the runtime parameter was not set before, or `{old,
31+
%% OldTerm}' with the old value.
32+
%%
33+
%% @private
34+
35+
set(Key, Term) when is_atom(Key) ->
36+
rabbit_db:run(
37+
#{mnesia => fun() -> set_in_mnesia(Key, Term) end}).
38+
39+
set_in_mnesia(Key, Term) ->
40+
rabbit_misc:execute_mnesia_transaction(
41+
fun() -> set_in_mnesia_tx(Key, Term) end).
42+
43+
-spec set(VHostName, Comp, Name, Term) -> Ret when
44+
VHostName :: vhost:name(),
45+
Comp :: binary(),
46+
Name :: binary() | atom(),
47+
Term :: any(),
48+
Ret :: new | {old, Term}.
49+
%% @doc Checks the existence of `VHostName' and sets the new value of the
50+
%% non-global runtime parameter named `Key'.
51+
%%
52+
%% @returns `new' if the runtime parameter was not set before, or `{old,
53+
%% OldTerm}' with the old value.
54+
%%
55+
%% @private
56+
57+
set(VHostName, Comp, Name, Term)
58+
when is_binary(VHostName) andalso
59+
is_binary(Comp) andalso
60+
(is_binary(Name) orelse is_atom(Name)) ->
61+
Key = {VHostName, Comp, Name},
62+
rabbit_db:run(
63+
#{mnesia => fun() -> set_in_mnesia(VHostName, Key, Term) end}).
64+
65+
set_in_mnesia(VHostName, Key, Term) ->
66+
rabbit_misc:execute_mnesia_transaction(
67+
rabbit_db_vhost:with_fun_in_mnesia_tx(
68+
VHostName,
69+
fun() -> set_in_mnesia_tx(Key, Term) end)).
70+
71+
set_in_mnesia_tx(Key, Term) ->
72+
Res = case mnesia:read(?MNESIA_TABLE, Key, read) of
73+
[Params] -> {old, Params#runtime_parameters.value};
74+
[] -> new
75+
end,
76+
Record = #runtime_parameters{key = Key,
77+
value = Term},
78+
mnesia:write(?MNESIA_TABLE, Record, write),
79+
Res.
80+
81+
%% -------------------------------------------------------------------
82+
%% lookup().
83+
%% -------------------------------------------------------------------
84+
85+
-spec lookup(Key) -> Ret when
86+
Key :: atom() | {vhost:name(), binary(), binary()},
87+
Ret :: #runtime_parameters{} | undefined.
88+
%% @doc Looks up a runtime parameter.
89+
%%
90+
%% @returns the value of the runtime parameter if it exists, or `undefined'
91+
%% otherwise.
92+
%%
93+
%% @private
94+
95+
lookup({VHostName, Comp, Name} = Key)
96+
when is_binary(VHostName) andalso
97+
is_binary(Comp) andalso
98+
(is_binary(Name) orelse is_atom(Name)) ->
99+
rabbit_db:run(
100+
#{mnesia => fun() -> lookup_in_mnesia(Key) end});
101+
lookup(Key) when is_atom(Key) ->
102+
rabbit_db:run(
103+
#{mnesia => fun() -> lookup_in_mnesia(Key) end}).
104+
105+
lookup_in_mnesia(Key) ->
106+
case mnesia:dirty_read(?MNESIA_TABLE, Key) of
107+
[] -> undefined;
108+
[Record] -> Record
109+
end.
110+
111+
%% -------------------------------------------------------------------
112+
%% lookup_or_set().
113+
%% -------------------------------------------------------------------
114+
115+
-spec lookup_or_set(Key, Default) -> Ret when
116+
Key :: atom() | {vhost:name(), binary(), binary()},
117+
Default :: any(),
118+
Ret :: #runtime_parameters{}.
119+
%% @doc Lookup runtime parameter or set its value if it does not exist.
120+
%%
121+
%% @private
122+
123+
lookup_or_set({VHostName, Comp, Name} = Key, Default)
124+
when is_binary(VHostName) andalso
125+
is_binary(Comp) andalso
126+
(is_binary(Name) orelse is_atom(Name)) ->
127+
rabbit_db:run(
128+
#{mnesia => fun() -> lookup_or_set_in_mnesia(Key, Default) end});
129+
lookup_or_set(Key, Default) ->
130+
rabbit_db:run(
131+
#{mnesia => fun() -> lookup_or_set_in_mnesia(Key, Default) end}).
132+
133+
lookup_or_set_in_mnesia(Key, Default) ->
134+
rabbit_misc:execute_mnesia_transaction(
135+
fun() -> lookup_or_set_in_mnesia_tx(Key, Default) end).
136+
137+
lookup_or_set_in_mnesia_tx(Key, Default) ->
138+
case mnesia:read(?MNESIA_TABLE, Key, read) of
139+
[Record] ->
140+
Record;
141+
[] ->
142+
Record = #runtime_parameters{key = Key,
143+
value = Default},
144+
mnesia:write(?MNESIA_TABLE, Record, write),
145+
Record
146+
end.
147+
148+
%% -------------------------------------------------------------------
149+
%% get_all().
150+
%% -------------------------------------------------------------------
151+
152+
-spec get_all() -> Ret when
153+
Ret :: [#runtime_parameters{}].
154+
%% @doc Gets all runtime parameters.
155+
%%
156+
%% @returns a list of runtime parameters records.
157+
%%
158+
%% @private
159+
160+
get_all() ->
161+
rabbit_db:run(
162+
#{mnesia => fun() -> get_all_in_mnesia() end}).
163+
164+
get_all_in_mnesia() ->
165+
rabbit_misc:dirty_read_all(?MNESIA_TABLE).
166+
167+
-spec get_all(VHostName, Comp) -> Ret when
168+
VHostName :: vhost:name() | '_',
169+
Comp :: binary() | '_',
170+
Ret :: [#runtime_parameters{}].
171+
%% @doc Gets all non-global runtime parameters matching the given virtual host
172+
%% and component.
173+
%%
174+
%% @returns a list of runtime parameters records.
175+
%%
176+
%% @private
177+
178+
get_all(VHostName, Comp)
179+
when (is_binary(VHostName) orelse VHostName =:= '_') andalso
180+
(is_binary(Comp) orelse Comp =:= '_') ->
181+
rabbit_db:run(
182+
#{mnesia => fun() -> get_all_in_mnesia(VHostName, Comp) end}).
183+
184+
get_all_in_mnesia(VHostName, Comp) ->
185+
mnesia:async_dirty(
186+
fun () ->
187+
case VHostName of
188+
'_' -> ok;
189+
_ -> rabbit_vhost:assert(VHostName)
190+
end,
191+
Match = #runtime_parameters{key = {VHostName, Comp, '_'},
192+
_ = '_'},
193+
mnesia:match_object(?MNESIA_TABLE, Match, read)
194+
end).
195+
196+
%% -------------------------------------------------------------------
197+
%% remove().
198+
%% -------------------------------------------------------------------
199+
200+
-spec remove(Key) -> ok when
201+
Key :: atom().
202+
%% @doc Removes the global runtime parameter named `Key'.
203+
%%
204+
%% @private
205+
206+
remove(Key) when is_atom(Key) ->
207+
rabbit_db:run(
208+
#{mnesia => fun() -> remove_in_mnesia(Key) end}).
209+
210+
-spec remove(VHostName, Comp, Name) -> ok when
211+
VHostName :: vhost:name() | '_',
212+
Comp :: binary() | '_',
213+
Name :: binary() | atom() | '_'.
214+
%% @doc Removes the non-global runtime parameter named `Name' for the given
215+
%% virtual host and component.
216+
%%
217+
%% @private
218+
219+
remove(VHostName, Comp, Name)
220+
when is_binary(VHostName) andalso
221+
is_binary(Comp) andalso
222+
(is_binary(Name) orelse (is_atom(Name) andalso Name =/= '_')) ->
223+
Key = {VHostName, Comp, Name},
224+
rabbit_db:run(
225+
#{mnesia => fun() -> remove_in_mnesia(Key) end});
226+
remove(VHostName, Comp, Name)
227+
when VHostName =:= '_' orelse Comp =:= '_' orelse Name =:= '_' ->
228+
rabbit_db:run(
229+
#{mnesia =>
230+
fun() -> remove_matching_in_mnesia(VHostName, Comp, Name) end}).
231+
232+
remove_in_mnesia(Key) ->
233+
rabbit_misc:execute_mnesia_transaction(
234+
fun() -> remove_in_mnesia_tx(Key) end).
235+
236+
remove_in_mnesia_tx(Key) ->
237+
mnesia:delete(?MNESIA_TABLE, Key, write).
238+
239+
remove_matching_in_mnesia(VHostName, Comp, Name) ->
240+
rabbit_misc:execute_mnesia_transaction(
241+
fun() -> remove_matching_in_mnesia_tx(VHostName, Comp, Name) end).
242+
243+
remove_matching_in_mnesia_tx(VHostName, Comp, Name) ->
244+
Match = #runtime_parameters{key = {VHostName, Comp, Name},
245+
_ = '_'},
246+
_ = [ok = mnesia:delete(?MNESIA_TABLE, Key, write)
247+
|| #runtime_parameters{key = Key} <-
248+
mnesia:match_object(?MNESIA_TABLE, Match, write)],
249+
ok.

0 commit comments

Comments
 (0)