Skip to content
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

Merge emqx otp 26.2.1 to emqx otp 26.2.2 #50

Merged
merged 42 commits into from
Mar 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
ba7ad19
emqx: add 'emqx' to beam boot log
zmstone Apr 9, 2021
8cf0a0b
emqx: dynmaic ipv6 resolution for gen_tcp
zmstone Apr 9, 2021
be79756
Configurable send table batch size.
qzhuyan Mar 30, 2021
6c3d512
mnesia send_table_batch_size as app env.
qzhuyan Mar 30, 2021
95d408c
mnesia: copy table from a specified node
qzhuyan Mar 31, 2021
7887d0e
chore: export gen_tcp:ipv6_probe/0 as emqx's fork identifier
zmstone Nov 16, 2021
2a0e1d5
mnesia: Add post-commit hook
thalesmg Jan 24, 2022
44379b8
feat: add minimal/experimental OCSP server support (TLS 1.2 and 1.3) …
thalesmg May 31, 2022
e6dad3a
chore: bump OTP version to 25.1.2-1
keynslug Dec 5, 2022
b8edd91
Merge pull request #31 from keynslug/emqx-OTP-25.1.2
keynslug Dec 6, 2022
9a2cba8
feat(ssl): no warning log when using verify_none
Dec 1, 2021
550f66a
ci: disable corresponding testcase
keynslug Dec 7, 2022
75b0adf
Merge pull request #32 from keynslug/emqx-OTP-25.1.2
keynslug Dec 7, 2022
e7e56f6
fix(ipv6_probe): handle local sockets properly
keynslug Dec 8, 2022
76d5b06
Merge pull request #33 from keynslug/emqx-OTP-25.1.2
keynslug Dec 8, 2022
fdd8f93
fix(vsn): bump OTP version to 25.1.2-2
keynslug Dec 8, 2022
76cda5a
Merge pull request #34 from keynslug/emqx-OTP-25.1.2
keynslug Dec 8, 2022
56c54f7
feat(mnesia): implement unregister_hook/1 in mnesia_hook.erl
SergeTupchiy Mar 21, 2023
085dda3
chore: bump otp version to 25.1.2-3
SergeTupchiy Mar 21, 2023
538c947
Merge pull request #38 from SergeTupchiy/mnesia/port-unregister-mnesi…
SergeTupchiy Mar 21, 2023
5c9f494
Merge remote-tracking branch 'emqx/emqx-OTP-25.1.2' into emqx-OTP-25.3.2
zmstone May 30, 2023
8639768
Merge pull request #40 from emqx/merge-25.1.2-to-25.3.2
zmstone May 31, 2023
3052272
fix(mnesia): exclude sensitive data from mnesia_hook log message
SergeTupchiy Aug 21, 2023
23e873f
fix(mnesia): report mnesia_hook post_commit failures at debug level
SergeTupchiy Aug 22, 2023
dfc38ee
chore: bump otp version to 25.3.2-2
SergeTupchiy Aug 21, 2023
e879558
Merge pull request #41 from SergeTupchiy/EMQX-10390-hide-sensitive-da…
SergeTupchiy Aug 22, 2023
f1511c9
Merge remote-tracking branch 'emqx/emqx-OTP-25.3.2' into merge-25-3-2…
thalesmg Nov 21, 2023
51b1d8a
test(ssl_api): remove references to non-existent test cases
thalesmg Nov 21, 2023
eed9fec
chore: prepare to tag 26.1.2-1
thalesmg Nov 21, 2023
281447f
Merge pull request #43 from thalesmg/merge-25-3-2-to-26-1-2-20231121
thalesmg Nov 22, 2023
2b642a1
stdlib: Prevent crash when writing a faulty attribute like '1> -hej.'
frazze-jobb Oct 27, 2023
87f2728
stdlib: Allow local func v(), in a restricted shell
frazze-jobb Oct 27, 2023
b7f0590
Merge pull request #44 from emqx/fix-v-command-not-found
zhongwencool Dec 6, 2023
dc2ae54
chore: bump OTP_VERSION to 26.1.2-2
zmstone Dec 11, 2023
d54de5f
feat: implement `mnesia:match_delete/2` function
SergeTupchiy Dec 13, 2023
6630e28
chore: bump OTP_VERSION to 26.1.2-3
SergeTupchiy Dec 14, 2023
be6661c
Merge pull request #46 from SergeTupchiy/add-mnesia-match_delete-OTP-26
SergeTupchiy Dec 18, 2023
0ad4972
Merge remote-tracking branch 'emqx/emqx-OTP-26.1.2' into emqx-OTP-26.2.1
zmstone Dec 28, 2023
5848055
ssl: Fix legacy name handling in certificate request too
IngelaAndin Jan 3, 2024
26b68b6
chore: bump to version 26.2.1-2
zmstone Jan 10, 2024
0324419
Merge remote-tracking branch 'emqx/emqx-OTP-26.2.1' into merge-emqx-O…
qzhuyan Mar 6, 2024
89a171a
chore: bump emqx OTP version 26.2.2-1
qzhuyan Mar 6, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion OTP_VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
26.2.2
26.2.2-1
4 changes: 2 additions & 2 deletions erts/emulator/beam/erl_bif_info.c
Original file line number Diff line number Diff line change
Expand Up @@ -88,9 +88,9 @@ static char erts_system_version[] = ("Erlang/OTP " ERLANG_OTP_RELEASE
" [erts-" ERLANG_VERSION "]"
#ifndef OTP_RELEASE
#ifdef ERLANG_GIT_VERSION
" [source-" ERLANG_GIT_VERSION "]"
" [emqx-" ERLANG_GIT_VERSION "]"
#else
" [source]"
" [emqx]"
#endif
#endif
#if defined(ARCH_64)
Expand Down
95 changes: 84 additions & 11 deletions lib/kernel/src/gen_tcp.erl
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
-export([send/2, recv/2, recv/3, unrecv/2]).
-export([controlling_process/2]).
-export([fdopen/2]).
-export([ipv6_probe/0]).

-include("inet_int.hrl").
-include("file.hrl").
Expand Down Expand Up @@ -120,7 +121,8 @@
recvtclass |
recvttl |
pktoptions |
ipv6_v6only.
ipv6_v6only |
ipv6_probe.
-type connect_option() ::
{fd, Fd :: non_neg_integer()} |
inet:address_family() |
Expand All @@ -131,6 +133,7 @@
{tcp_module, module()} |
{netns, file:filename_all()} |
{bind_to_device, binary()} |
{ipv6_probe, boolean() | timeout()} |
option().
-type listen_option() ::
{fd, Fd :: non_neg_integer()} |
Expand All @@ -157,6 +160,8 @@
%% Connect a socket
%%

ipv6_probe() -> true.

-spec connect(SockAddr, Opts) -> {ok, Socket} | {error, Reason} when
SockAddr :: socket:sockaddr_in() | socket:sockaddr_in6(),
Opts :: [inet:inet_backend() | connect_option()],
Expand Down Expand Up @@ -218,21 +223,89 @@ connect(#{family := Fam} = SockAddr, Opts, Timeout)
Reason :: timeout | inet:posix().

connect(Address, Port, Opts0, Timeout) ->
case inet:gen_tcp_module(Opts0) of
%% When neither `inet` nor `inet6` is provided in Opts0,
%% and if `ipv6_probe` option is given, try to connect ipv6 first.
{TryIpv6, Ipv6T} =
case proplists:get_value(ipv6_probe, Opts0) of
true -> {true, 2000}; %% default 2 seconds
false -> {false, 0};
undefined -> {false, 0};
T -> {true, T}
end,
%% delete it to avoid interference
Opts1 = proplists:delete(ipv6_probe, Opts0),
case inet:gen_tcp_module(Opts1) of
{?MODULE, Opts} ->
Timer = inet:start_timer(Timeout),
Res = (catch connect1(Address,Port,Opts,Timer)),
_ = inet:stop_timer(Timer),
case Res of
{ok,S} -> {ok,S};
{error, einval} -> exit(badarg);
{'EXIT',Reason} -> exit(Reason);
Error -> Error
end;
connect_maybe_ipv6(Address, Port, Opts, Timeout, TryIpv6, Ipv6T);
{GenTcpMod, Opts} ->
GenTcpMod:connect(Address, Port, Opts, Timeout)
end.

connect_maybe_ipv6(Address, Port, Opts, Timeout, TryIpv6, Ipv6T) ->
case maybe_ipv6(Address, Opts, TryIpv6) of
{maybe, NewOpts} when TryIpv6 ->
try
{ok, _} = connect_0(Address, Port, NewOpts, Ipv6T)
catch
_ : _ ->
%% fallback
connect_0(Address, Port, Opts, Timeout)
end;
NewOpts ->
connect_0(Address, Port, NewOpts, Timeout)
end.

connect_0(Address, Port, Opts, Timeout) ->
Timer = inet:start_timer(Timeout),
Res = (catch connect1(Address,Port,Opts,Timer)),
_ = inet:stop_timer(Timer),
case Res of
{ok,S} -> {ok,S};
{error, einval} -> exit(badarg);
{'EXIT',Reason} -> exit(Reason);
Error -> Error
end.

maybe_ipv6({local, _}, Opts, _TryIpv6) ->
%% unapplicable to local sockets
Opts;
maybe_ipv6(Host, Opts, TryIpv6) ->
case lists:member(inet, Opts) orelse lists:member(inet6, Opts) of
true ->
Opts; %% caller has made the decision
false when is_tuple(Host) ->
%% ip tuple provided
maybe_ipv6_1(Host, Opts);
false when TryIpv6 ->
%% string host
maybe_ipv6_2(Host, Opts);
false ->
Opts
end.

maybe_ipv6_1(Ip, Opts) when tuple_size(Ip) =:= 4 -> Opts;
maybe_ipv6_1(Ip, Opts) when tuple_size(Ip) =:= 8 -> [inet6 | Opts].

maybe_ipv6_2(Host, Opts) ->
case inet:parse_address(Host) of
{ok, Ip} when is_tuple(Ip) ->
%% ip string provided, parsed into tuple
maybe_ipv6_1(Ip, Opts);
_ ->
maybe_ipv6_3(Host, Opts)
end.

maybe_ipv6_3(Host, Opts) ->
case inet:getaddr(Host, inet6) of
{ok, _} ->
%% the target has a resolvable v6 IP
%% maybe try to connect
{maybe, [inet6 | Opts]};
_ ->
%% the target has no resolvable v6 IP
Opts
end.

connect1(Address, Port, Opts0, Timer) ->
{Mod, Opts} = inet:tcp_module(Opts0, Address),
case Mod:getaddrs(Address, Timer) of
Expand Down
1 change: 1 addition & 0 deletions lib/mnesia/src/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ MODULES= \
mnesia_ext_sup \
mnesia_frag \
mnesia_frag_hash \
mnesia_hook \
mnesia_index \
mnesia_kernel_sup \
mnesia_late_loader \
Expand Down
1 change: 1 addition & 0 deletions lib/mnesia/src/mnesia.app.src
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
mnesia_ext_sup,
mnesia_frag,
mnesia_frag_hash,
mnesia_hook,
mnesia_index,
mnesia_kernel_sup,
mnesia_late_loader,
Expand Down
15 changes: 10 additions & 5 deletions lib/mnesia/src/mnesia.erl
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@
read_table_property/2, write_table_property/2, delete_table_property/2,
change_table_frag/2,
clear_table/1, clear_table/4,
match_delete/2,

%% Table load
dump_tables/1, wait_for_tables/2, force_load_table/1,
Expand Down Expand Up @@ -2812,21 +2813,25 @@ change_table_copy_type(T, N, S) ->

-spec clear_table(Tab::table()) -> t_result('ok').
clear_table(Tab) ->
match_delete(Tab, '_').

-spec match_delete(Tab::table(), ets:match_pattern()) -> t_result('ok').
match_delete(Tab, Pattern) ->
case get(mnesia_activity_state) of
State = {Mod, Tid, _Ts} when element(1, Tid) =/= tid ->
transaction(State, fun() -> do_clear_table(Tab) end, [], infinity, Mod, sync);
transaction(State, fun() -> do_clear_table(Tab, Pattern) end, [], infinity, Mod, sync);
undefined ->
transaction(undefined, fun() -> do_clear_table(Tab) end, [], infinity, ?DEFAULT_ACCESS, sync);
transaction(undefined, fun() -> do_clear_table(Tab, Pattern) end, [], infinity, ?DEFAULT_ACCESS, sync);
_ -> %% Not allowed for clear_table
mnesia:abort({aborted, nested_transaction})
end.

do_clear_table(Tab) ->
do_clear_table(Tab, Pattern) ->
case get(mnesia_activity_state) of
{?DEFAULT_ACCESS, Tid, Ts} ->
clear_table(Tid, Ts, Tab, '_');
clear_table(Tid, Ts, Tab, Pattern);
{Mod, Tid, Ts} ->
Mod:clear_table(Tid, Ts, Tab, '_');
Mod:clear_table(Tid, Ts, Tab, Pattern);
_ ->
abort(no_transaction)
end.
Expand Down
9 changes: 6 additions & 3 deletions lib/mnesia/src/mnesia_checkpoint.erl
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
tm_prepare/1,
tm_retain/4,
tm_retain/5,
tm_retain/6,
tm_enter_pending/1,
tm_enter_pending/3,
tm_exit_pending/1
Expand Down Expand Up @@ -148,7 +149,6 @@ enter_still_pending([Tid | Tids], Tab) ->
enter_still_pending([], _Tab) ->
ok.


%% Looks up checkpoints for functions in mnesia_tm.
tm_retain(Tid, Tab, Key, Op) ->
case val({Tab, commit_work}) of
Expand All @@ -157,11 +157,14 @@ tm_retain(Tid, Tab, Key, Op) ->
_ ->
undefined
end.

tm_retain(Tid, Tab, Key, Op, Checkpoints) ->
tm_retain(Tid, Tab, Key, Op, Checkpoints, '_').

tm_retain(Tid, Tab, Key, Op, Checkpoints, Obj) ->
case Op of
clear_table ->
OldRecs = mnesia_lib:db_match_object(Tab, '_'),
OldRecs = mnesia_lib:db_match_object(Tab, Obj),
send_group_retain(OldRecs, Checkpoints, Tid, Tab, []),
OldRecs;
_ ->
Expand Down
8 changes: 6 additions & 2 deletions lib/mnesia/src/mnesia_dumper.erl
Original file line number Diff line number Diff line change
Expand Up @@ -404,8 +404,12 @@ dets_insert(Op,Tab,Key,Val, Storage0) ->
dets_updated(Tab,Key),
mnesia_lib:db_match_erase(Storage, Tab, Val);
clear_table ->
dets_cleared(Tab),
ok = mnesia_lib:db_match_erase(Storage, Tab, '_')
%% Val is a match_delete pattern
case Val of
'_' -> dets_cleared(Tab);
_ -> dets_updated(Tab, Val)
end,
ok = mnesia_lib:db_match_erase(Storage, Tab, Val)
end.

dets_updated(Tab,Key) ->
Expand Down
105 changes: 105 additions & 0 deletions lib/mnesia/src/mnesia_hook.erl
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
%%
%% %CopyrightBegin%
%%
%% Copyright Ericsson AB 1996-2021. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
%% You may obtain a copy of the License at
%%
%% http://www.apache.org/licenses/LICENSE-2.0
%%
%% Unless required by applicable law or agreed to in writing, software
%% distributed under the License is distributed on an "AS IS" BASIS,
%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%% See the License for the specific language governing permissions and
%% limitations under the License.
%%
%% %CopyrightEnd%
%%

-module(mnesia_hook).

-include("mnesia.hrl").

-export([
register_hook/2,
unregister_hook/1,
do_post_commit/2
]).

-define(hook(NAME), {mnesia_hook, NAME}).

-type post_commit_hook_data() ::
#{ node => node()
, ram_copies => list()
, disc_copies => list()
, disc_only_copies => list()
, ext => list()
, schema_ops => list()
}.

-type post_commit_hook() :: fun((_Tid, post_commit_hook_data()) -> ok).

-spec register_hook(post_commit, post_commit_hook()) -> ok | {error, term()}.
register_hook(post_commit, Hook) when is_function(Hook, 2) ->
persistent_term:put(?hook(post_commit), Hook);
register_hook(_, _) ->
{error, bad_type}.

-spec unregister_hook(post_commit) -> boolean() | {error, term()}.
unregister_hook(post_commit) ->
persistent_term:erase(?hook(post_commit));
unregister_hook(_) ->
{error, bad_type}.

-spec do_post_commit(_Tid, #commit{}) -> ok.
do_post_commit(Tid, Commit) ->
case persistent_term:get(?hook(post_commit), undefined) of
undefined ->
ok;
Fun ->
#commit{ node = Node
, ram_copies = Ram
, disc_copies = Disc
, disc_only_copies = DiscOnly
, ext = Ext
, schema_ops = SchemaOps
} = Commit,
CommitData = #{ node => Node
, ram_copies => Ram
, disc_copies => Disc
, disc_only_copies => DiscOnly
, ext => Ext
, schema_ops => SchemaOps
},
try Fun(Tid, CommitData)
catch EC:Err:St ->
CommitTabs = commit_tabs(Ram, Disc, DiscOnly, Ext),
mnesia_lib:dbg_out("Mnesia post_commit hook failed: ~p:~p~nStacktrace:~p~nCommit tables:~p~n",
[EC, Err, stack_without_args(St), CommitTabs])
end,
ok
end.

%% May be helpful for debugging
commit_tabs(Ram, Disc, DiscOnly, Ext) ->
Acc = tabs_from_ops(Ram, []),
Acc1 = tabs_from_ops(Disc, Acc),
Acc2 = tabs_from_ops(DiscOnly, Acc1),
lists:uniq(tabs_from_ops(Ext, Acc2)).

tabs_from_ops([{{Tab, _K}, _Val, _Op} | T], Acc) ->
tabs_from_ops(T, [Tab | Acc]);
tabs_from_ops([_ | T], Acc) ->
tabs_from_ops(T, Acc);
tabs_from_ops([], Acc) ->
Acc.

%% Args may contain sensitive data
stack_without_args([{M, F, Args, Info} | T]) when is_list(Args) ->
[{M, F, length(Args), Info} | stack_without_args(T)];
stack_without_args([StItem | T] ) ->
[StItem | stack_without_args(T)];
stack_without_args([]) ->
[].
25 changes: 23 additions & 2 deletions lib/mnesia/src/mnesia_loader.erl
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,19 @@ do_get_network_copy(Tab, _Reason, _Ns, unknown, _Cs) ->
verbose("Local table copy of ~tp has recently been deleted, ignored.~n", [Tab]),
{not_loaded, storage_unknown};
do_get_network_copy(Tab, Reason, Ns, Storage, Cs) ->
[Node | Tail] = Ns,
[Node | Tail] =
case ?catch_val(copy_from_node) of
undefined -> Ns;
CPNode when is_atom(CPNode) ->
case lists:member(CPNode, Ns) of
true ->
[CPNode | Ns -- [CPNode]];
false ->
Ns
end;
_ ->
Ns
end,
case lists:member(Node,val({current, db_nodes})) of
true ->
dbg_out("Getting table ~tp (~p) from node ~p: ~tp~n",
Expand Down Expand Up @@ -917,7 +929,16 @@ get_chunk_func(Pid, Tab, {ext, Alias, Mod}, RemoteS) ->
get_chunk_func(Pid, Tab, Storage, RemoteS) ->
try
TabSize = mnesia:table_info(Tab, size),
KeysPerTransfer = calc_nokeys(Storage, Tab),
KeysPerTransfer =
case ?catch_val(send_table_batch_size) of
{'EXIT', _} ->
mnesia_lib:set(send_table_batch_size, 0),
calc_nokeys(Storage, Tab);
0 ->
calc_nokeys(Storage, Tab);
Val when is_integer(Val) ->
Val
end,
ChunkData = dets:info(Tab, bchunk_format),
UseDetsChunk =
Storage == RemoteS andalso
Expand Down
Loading
Loading