Skip to content

Commit d297dfb

Browse files
author
Simon MacMullen
committed
Merge bug 24561 (x-ha-policy=nodes doesn't fully cope with failure of master)
2 parents 251dc0c + 5930d04 commit d297dfb

File tree

8 files changed

+92
-28
lines changed

8 files changed

+92
-28
lines changed

docs/rabbitmqctl.1.xml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1315,6 +1315,22 @@
13151315
</para>
13161316
</listitem>
13171317
</varlistentry>
1318+
1319+
<varlistentry>
1320+
<term><cmdsynopsis><command>eval</command> <arg choice="req"><replaceable>expr</replaceable></arg></cmdsynopsis></term>
1321+
<listitem>
1322+
<para>
1323+
Evaluate an arbitrary Erlang expression.
1324+
</para>
1325+
<para role="example-prefix">
1326+
For example:
1327+
</para>
1328+
<screen role="example">rabbitmqctl eval 'node().'</screen>
1329+
<para role="example">
1330+
This command returns the name of the node to which rabbitmqctl has connected.
1331+
</para>
1332+
</listitem>
1333+
</varlistentry>
13181334
</variablelist>
13191335
</refsect2>
13201336

src/mirrored_supervisor_tests.erl

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,9 @@ all_tests() ->
3636
passed = test_already_there(),
3737
passed = test_delete_restart(),
3838
passed = test_which_children(),
39-
passed = test_large_group(),
39+
%% commented out in order to determine whether this is the only test
40+
%% that is failing - see bug 24362
41+
%% passed = test_large_group(),
4042
passed = test_childspecs_at_init(),
4143
passed = test_anonymous_supervisors(),
4244
passed = test_no_migration_on_shutdown(),
@@ -158,7 +160,7 @@ test_no_migration_on_shutdown() ->
158160
try
159161
call(worker, ping),
160162
exit(worker_should_not_have_migrated)
161-
catch exit:{timeout_waiting_for_server, _} ->
163+
catch exit:{timeout_waiting_for_server, _, _} ->
162164
ok
163165
end
164166
end, [evil, good]).
@@ -245,10 +247,10 @@ inc_group() ->
245247
get_group(Group) ->
246248
{Group, get(counter)}.
247249

248-
call(Id, Msg) -> call(Id, Msg, 100, 10).
250+
call(Id, Msg) -> call(Id, Msg, 1000, 100).
249251

250252
call(Id, Msg, 0, _Decr) ->
251-
exit({timeout_waiting_for_server, {Id, Msg}});
253+
exit({timeout_waiting_for_server, {Id, Msg}, erlang:get_stacktrace()});
252254

253255
call(Id, Msg, MaxDelay, Decr) ->
254256
try

src/rabbit_control.erl

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,9 @@ start() ->
9898
{error, Reason} ->
9999
print_error("~p", [Reason]),
100100
rabbit_misc:quit(2);
101+
{error_string, Reason} ->
102+
print_error("~s", [Reason]),
103+
rabbit_misc:quit(2);
101104
{badrpc, {'EXIT', Reason}} ->
102105
print_error("~p", [Reason]),
103106
rabbit_misc:quit(2);
@@ -368,7 +371,23 @@ action(report, Node, _Args, _Opts, Inform) ->
368371
[print_report(Node, Q) || Q <- ?GLOBAL_QUERIES],
369372
[print_report(Node, Q, [V]) || Q <- ?VHOST_QUERIES, V <- VHosts],
370373
io:format("End of server status report~n"),
371-
ok.
374+
ok;
375+
376+
action(eval, Node, [Expr], _Opts, _Inform) ->
377+
case erl_scan:string(Expr) of
378+
{ok, Scanned, _} ->
379+
case erl_parse:parse_exprs(Scanned) of
380+
{ok, Parsed} ->
381+
{value, Value, _} = unsafe_rpc(
382+
Node, erl_eval, exprs, [Parsed, []]),
383+
io:format("~p~n", [Value]),
384+
ok;
385+
{error, E} ->
386+
{error_string, format_parse_error(E)}
387+
end;
388+
{error, E, _} ->
389+
{error_string, format_parse_error(E)}
390+
end.
372391

373392
%%----------------------------------------------------------------------------
374393

@@ -443,6 +462,9 @@ system(Cmd) ->
443462
escape_quotes(Cmd) ->
444463
lists:flatten(lists:map(fun ($') -> "'\\''"; (Ch) -> Ch end, Cmd)).
445464

465+
format_parse_error({_Line, Mod, Err}) ->
466+
lists:flatten(Mod:format_error(Err)).
467+
446468
%%----------------------------------------------------------------------------
447469

448470
default_if_empty(List, Default) when is_list(List) ->

src/rabbit_guid.erl

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,8 +89,15 @@ guid() ->
8989
erlang:md5(term_to_binary(G)).
9090

9191
%% generate a readable string representation of a GUID.
92+
%%
93+
%% employs base64url encoding, which is safer in more contexts than
94+
%% plain base64.
9295
string_guid(Prefix) ->
93-
Prefix ++ "-" ++ base64:encode_to_string(guid()).
96+
Prefix ++ "-" ++ lists:foldl(fun ($\+, Acc) -> [$\- | Acc];
97+
($\/, Acc) -> [$\_ | Acc];
98+
($\=, Acc) -> Acc;
99+
(Chr, Acc) -> [Chr | Acc]
100+
end, [], base64:encode_to_string(guid())).
94101

95102
binstring_guid(Prefix) ->
96103
list_to_binary(string_guid(Prefix)).

src/rabbit_mirror_queue_slave.erl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -725,7 +725,7 @@ process_instruction(
725725
never ->
726726
{MQ2, PendingCh, MS};
727727
eventually ->
728-
{MQ2, sets:add_element(MsgId, PendingCh),
728+
{MQ2, PendingCh,
729729
dict:store(MsgId, {published, ChPid, MsgSeqNo}, MS)};
730730
immediately ->
731731
ok = rabbit_channel:confirm(ChPid, [MsgSeqNo]),

src/rabbit_misc.erl

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -250,18 +250,23 @@ assert_args_equivalence(Orig, New, Name, Keys) ->
250250
ok.
251251

252252
assert_args_equivalence1(Orig, New, Name, Key) ->
253-
case {table_lookup(Orig, Key), table_lookup(New, Key)} of
253+
{Orig1, New1} = {table_lookup(Orig, Key), table_lookup(New, Key)},
254+
FailureFun = fun () ->
255+
protocol_error(precondition_failed, "inequivalent arg '~s'"
256+
"for ~s: received ~s but current is ~s",
257+
[Key, rs(Name), val(New1), val(Orig1)])
258+
end,
259+
case {Orig1, New1} of
254260
{Same, Same} ->
255261
ok;
256-
{{OrigType, OrigVal} = Orig1, {NewType, NewVal} = New1} ->
262+
{{OrigType, OrigVal}, {NewType, NewVal}} ->
257263
case type_class(OrigType) == type_class(NewType) andalso
258264
OrigVal == NewVal of
259265
true -> ok;
260-
false -> protocol_error(precondition_failed, "inequivalent arg"
261-
" '~s' for ~s: received ~s but current"
262-
" is ~s",
263-
[Key, rs(Name), val(New1), val(Orig1)])
264-
end
266+
false -> FailureFun()
267+
end;
268+
{_, _} ->
269+
FailureFun()
265270
end.
266271

267272
val(undefined) ->

src/rabbit_networking.erl

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -307,9 +307,15 @@ connections() ->
307307
rabbit_networking, connections_local, []).
308308

309309
connections_local() ->
310-
[rabbit_connection_sup:reader(ConnSup) ||
310+
[Reader ||
311311
{_, ConnSup, supervisor, _}
312-
<- supervisor:which_children(rabbit_tcp_client_sup)].
312+
<- supervisor:which_children(rabbit_tcp_client_sup),
313+
Reader <- [try
314+
rabbit_connection_sup:reader(ConnSup)
315+
catch exit:{noproc, _} ->
316+
noproc
317+
end],
318+
Reader =/= noproc].
313319

314320
connection_info_keys() -> rabbit_reader:info_keys().
315321

src/rabbit_queue_index.erl

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -505,7 +505,10 @@ queue_index_walker({start, DurableQueues}) when is_list(DurableQueues) ->
505505
[begin
506506
ok = gatherer:fork(Gatherer),
507507
ok = worker_pool:submit_async(
508-
fun () -> queue_index_walker_reader(QueueName, Gatherer)
508+
fun () -> link(Gatherer),
509+
ok = queue_index_walker_reader(QueueName, Gatherer),
510+
unlink(Gatherer),
511+
ok
509512
end)
510513
end || QueueName <- DurableQueues],
511514
queue_index_walker({next, Gatherer});
@@ -837,13 +840,16 @@ segment_entries_foldr(Fun, Init,
837840
%%
838841
%% Does not do any combining with the journal at all.
839842
load_segment(KeepAcked, #segment { path = Path }) ->
843+
Empty = {array_new(), 0},
840844
case rabbit_file:is_file(Path) of
841-
false -> {array_new(), 0};
845+
false -> Empty;
842846
true -> {ok, Hdl} = file_handle_cache:open(Path, ?READ_AHEAD_MODE, []),
843847
{ok, 0} = file_handle_cache:position(Hdl, bof),
844-
{ok, SegData} = file_handle_cache:read(
845-
Hdl, ?SEGMENT_TOTAL_SIZE),
846-
Res = load_segment_entries(KeepAcked, SegData, array_new(), 0),
848+
Res = case file_handle_cache:read(Hdl, ?SEGMENT_TOTAL_SIZE) of
849+
{ok, SegData} -> load_segment_entries(
850+
KeepAcked, SegData, Empty);
851+
eof -> Empty
852+
end,
847853
ok = file_handle_cache:close(Hdl),
848854
Res
849855
end.
@@ -853,15 +859,15 @@ load_segment_entries(KeepAcked,
853859
IsPersistentNum:1, RelSeq:?REL_SEQ_BITS,
854860
PubRecordBody:?PUB_RECORD_BODY_BYTES/binary,
855861
SegData/binary>>,
856-
SegEntries, UnackedCount) ->
862+
{SegEntries, UnackedCount}) ->
857863
{MsgId, MsgProps} = parse_pub_record_body(PubRecordBody),
858864
Obj = {{MsgId, MsgProps, 1 == IsPersistentNum}, no_del, no_ack},
859865
SegEntries1 = array:set(RelSeq, Obj, SegEntries),
860-
load_segment_entries(KeepAcked, SegData, SegEntries1, UnackedCount + 1);
866+
load_segment_entries(KeepAcked, SegData, {SegEntries1, UnackedCount + 1});
861867
load_segment_entries(KeepAcked,
862868
<<?REL_SEQ_ONLY_PREFIX:?REL_SEQ_ONLY_PREFIX_BITS,
863869
RelSeq:?REL_SEQ_BITS, SegData/binary>>,
864-
SegEntries, UnackedCount) ->
870+
{SegEntries, UnackedCount}) ->
865871
{UnackedCountDelta, SegEntries1} =
866872
case array:get(RelSeq, SegEntries) of
867873
{Pub, no_del, no_ack} ->
@@ -871,10 +877,10 @@ load_segment_entries(KeepAcked,
871877
{_Pub, del, no_ack} ->
872878
{-1, array:reset(RelSeq, SegEntries)}
873879
end,
874-
load_segment_entries(KeepAcked, SegData, SegEntries1,
875-
UnackedCount + UnackedCountDelta);
876-
load_segment_entries(_KeepAcked, _SegData, SegEntries, UnackedCount) ->
877-
{SegEntries, UnackedCount}.
880+
load_segment_entries(KeepAcked, SegData,
881+
{SegEntries1, UnackedCount + UnackedCountDelta});
882+
load_segment_entries(_KeepAcked, _SegData, Res) ->
883+
Res.
878884

879885
array_new() ->
880886
array:new([{default, undefined}, fixed, {size, ?SEGMENT_ENTRY_COUNT}]).

0 commit comments

Comments
 (0)