summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/chttpd/src/chttpd_node.erl28
-rw-r--r--src/couch/priv/couch_ejson_compare/couch_ejson_compare.c38
-rw-r--r--src/couch/src/couch_ejson_compare.erl22
-rw-r--r--src/couch/test/eunit/couch_ejson_compare_tests.erl20
4 files changed, 98 insertions, 10 deletions
diff --git a/src/chttpd/src/chttpd_node.erl b/src/chttpd/src/chttpd_node.erl
index 7486aadfe..e92a1e506 100644
--- a/src/chttpd/src/chttpd_node.erl
+++ b/src/chttpd/src/chttpd_node.erl
@@ -33,13 +33,20 @@ handle_node_req(#httpd{path_parts=[A, <<"_local">>|Rest]}=Req) ->
handle_node_req(Req#httpd{path_parts=[A, node()] ++ Rest});
% GET /_node/$node/_versions
handle_node_req(#httpd{method='GET', path_parts=[_, _Node, <<"_versions">>]}=Req) ->
- send_json(Req, 200, {[
- {erlang_version, ?l2b(?COUCHDB_ERLANG_VERSION)},
- {javascript_engine, {[
- {name, <<"spidermonkey">>},
- {version, couch_server:get_spidermonkey_version()}
- ]}}
- ]});
+ IcuVer = couch_ejson_compare:get_icu_version(),
+ UcaVer = couch_ejson_compare:get_uca_version(),
+ send_json(Req, 200, #{
+ erlang_version => ?l2b(?COUCHDB_ERLANG_VERSION),
+ collation_driver => #{
+ name => <<"libicu">>,
+ library_version => version_tuple_to_str(IcuVer),
+ collation_algorithm_version => version_tuple_to_str(UcaVer)
+ },
+ javascript_engine => #{
+ name => <<"spidermonkey">>,
+ version => couch_server:get_spidermonkey_version()
+ }
+ });
handle_node_req(#httpd{path_parts=[_, _Node, <<"_versions">>]}=Req) ->
send_method_not_allowed(Req, "GET");
@@ -322,3 +329,10 @@ run_queues() ->
[DCQ | SQs] = lists:reverse(statistics(run_queue_lengths)),
{lists:sum(SQs), DCQ}
end.
+
+version_tuple_to_str(Version) when is_tuple(Version) ->
+ List1 = tuple_to_list(Version),
+ IsZero = fun(N) -> N == 0 end,
+ List2 = lists:reverse(lists:dropwhile(IsZero, lists:reverse(List1))),
+ List3 = [erlang:integer_to_list(N) || N <- List2],
+ ?l2b(lists:join(".", List3)).
diff --git a/src/couch/priv/couch_ejson_compare/couch_ejson_compare.c b/src/couch/priv/couch_ejson_compare/couch_ejson_compare.c
index f453a295f..6e200320d 100644
--- a/src/couch/priv/couch_ejson_compare/couch_ejson_compare.c
+++ b/src/couch/priv/couch_ejson_compare/couch_ejson_compare.c
@@ -166,6 +166,40 @@ compare_strings_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
}
+ERL_NIF_TERM
+get_icu_version(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{
+ UVersionInfo ver = {0};
+ ERL_NIF_TERM tup[U_MAX_VERSION_LENGTH] = {0};
+ int i;
+
+ u_getVersion(ver);
+
+ for (i = 0; i < U_MAX_VERSION_LENGTH; i++) {
+ tup[i] = enif_make_int(env, ver[i]);
+ }
+
+ return enif_make_tuple_from_array(env, tup, U_MAX_VERSION_LENGTH);
+}
+
+
+ERL_NIF_TERM
+get_uca_version(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{
+ UVersionInfo ver = {0};
+ ERL_NIF_TERM tup[U_MAX_VERSION_LENGTH] = {0};
+ int i;
+
+ ucol_getUCAVersion(get_collator(), ver);
+
+ for (i = 0; i < U_MAX_VERSION_LENGTH; i++) {
+ tup[i] = enif_make_int(env, ver[i]);
+ }
+
+ return enif_make_tuple_from_array(env, tup, U_MAX_VERSION_LENGTH);
+}
+
+
int
less_json(int depth, ctx_t* ctx, ERL_NIF_TERM a, ERL_NIF_TERM b)
{
@@ -531,7 +565,9 @@ on_unload(ErlNifEnv* env, void* priv_data)
static ErlNifFunc nif_functions[] = {
{"less_nif", 2, less_json_nif},
- {"compare_strings_nif", 2, compare_strings_nif}
+ {"compare_strings_nif", 2, compare_strings_nif},
+ {"get_icu_version", 0, get_icu_version},
+ {"get_uca_version", 0, get_uca_version}
};
diff --git a/src/couch/src/couch_ejson_compare.erl b/src/couch/src/couch_ejson_compare.erl
index 8681296f1..b02b9ba7c 100644
--- a/src/couch/src/couch_ejson_compare.erl
+++ b/src/couch/src/couch_ejson_compare.erl
@@ -12,10 +12,20 @@
-module(couch_ejson_compare).
--export([less/2, less_json_ids/2, less_json/2]).
+-export([
+ less/2,
+ less_json_ids/2,
+ less_json/2,
+ get_icu_version/0,
+ get_uca_version/0
+]).
% For testing
--export([less_nif/2, less_erl/2, compare_strings_nif/2]).
+-export([
+ less_nif/2,
+ less_erl/2,
+ compare_strings_nif/2
+]).
-on_load(init/0).
@@ -51,6 +61,14 @@ less_json(A,B) ->
less(A, B) < 0.
+get_icu_version() ->
+ erlang:nif_error(get_icu_version).
+
+
+get_uca_version() ->
+ erlang:nif_error(get_uca_version).
+
+
less_nif(A, B) ->
erlang:nif_error(less_nif_load_error, [A, B]).
diff --git a/src/couch/test/eunit/couch_ejson_compare_tests.erl b/src/couch/test/eunit/couch_ejson_compare_tests.erl
index 790f6e54c..1dfbad4ed 100644
--- a/src/couch/test/eunit/couch_ejson_compare_tests.erl
+++ b/src/couch/test/eunit/couch_ejson_compare_tests.erl
@@ -183,6 +183,26 @@ zero_width_chars() ->
% Regular EUnit tests
+get_icu_version_test() ->
+ Ver = couch_ejson_compare:get_icu_version(),
+ ?assertMatch({_, _, _, _}, Ver),
+ {V1, V2, V3, V4} = Ver,
+ ?assert(is_integer(V1) andalso V1 > 0),
+ ?assert(is_integer(V2) andalso V2 >= 0),
+ ?assert(is_integer(V3) andalso V3 >= 0),
+ ?assert(is_integer(V4) andalso V4 >= 0).
+
+
+get_uca_version_test() ->
+ Ver = couch_ejson_compare:get_uca_version(),
+ ?assertMatch({_, _, _, _}, Ver),
+ {V1, V2, V3, V4} = Ver,
+ ?assert(is_integer(V1) andalso V1 > 0),
+ ?assert(is_integer(V2) andalso V2 >= 0),
+ ?assert(is_integer(V3) andalso V3 >= 0),
+ ?assert(is_integer(V4) andalso V4 >= 0).
+
+
max_depth_error_list_test() ->
% NIF can handle terms with depth <= 9
Nested9 = nest_list(<<"val">>, 9),