diff options
author | Nick Vatamaniuc <vatamane@apache.org> | 2021-10-24 02:33:43 -0400 |
---|---|---|
committer | Nick Vatamaniuc <nickva@users.noreply.github.com> | 2021-10-24 14:51:17 -0400 |
commit | c1bb4e4856edd93255d75ebe158b4da38bbf3333 (patch) | |
tree | e0363657db5015b572c9e3f999101f2902dcb9e5 | |
parent | bdde402a146788b7a43837311cb8208c92baeb43 (diff) | |
download | couchdb-c1bb4e4856edd93255d75ebe158b4da38bbf3333.tar.gz |
Add libicu version fetching and emit it in the _node/_local/_versions
Fetch the libicu base version as well as the collator version. The
base version may be used to determine which libicu library CouchDB is
using. The collator version may be used to debug view behavior in case
when collation order had changed from one version ot the next.
-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), |