-
Notifications
You must be signed in to change notification settings - Fork 3.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Per vhost message store #766
Merged
Merged
Changes from 20 commits
Commits
Show all changes
55 commits
Select commit
Hold shift + click to select a range
abaa770
message store supervisor
80436df
Starting and restarting app
ec15e97
Migration algorithm
d1bffd0
Work in progress: Migration to vhost based message store
b3fc71a
wip
492e23b
wip: migrating to vhost base messge store
325e2fc
New upgrade scope `queues` started by boot step before queue recovery
d1f4a9d
Remove duplicate migration. Match no_ack message
93ba24b
Moved directory selection to vhost_dir function
460abf2
Update tests
fdd7b87
Updated tests to support per-vhost message store
e6c76fd
Queue index per vhost location
4f12ebe
Tests for per-vhost message store. Stop vhost message store when dele…
fd4db66
Terminate message store ignoring file save errors
8369950
Allow restart of a vhost message store. purge_messages function to cl…
1c81c50
Move queues to vhost storage on upgrade
8a45f40
Migration to per-vhost store message
36f3e67
Purge vhost storage in transaction
008c4eb
Rename an upgrade function
michaelklishin 4837af6
Merge branch 'master' into rabbitmq-server-567
michaelklishin 05e9dbe
Naming and cosmetics
michaelklishin 0b37027
Merge branch 'master' into rabbitmq-server-567
cc75e56
Avoid atom exhaustion in vhost message stores
eea4fc3
Use a fixed size encoding fn for vhost directory names
michaelklishin 1643c34
Renames
michaelklishin 460d413
We get a tuple from ETS here, not just a pid
michaelklishin 245fd08
Fix test expectations, more renames, more logging
michaelklishin 7a84a24
Towards functional message store migration fn
michaelklishin f6feb6b
Cosmetics
michaelklishin c135b70
New dir path for queue index data
3542d80
Merge branch 'master' into rabbitmq-server-567
c3ae581
Rollback to sequential queue migration. Move queue directories before…
944e0f4
Fix vhost dir location in test
03bdc78
Keep backup between mnesia upgrade and message store upgrade
5545152
Migrate queues in batches of 100 in parallel. Write recovery terms fo…
475e86b
Merge branch 'master' into rabbitmq-server-567
cfc9a88
Write per queue upgrade log to a separate file
f43990d
Make queue migration batch size configurable
321abd4
Merge branch 'master' into rabbitmq-server-567
dcorbacho 806cd80
Replace dying_client_index and dying_clients set with a map
8a98bdb
Merge branch 'master' into rabbitmq-server-567
michaelklishin 3d56870
fix typo
5f7553c
Merge branch 'master' into rabbitmq-server-567
308a2b5
Group recovery client refs by vhost
1ec2ac8
Pass queues and recovery terms to fold
eafad5a
Refs can be undefined
569d114
change error function with rabbit_log:error
e5557ad
Fix msg_store test
1403596
Force recover client references to be maps. Start empty message store…
5282534
Recover vhosts message stores in parallel after a crash
79685d0
Recover queues after non-clean shutdown
83d3222
Fix logs. Expect multiple logs during startup
12901fb
Revert to syncronous vhost recovery since there are concurency limita…
bcff954
Merge branch 'master' into rabbitmq-server-567
michaelklishin 1d4e939
Don't log #resource records
michaelklishin File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
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
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
-module(rabbit_msg_store_vhost_sup). | ||
|
||
-behaviour(supervisor2). | ||
|
||
-export([start_link/3, init/1, add_vhost/2, delete_vhost/2, | ||
client_init/5, successfully_recovered_state/2]). | ||
|
||
%% Internal | ||
-export([start_vhost/4]). | ||
|
||
start_link(Name, ClientRefs, StartupFunState) -> | ||
supervisor2:start_link({local, Name}, ?MODULE, | ||
[Name, ClientRefs, StartupFunState]). | ||
|
||
init([Name, ClientRefs, StartupFunState]) -> | ||
{ok, {{simple_one_for_one, 1, 1}, | ||
[{rabbit_msg_store_vhost, {rabbit_msg_store_vhost_sup, start_vhost, | ||
[Name, ClientRefs, StartupFunState]}, | ||
transient, infinity, supervisor, [rabbit_msg_store]}]}}. | ||
|
||
|
||
add_vhost(Name, VHost) -> | ||
supervisor2:start_child(Name, [VHost]). | ||
|
||
start_vhost(Name, ClientRefs, StartupFunState, VHost) -> | ||
VHostName = vhost_store_name(Name, VHost), | ||
VHostDir = vhost_store_dir(VHost), | ||
ok = rabbit_file:ensure_dir(VHostDir), | ||
rabbit_msg_store:start_link(VHostName, VHostDir, | ||
ClientRefs, StartupFunState). | ||
|
||
delete_vhost(Name, VHost) -> | ||
VHostName = vhost_store_name(Name, VHost), | ||
case whereis(VHostName) of | ||
undefined -> ok; | ||
Pid -> supervisor2:terminate_child(Name, Pid) | ||
end, | ||
ok. | ||
|
||
client_init(Server, Ref, MsgOnDiskFun, CloseFDsFun, VHost) -> | ||
VHostName = maybe_start_vhost(Server, VHost), | ||
rabbit_msg_store:client_init(VHostName, Ref, MsgOnDiskFun, CloseFDsFun). | ||
|
||
maybe_start_vhost(Server, VHost) -> | ||
VHostName = vhost_store_name(Server, VHost), | ||
case whereis(VHostName) of | ||
undefined -> add_vhost(Server, VHost); | ||
_ -> ok | ||
end, | ||
VHostName. | ||
|
||
vhost_store_name(Name, VHost) -> | ||
VhostEncoded = rabbit_vhost:dir(VHost), | ||
binary_to_atom(<<(atom_to_binary(Name, utf8))/binary, "_", | ||
VhostEncoded/binary>>, | ||
utf8). | ||
|
||
vhost_store_dir(VHost) -> | ||
Dir = rabbit_mnesia:dir(), | ||
VhostEncoded = rabbit_vhost:dir(VHost), | ||
binary_to_list(filename:join([Dir, VhostEncoded])). | ||
|
||
successfully_recovered_state(Name, VHost) -> | ||
VHostName = vhost_store_name(Name, VHost), | ||
rabbit_msg_store:successfully_recovered_state(VHostName). | ||
|
||
% force_recovery | ||
% transform_dir |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -23,6 +23,10 @@ | |
read/3, next_segment_boundary/1, bounds/1, start/1, stop/0]). | ||
|
||
-export([add_queue_ttl/0, avoid_zeroes/0, store_msg_size/0, store_msg/0]). | ||
-export([scan_queue_segments/3]). | ||
|
||
%% Migration to per-vhost message store | ||
-export([move_to_vhost_store/1]). | ||
|
||
-define(CLEAN_FILENAME, "clean.dot"). | ||
|
||
|
@@ -475,11 +479,10 @@ start(DurableQueueNames) -> | |
end, {[], sets:new()}, DurableQueueNames), | ||
|
||
%% Any queue directory we've not been asked to recover is considered garbage | ||
QueuesDir = queues_dir(), | ||
rabbit_file:recursive_delete( | ||
[filename:join(QueuesDir, DirName) || | ||
DirName <- all_queue_directory_names(QueuesDir), | ||
not sets:is_element(DirName, DurableDirectories)]), | ||
[DirName || | ||
DirName <- all_queue_directory_names(), | ||
not sets:is_element(filename:basename(DirName), DurableDirectories)]), | ||
|
||
rabbit_recovery_terms:clear(), | ||
|
||
|
@@ -490,12 +493,9 @@ start(DurableQueueNames) -> | |
|
||
stop() -> rabbit_recovery_terms:stop(). | ||
|
||
all_queue_directory_names(Dir) -> | ||
case rabbit_file:list_dir(Dir) of | ||
{ok, Entries} -> [E || E <- Entries, | ||
rabbit_file:is_dir(filename:join(Dir, E))]; | ||
{error, enoent} -> [] | ||
end. | ||
all_queue_directory_names() -> | ||
QueuesBaseDir = queues_base_dir(), | ||
filelib:wildcard(filename:join([QueuesBaseDir, "*", "queues", "*"])). | ||
|
||
%%---------------------------------------------------------------------------- | ||
%% startup and shutdown | ||
|
@@ -508,14 +508,18 @@ erase_index_dir(Dir) -> | |
end. | ||
|
||
blank_state(QueueName) -> | ||
blank_state_dir( | ||
filename:join(queues_dir(), queue_name_to_dir_name(QueueName))). | ||
blank_state_dir(queue_dir(QueueName)). | ||
|
||
blank_state_dir(Dir) -> | ||
blank_state_dir_funs(Dir, | ||
fun (_) -> ok end, | ||
fun (_) -> ok end). | ||
|
||
queue_dir(#resource{ virtual_host = VHost } = QueueName) -> | ||
%% Queue directory is rabbit_mnesia_dir/:vhost/queues/:queue_id | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It would be a bit clearer if we used |
||
filename:join([queues_base_dir(), rabbit_vhost:dir(VHost), | ||
"queues", queue_name_to_dir_name(QueueName)]). | ||
|
||
blank_state_dir_funs(Dir, OnSyncFun, OnSyncMsgFun) -> | ||
{ok, MaxJournal} = | ||
application:get_env(rabbit, queue_index_max_journal_entries), | ||
|
@@ -629,8 +633,8 @@ queue_name_to_dir_name(Name = #resource { kind = queue }) -> | |
<<Num:128>> = erlang:md5(term_to_binary(Name)), | ||
rabbit_misc:format("~.36B", [Num]). | ||
|
||
queues_dir() -> | ||
filename:join(rabbit_mnesia:dir(), "queues"). | ||
queues_base_dir() -> | ||
rabbit_mnesia:dir(). | ||
|
||
%%---------------------------------------------------------------------------- | ||
%% msg store startup delta function | ||
|
@@ -660,20 +664,19 @@ queue_index_walker({next, Gatherer}) when is_pid(Gatherer) -> | |
end. | ||
|
||
queue_index_walker_reader(QueueName, Gatherer) -> | ||
State = blank_state(QueueName), | ||
ok = scan_segments( | ||
ok = scan_queue_segments( | ||
fun (_SeqId, MsgId, _MsgProps, true, _IsDelivered, no_ack, ok) | ||
when is_binary(MsgId) -> | ||
gatherer:sync_in(Gatherer, {MsgId, 1}); | ||
(_SeqId, _MsgId, _MsgProps, _IsPersistent, _IsDelivered, | ||
_IsAcked, Acc) -> | ||
Acc | ||
end, ok, State), | ||
end, ok, QueueName), | ||
ok = gatherer:finish(Gatherer). | ||
|
||
scan_segments(Fun, Acc, State) -> | ||
State1 = #qistate { segments = Segments, dir = Dir } = | ||
recover_journal(State), | ||
scan_queue_segments(Fun, Acc, QueueName) -> | ||
State = #qistate { segments = Segments, dir = Dir } = | ||
recover_journal(blank_state(QueueName)), | ||
Result = lists:foldr( | ||
fun (Seg, AccN) -> | ||
segment_entries_foldr( | ||
|
@@ -682,8 +685,8 @@ scan_segments(Fun, Acc, State) -> | |
Fun(reconstruct_seq_id(Seg, RelSeq), MsgOrId, MsgProps, | ||
IsPersistent, IsDelivered, IsAcked, AccM) | ||
end, AccN, segment_find_or_new(Seg, Dir, Segments)) | ||
end, Acc, all_segment_nums(State1)), | ||
{_SegmentCounts, _State} = terminate(State1), | ||
end, Acc, all_segment_nums(State)), | ||
{_SegmentCounts, _State} = terminate(State), | ||
Result. | ||
|
||
%%---------------------------------------------------------------------------- | ||
|
@@ -1353,15 +1356,13 @@ store_msg_segment(_) -> | |
%%---------------------------------------------------------------------------- | ||
|
||
foreach_queue_index(Funs) -> | ||
QueuesDir = queues_dir(), | ||
QueueDirNames = all_queue_directory_names(QueuesDir), | ||
QueueDirNames = all_queue_directory_names(), | ||
{ok, Gatherer} = gatherer:start_link(), | ||
[begin | ||
ok = gatherer:fork(Gatherer), | ||
ok = worker_pool:submit_async( | ||
fun () -> | ||
transform_queue(filename:join(QueuesDir, QueueDirName), | ||
Gatherer, Funs) | ||
transform_queue(QueueDirName, Gatherer, Funs) | ||
end) | ||
end || QueueDirName <- QueueDirNames], | ||
empty = gatherer:out(Gatherer), | ||
|
@@ -1402,3 +1403,17 @@ drive_transform_fun(Fun, Hdl, Contents) -> | |
{Output, Contents1} -> ok = file_handle_cache:append(Hdl, Output), | ||
drive_transform_fun(Fun, Hdl, Contents1) | ||
end. | ||
|
||
move_to_vhost_store(#resource{} = QueueName) -> | ||
OldQueueDir = filename:join([queues_base_dir(), "queues", | ||
queue_name_to_dir_name(QueueName)]), | ||
NewQueueDir = queue_dir(QueueName), | ||
case rabbit_file:is_dir(OldQueueDir) of | ||
true -> | ||
ok = rabbit_file:ensure_dir(NewQueueDir), | ||
ok = rabbit_file:rename(OldQueueDir, NewQueueDir); | ||
false -> | ||
rabbit_log:info("Queue index directoy not found for queue ~p~n", | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
[QueueName]) | ||
end, | ||
ok. |
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
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See below. It would be less risky if we used
{node_database_dir}/vhosts/{vhost}/queues/{queue}
for path naming.