diff --git a/test/append.cc b/test/append.cc index 495d4be1..7d8aa309 100644 --- a/test/append.cc +++ b/test/append.cc @@ -21,7 +21,7 @@ public: bool run() override; static bool review_params(actor_params ¶ms) { - return testcase::review_params(params); + return testcase::review_params(params) && params.make_keygen_linear(); } }; REGISTER_TESTCASE(append); @@ -41,7 +41,6 @@ bool testcase_append::run() { (config.params.table_flags & MDBX_DUPSORT) ? (flipcoin() ? MDBX_APPEND | MDBX_APPENDDUP : MDBX_APPENDDUP) : MDBX_APPEND; - keyvalue_maker.make_linear(); key = keygen::alloc(config.params.keylen_max); data = keygen::alloc(config.params.datalen_max); diff --git a/test/config.cc b/test/config.cc index cfc6b2c1..3708f7f8 100644 --- a/test/config.cc +++ b/test/config.cc @@ -623,3 +623,36 @@ unsigned actor_params::mdbx_datalen_max() const { return std::min(unsigned(UINT16_MAX), unsigned(mdbx_limits_valsize_max(pagesize, table_flags))); } + +bool actor_params::make_keygen_linear() { + const auto base = serial_base(); + keygen.mesh = (table_flags & MDBX_DUPSORT) ? 0 : keygen.split; + keygen.rotate = 0; + keygen.offset = 0; + const auto max_serial = serial_mask(keygen.width) + base; + const auto max_key_serial = (keygen.split && (table_flags & MDBX_DUPSORT)) + ? max_serial >> keygen.split + : max_serial; + const auto max_value_serial = (keygen.split && (table_flags & MDBX_DUPSORT)) + ? serial_mask(keygen.split) + : 0; + + while (keylen_min < 8 && + (keylen_min == 0 || serial_mask(keylen_min * 8) < max_key_serial)) { + keylen_min += (table_flags & (MDBX_INTEGERKEY | MDBX_INTEGERDUP)) ? 4 : 1; + if (keylen_max < keylen_min) + keylen_max = keylen_min; + } + + if (table_flags & MDBX_DUPSORT) + while ( + datalen_min < 8 && + (datalen_min == 0 || serial_mask(datalen_min * 8) < max_value_serial)) { + datalen_min += + (table_flags & (MDBX_INTEGERKEY | MDBX_INTEGERDUP)) ? 4 : 1; + if (datalen_max < datalen_min) + datalen_max = datalen_min; + } + + return true; +} diff --git a/test/config.h b/test/config.h index db7b7546..f8ee52dc 100644 --- a/test/config.h +++ b/test/config.h @@ -283,6 +283,15 @@ struct actor_params_pod { bool ignore_dbfull{false}; bool speculum{false}; bool random_writemap{true}; + + uint64_t serial_base() const { + // FIXME: TODO + return 0; + } + static MDBX_PURE_FUNCTION uint64_t serial_mask(unsigned bits) { + assert(bits > 0 && bits <= 64); + return (~(uint64_t)0u) >> (64 - bits); + } }; struct actor_config_pod { @@ -312,6 +321,7 @@ struct actor_params : public config::actor_params_pod { actor_params() = default; void set_defaults(const std::string &tmpdir); + bool make_keygen_linear(); unsigned mdbx_keylen_min() const; unsigned mdbx_keylen_max() const; unsigned mdbx_datalen_min() const; diff --git a/test/keygen.cc b/test/keygen.cc index f5436feb..dd2ecff3 100644 --- a/test/keygen.cc +++ b/test/keygen.cc @@ -16,11 +16,6 @@ namespace keygen { -static inline MDBX_PURE_FUNCTION serial_t mask(unsigned bits) { - assert(bits > 0 && bits <= serial_maxwith); - return serial_allones >> (serial_maxwith - bits); -} - /* LY: https://en.wikipedia.org/wiki/Injective_function */ serial_t injective(const serial_t serial, const unsigned bits /* at least serial_minwith (8) */, @@ -59,12 +54,13 @@ serial_t injective(const serial_t serial, if (salt) { const unsigned left = bits / 2; const unsigned right = bits - left; - result = (result << left) | ((result & mask(bits)) >> right); + result = (result << left) | + ((result & actor_params::serial_mask(bits)) >> right); result = (result ^ salt) * mult; } result ^= result << shift; - result &= mask(bits); + result &= actor_params::serial_mask(bits); log_trace("keygen-injective: serial %" PRIu64 "/%u @%" PRIx64 ",%u,%" PRIu64 " => %" PRIu64 "/%u", serial, bits, mult, shift, salt, result, bits); @@ -77,7 +73,7 @@ void __hot maker::pair(serial_t serial, const buffer &key, buffer &value, assert(mapping.split <= mapping.width); assert(mapping.mesh <= mapping.width); assert(mapping.rotate <= mapping.width); - assert(mapping.offset <= mask(mapping.width)); + assert(mapping.offset <= actor_params::serial_mask(mapping.width)); assert(!(key_essentials.flags & ~(essentials::prng_fill_flag | unsigned(MDBX_INTEGERKEY | MDBX_REVERSEKEY | MDBX_DUPSORT)))); @@ -89,21 +85,23 @@ void __hot maker::pair(serial_t serial, const buffer &key, buffer &value, value_age); if (mapping.mesh >= serial_minwith) { - serial = - (serial & ~mask(mapping.mesh)) | injective(serial, mapping.mesh, salt); + serial = (serial & ~actor_params::serial_mask(mapping.mesh)) | + injective(serial, mapping.mesh, salt); log_trace("keygen-pair: mesh@%u => %" PRIu64, mapping.mesh, serial); } if (mapping.rotate) { const unsigned right = mapping.rotate; const unsigned left = mapping.width - right; - serial = (serial << left) | ((serial & mask(mapping.width)) >> right); + serial = (serial << left) | + ((serial & actor_params::serial_mask(mapping.width)) >> right); log_trace("keygen-pair: rotate@%u => %" PRIu64 ", 0x%" PRIx64, mapping.rotate, serial, serial); } if (mapping.offset) { - serial = (serial + mapping.offset) & mask(mapping.width); + serial = + (serial + mapping.offset) & actor_params::serial_mask(mapping.width); log_trace("keygen-pair: offset@%" PRIu64 " => %" PRIu64, mapping.offset, serial); } @@ -117,7 +115,7 @@ void __hot maker::pair(serial_t serial, const buffer &key, buffer &value, if (mapping.split) { if (MDBX_db_flags_t(key_essentials.flags) & MDBX_DUPSORT) { key_serial >>= mapping.split; - value_serial += serial & mask(mapping.split); + value_serial += serial & actor_params::serial_mask(mapping.split); } else { /* Без MDBX_DUPSORT требуется уникальность ключей, а для этого нельзя * отбрасывать какие-либо биты serial после инъективного преобразования. @@ -125,7 +123,7 @@ void __hot maker::pair(serial_t serial, const buffer &key, buffer &value, * запрошенное количество бит из serial */ value_serial += (serial ^ (serial >> mapping.split) * UINT64_C(57035339200100753)) & - mask(mapping.split); + actor_params::serial_mask(mapping.split); } value_serial |= value_age << mapping.split; @@ -231,49 +229,7 @@ void maker::setup(const config::actor_params_pod &actor, unsigned actor_id, mapping = actor.keygen; salt = (actor.keygen.seed + actor_id) * UINT64_C(14653293970879851569); - // FIXME: TODO - base = 0; -} - -void maker::make_linear() { - mapping.mesh = (MDBX_db_flags_t(key_essentials.flags) & MDBX_DUPSORT) - ? 0 - : mapping.split; - mapping.rotate = 0; - mapping.offset = 0; - const auto max_serial = mask(mapping.width) + base; - const auto max_key_serial = - (mapping.split && (MDBX_db_flags_t(key_essentials.flags) & MDBX_DUPSORT)) - ? max_serial >> mapping.split - : max_serial; - const auto max_value_serial = - (mapping.split && (MDBX_db_flags_t(key_essentials.flags) & MDBX_DUPSORT)) - ? mask(mapping.split) - : 0; - - while (key_essentials.minlen < 8 && - (key_essentials.minlen == 0 || - mask(key_essentials.minlen * 8) < max_key_serial)) { - key_essentials.minlen += (MDBX_db_flags_t(key_essentials.flags) & - (MDBX_INTEGERKEY | MDBX_INTEGERDUP)) - ? 4 - : 1; - if (key_essentials.maxlen < key_essentials.minlen) - key_essentials.maxlen = key_essentials.minlen; - } - - if (MDBX_db_flags_t(key_essentials.flags | value_essentials.flags) & - MDBX_DUPSORT) - while (value_essentials.minlen < 8 && - (value_essentials.minlen == 0 || - mask(value_essentials.minlen * 8) < max_value_serial)) { - value_essentials.minlen += (MDBX_db_flags_t(value_essentials.flags) & - (MDBX_INTEGERKEY | MDBX_INTEGERDUP)) - ? 4 - : 1; - if (value_essentials.maxlen < value_essentials.minlen) - value_essentials.maxlen = value_essentials.minlen; - } + base = actor.serial_base(); } bool maker::is_unordered() const { @@ -284,14 +240,14 @@ bool maker::is_unordered() const { } bool maker::increment(serial_t &serial, int delta) const { - if (serial > mask(mapping.width)) { + if (serial > actor_params::serial_mask(mapping.width)) { log_extra("keygen-increment: %" PRIu64 " > %" PRIu64 ", overflow", serial, - mask(mapping.width)); + actor_params::serial_mask(mapping.width)); return false; } serial_t target = serial + (int64_t)delta; - if (target > mask(mapping.width) || + if (target > actor_params::serial_mask(mapping.width) || ((delta > 0) ? target < serial : target > serial)) { log_extra("keygen-increment: %" PRIu64 "%-d => %" PRIu64 ", overflow", serial, delta, target); diff --git a/test/keygen.h b/test/keygen.h index 39d2f7a7..c256150c 100644 --- a/test/keygen.h +++ b/test/keygen.h @@ -127,7 +127,6 @@ public: serial_t value_age, const bool keylen_changeable); void setup(const config::actor_params_pod &actor, unsigned actor_id, unsigned thread_number); - void make_linear(); bool is_unordered() const; bool increment(serial_t &serial, int delta) const;