nickva commented on code in PR #6050:
URL: https://github.com/apache/couchdb/pull/6050#discussion_r3492651733
##########
src/couch/priv/couch_ejson_compare/couch_ejson_compare.c:
##########
@@ -174,6 +175,81 @@ compare_strings_nif(ErlNifEnv* env, int argc, const
ERL_NIF_TERM argv[])
}
+/*
+ * Return an ICU collation sort key as an Erlang binary. Two keys that collate
+ * equally produce identical sort keys. Sort keys can be used to keep a bunch
+ * of ICU key-value pairs in collation order (in a sorted KV data structure for
+ * example) and minimize the times ICU pair-wise comparison function would be
+ * called when keeping that data structure sorted. The only caveat is not to
+ * compare sort keys generated by different major versions of libicu, so use
+ * them on the same node in memory and don't store them on disk.
+ */
+ERL_NIF_TERM
+get_sort_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{
+ ErlNifBinary bin;
+ UCollator* coll;
+ UErrorCode status = U_ZERO_ERROR;
+ UCharIterator iter;
+ /* Part of libicu "Between calls to the API you need to save a 64-bit
state"
+ * see https://unicode-org.github.io/icu/userguide/collation/api.html */
+ uint32_t state[2] = {0, 0};
+ /* This our stack cache */
+ uint8_t keystack[256];
+ uint8_t* key = keystack;
+ int32_t keycap = (int32_t) sizeof(keystack);
+ int32_t keylen = 0;
+ unsigned char* out;
+ ERL_NIF_TERM result;
+
+ if (!enif_inspect_binary(env, argv[0], &bin)) {
+ return enif_make_badarg(env);
+ }
+
+ coll = get_collator();
+ if (coll == NULL) {
+ return enif_make_badarg(env);
+ }
+
+ uiter_setUTF8(&iter, (const char*) bin.data, (uint32_t) bin.size);
+
+ /* At first use a short 256 stack cache to fill the key in. If that gets
+ * too small start allocating memory. If we get less than our buffer size
+ * it means we're done. */
+ for (;;) {
+ int32_t want = keycap - keylen;
+ int32_t got = ucol_nextSortKeyPart(coll, &iter, state, key + keylen,
want, &status);
+ if (U_FAILURE(status)) {
+ if (key != keystack) {
+ enif_free(key);
+ }
+ return enif_make_badarg(env);
+ }
+ keylen += got;
+ if (got < want) {
+ break;
+ }
+ int32_t newcap = keycap * 2;
Review Comment:
Good idea. Trying to pick a value, and remembered we've had to bump memory
limits on couch_js executables due to some large rows / ddocs. The highest I've
seen in production was 128Mb of total heap size so maybe we can make that the
limit.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]