summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Newson <rnewson@apache.org>2023-04-25 09:38:00 +0100
committerRobert Newson <rnewson@apache.org>2023-04-27 10:32:15 +0100
commit57fc9047a3b5375884c963cbddd6470cbe6319dd (patch)
tree9681de6dca6f2c994a473eb0713a7799a507cd04
parent3ea049d643db534071fab4f576c39d34f2f856c6 (diff)
downloadcouchdb-57fc9047a3b5375884c963cbddd6470cbe6319dd.tar.gz
OTP 23 support
-rw-r--r--src/nouveau/src/nouveau_fabric_info.erl2
-rw-r--r--src/nouveau/src/nouveau_fabric_search.erl4
-rw-r--r--src/nouveau/src/nouveau_httpd.erl2
-rw-r--r--src/nouveau/src/nouveau_maps.erl121
4 files changed, 125 insertions, 4 deletions
diff --git a/src/nouveau/src/nouveau_fabric_info.erl b/src/nouveau/src/nouveau_fabric_info.erl
index 59e47094f..b5f928075 100644
--- a/src/nouveau/src/nouveau_fabric_info.erl
+++ b/src/nouveau/src/nouveau_fabric_info.erl
@@ -70,7 +70,7 @@ handle_message({ok, Info}, Worker, {Counters, Acc0}) ->
nil ->
C1 = fabric_dict:store(Worker, ok, Counters),
C2 = fabric_view:remove_overlapping_shards(Worker, C1),
- Acc1 = maps:merge_with(fun merge_info/3, Info, Acc0),
+ Acc1 = nouveau_maps:merge_with(fun merge_info/3, Info, Acc0),
case fabric_dict:any(nil, C2) of
true ->
{ok, {C2, Acc1}};
diff --git a/src/nouveau/src/nouveau_fabric_search.erl b/src/nouveau/src/nouveau_fabric_search.erl
index 4e528cc93..ca101ba9c 100644
--- a/src/nouveau/src/nouveau_fabric_search.erl
+++ b/src/nouveau/src/nouveau_fabric_search.erl
@@ -217,5 +217,5 @@ merge_facets(FacetsA, null, _Limit) ->
merge_facets(null, FacetsB, _Limit) ->
FacetsB;
merge_facets(FacetsA, FacetsB, _Limit) ->
- Combiner = fun(_, V1, V2) -> maps:merge_with(fun(_, V3, V4) -> V3 + V4 end, V1, V2) end,
- maps:merge_with(Combiner, FacetsA, FacetsB).
+ Combiner = fun(_, V1, V2) -> nouveau_maps:merge_with(fun(_, V3, V4) -> V3 + V4 end, V1, V2) end,
+ nouveau_maps:merge_with(Combiner, FacetsA, FacetsB).
diff --git a/src/nouveau/src/nouveau_httpd.erl b/src/nouveau/src/nouveau_httpd.erl
index 999acc7ea..8d27048a1 100644
--- a/src/nouveau/src/nouveau_httpd.erl
+++ b/src/nouveau/src/nouveau_httpd.erl
@@ -200,7 +200,7 @@ validate_query_arg(sort, Sort) ->
validate_query_arg(ranges, undefined) ->
null;
validate_query_arg(ranges, {json, Ranges}) when is_map(Ranges) ->
- maps:foreach(fun is_valid_range/2, Ranges),
+ nouveau_maps:foreach(fun is_valid_range/2, Ranges),
Ranges;
validate_query_arg(ranges, Ranges) ->
validate_query_arg(ranges, {json, ?JSON_DECODE(Ranges, [return_maps])});
diff --git a/src/nouveau/src/nouveau_maps.erl b/src/nouveau/src/nouveau_maps.erl
new file mode 100644
index 000000000..81a145557
--- /dev/null
+++ b/src/nouveau/src/nouveau_maps.erl
@@ -0,0 +1,121 @@
+%%
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2013-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%
+%%
+
+%% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*-
+
+%% backport of OTP 24 map functions not present in 23.
+
+-module(nouveau_maps).
+
+-export([merge_with/3, foreach/2]).
+
+-if(?OTP_RELEASE >= 24).
+merge_with(Combiner, Map1, Map2) ->
+ maps:merge_with(Combiner, Map1, Map2).
+
+foreach(Fun, MapOrIter) ->
+ maps:foreach(Fun, MapOrIter).
+
+-else.
+
+merge_with(Combiner, Map1, Map2) when
+ is_map(Map1),
+ is_map(Map2),
+ is_function(Combiner, 3)
+->
+ case map_size(Map1) > map_size(Map2) of
+ true ->
+ Iterator = maps:iterator(Map2),
+ merge_with_1(
+ maps:next(Iterator),
+ Map1,
+ Map2,
+ Combiner
+ );
+ false ->
+ Iterator = maps:iterator(Map1),
+ merge_with_1(
+ maps:next(Iterator),
+ Map2,
+ Map1,
+ fun(K, V1, V2) -> Combiner(K, V2, V1) end
+ )
+ end;
+merge_with(Combiner, Map1, Map2) ->
+ error_with_info(
+ error_type_merge_intersect(Map1, Map2, Combiner),
+ [Combiner, Map1, Map2]
+ ).
+
+merge_with_1({K, V2, Iterator}, Map1, Map2, Combiner) ->
+ case Map1 of
+ #{K := V1} ->
+ NewMap1 = Map1#{K := Combiner(K, V1, V2)},
+ merge_with_1(maps:next(Iterator), NewMap1, Map2, Combiner);
+ #{} ->
+ merge_with_1(maps:next(Iterator), maps:put(K, V2, Map1), Map2, Combiner)
+ end;
+merge_with_1(none, Result, _, _) ->
+ Result.
+
+foreach(Fun, MapOrIter) when is_function(Fun, 2) ->
+ Iter =
+ if
+ is_map(MapOrIter) -> maps:iterator(MapOrIter);
+ true -> MapOrIter
+ end,
+ try maps:next(Iter) of
+ Next ->
+ foreach_1(Fun, Next)
+ catch
+ error:_ ->
+ error_with_info({badmap, MapOrIter}, [Fun, MapOrIter])
+ end;
+foreach(Pred, Map) ->
+ badarg_with_info([Pred, Map]).
+
+foreach_1(Fun, {K, V, Iter}) ->
+ Fun(K, V),
+ foreach_1(Fun, maps:next(Iter));
+foreach_1(_Fun, none) ->
+ ok.
+
+%% We must inline these functions so that the stacktrace points to
+%% the correct function.
+-compile({inline, [badarg_with_info/1, error_with_info/2]}).
+
+badarg_with_info(Args) ->
+ erlang:error(badarg, Args, [{error_info, #{module => erl_stdlib_errors}}]).
+
+error_with_info(Reason, Args) ->
+ erlang:error(Reason, Args, [{error_info, #{module => erl_stdlib_errors}}]).
+
+error_type_two_maps(M1, M2) when is_map(M1) ->
+ {badmap, M2};
+error_type_two_maps(M1, _M2) ->
+ {badmap, M1}.
+
+error_type_merge_intersect(M1, M2, Combiner) when is_function(Combiner, 3) ->
+ error_type_two_maps(M1, M2);
+error_type_merge_intersect(_M1, _M2, _Combiner) ->
+ badarg.
+
+-endif.