mirror of
https://github.com/isar/libmdbx.git
synced 2024-12-30 01:54:13 +08:00
mdbx: move key generator linearization into actor::review_params()
.
Change-Id: I35492f64b6b5eae9702d26f3e0ba9df31f57a4af
This commit is contained in:
parent
f4781b63a8
commit
ecc755881e
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user