diff options
-rw-r--r-- | src/chttpd/src/chttpd_node.erl | 28 | ||||
-rw-r--r-- | src/couch/priv/couch_ejson_compare/couch_ejson_compare.c | 38 | ||||
-rw-r--r-- | src/couch/src/couch_ejson_compare.erl | 22 | ||||
-rw-r--r-- | src/couch/test/eunit/couch_ejson_compare_tests.erl | 20 |
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), |