mirror of
https://github.com/isar/libmdbx.git
synced 2025-01-02 00:14:14 +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;
|
bool run() override;
|
||||||
|
|
||||||
static bool review_params(actor_params ¶ms) {
|
static bool review_params(actor_params ¶ms) {
|
||||||
return testcase::review_params(params);
|
return testcase::review_params(params) && params.make_keygen_linear();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
REGISTER_TESTCASE(append);
|
REGISTER_TESTCASE(append);
|
||||||
@ -41,7 +41,6 @@ bool testcase_append::run() {
|
|||||||
(config.params.table_flags & MDBX_DUPSORT)
|
(config.params.table_flags & MDBX_DUPSORT)
|
||||||
? (flipcoin() ? MDBX_APPEND | MDBX_APPENDDUP : MDBX_APPENDDUP)
|
? (flipcoin() ? MDBX_APPEND | MDBX_APPENDDUP : MDBX_APPENDDUP)
|
||||||
: MDBX_APPEND;
|
: MDBX_APPEND;
|
||||||
keyvalue_maker.make_linear();
|
|
||||||
|
|
||||||
key = keygen::alloc(config.params.keylen_max);
|
key = keygen::alloc(config.params.keylen_max);
|
||||||
data = keygen::alloc(config.params.datalen_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),
|
return std::min(unsigned(UINT16_MAX),
|
||||||
unsigned(mdbx_limits_valsize_max(pagesize, table_flags)));
|
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 ignore_dbfull{false};
|
||||||
bool speculum{false};
|
bool speculum{false};
|
||||||
bool random_writemap{true};
|
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 {
|
struct actor_config_pod {
|
||||||
@ -312,6 +321,7 @@ struct actor_params : public config::actor_params_pod {
|
|||||||
actor_params() = default;
|
actor_params() = default;
|
||||||
|
|
||||||
void set_defaults(const std::string &tmpdir);
|
void set_defaults(const std::string &tmpdir);
|
||||||
|
bool make_keygen_linear();
|
||||||
unsigned mdbx_keylen_min() const;
|
unsigned mdbx_keylen_min() const;
|
||||||
unsigned mdbx_keylen_max() const;
|
unsigned mdbx_keylen_max() const;
|
||||||
unsigned mdbx_datalen_min() const;
|
unsigned mdbx_datalen_min() const;
|
||||||
|
@ -16,11 +16,6 @@
|
|||||||
|
|
||||||
namespace keygen {
|
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 */
|
/* LY: https://en.wikipedia.org/wiki/Injective_function */
|
||||||
serial_t injective(const serial_t serial,
|
serial_t injective(const serial_t serial,
|
||||||
const unsigned bits /* at least serial_minwith (8) */,
|
const unsigned bits /* at least serial_minwith (8) */,
|
||||||
@ -59,12 +54,13 @@ serial_t injective(const serial_t serial,
|
|||||||
if (salt) {
|
if (salt) {
|
||||||
const unsigned left = bits / 2;
|
const unsigned left = bits / 2;
|
||||||
const unsigned right = bits - left;
|
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 ^ salt) * mult;
|
||||||
}
|
}
|
||||||
|
|
||||||
result ^= result << shift;
|
result ^= result << shift;
|
||||||
result &= mask(bits);
|
result &= actor_params::serial_mask(bits);
|
||||||
log_trace("keygen-injective: serial %" PRIu64 "/%u @%" PRIx64 ",%u,%" PRIu64
|
log_trace("keygen-injective: serial %" PRIu64 "/%u @%" PRIx64 ",%u,%" PRIu64
|
||||||
" => %" PRIu64 "/%u",
|
" => %" PRIu64 "/%u",
|
||||||
serial, bits, mult, shift, salt, result, bits);
|
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.split <= mapping.width);
|
||||||
assert(mapping.mesh <= mapping.width);
|
assert(mapping.mesh <= mapping.width);
|
||||||
assert(mapping.rotate <= 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 &
|
assert(!(key_essentials.flags &
|
||||||
~(essentials::prng_fill_flag |
|
~(essentials::prng_fill_flag |
|
||||||
unsigned(MDBX_INTEGERKEY | MDBX_REVERSEKEY | MDBX_DUPSORT))));
|
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);
|
value_age);
|
||||||
|
|
||||||
if (mapping.mesh >= serial_minwith) {
|
if (mapping.mesh >= serial_minwith) {
|
||||||
serial =
|
serial = (serial & ~actor_params::serial_mask(mapping.mesh)) |
|
||||||
(serial & ~mask(mapping.mesh)) | injective(serial, mapping.mesh, salt);
|
injective(serial, mapping.mesh, salt);
|
||||||
log_trace("keygen-pair: mesh@%u => %" PRIu64, mapping.mesh, serial);
|
log_trace("keygen-pair: mesh@%u => %" PRIu64, mapping.mesh, serial);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mapping.rotate) {
|
if (mapping.rotate) {
|
||||||
const unsigned right = mapping.rotate;
|
const unsigned right = mapping.rotate;
|
||||||
const unsigned left = mapping.width - right;
|
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,
|
log_trace("keygen-pair: rotate@%u => %" PRIu64 ", 0x%" PRIx64,
|
||||||
mapping.rotate, serial, serial);
|
mapping.rotate, serial, serial);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mapping.offset) {
|
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,
|
log_trace("keygen-pair: offset@%" PRIu64 " => %" PRIu64, mapping.offset,
|
||||||
serial);
|
serial);
|
||||||
}
|
}
|
||||||
@ -117,7 +115,7 @@ void __hot maker::pair(serial_t serial, const buffer &key, buffer &value,
|
|||||||
if (mapping.split) {
|
if (mapping.split) {
|
||||||
if (MDBX_db_flags_t(key_essentials.flags) & MDBX_DUPSORT) {
|
if (MDBX_db_flags_t(key_essentials.flags) & MDBX_DUPSORT) {
|
||||||
key_serial >>= mapping.split;
|
key_serial >>= mapping.split;
|
||||||
value_serial += serial & mask(mapping.split);
|
value_serial += serial & actor_params::serial_mask(mapping.split);
|
||||||
} else {
|
} else {
|
||||||
/* Без MDBX_DUPSORT требуется уникальность ключей, а для этого нельзя
|
/* Без MDBX_DUPSORT требуется уникальность ключей, а для этого нельзя
|
||||||
* отбрасывать какие-либо биты serial после инъективного преобразования.
|
* отбрасывать какие-либо биты serial после инъективного преобразования.
|
||||||
@ -125,7 +123,7 @@ void __hot maker::pair(serial_t serial, const buffer &key, buffer &value,
|
|||||||
* запрошенное количество бит из serial */
|
* запрошенное количество бит из serial */
|
||||||
value_serial +=
|
value_serial +=
|
||||||
(serial ^ (serial >> mapping.split) * UINT64_C(57035339200100753)) &
|
(serial ^ (serial >> mapping.split) * UINT64_C(57035339200100753)) &
|
||||||
mask(mapping.split);
|
actor_params::serial_mask(mapping.split);
|
||||||
}
|
}
|
||||||
|
|
||||||
value_serial |= value_age << 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;
|
mapping = actor.keygen;
|
||||||
salt = (actor.keygen.seed + actor_id) * UINT64_C(14653293970879851569);
|
salt = (actor.keygen.seed + actor_id) * UINT64_C(14653293970879851569);
|
||||||
|
|
||||||
// FIXME: TODO
|
base = actor.serial_base();
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool maker::is_unordered() const {
|
bool maker::is_unordered() const {
|
||||||
@ -284,14 +240,14 @@ bool maker::is_unordered() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool maker::increment(serial_t &serial, int delta) 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,
|
log_extra("keygen-increment: %" PRIu64 " > %" PRIu64 ", overflow", serial,
|
||||||
mask(mapping.width));
|
actor_params::serial_mask(mapping.width));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
serial_t target = serial + (int64_t)delta;
|
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)) {
|
((delta > 0) ? target < serial : target > serial)) {
|
||||||
log_extra("keygen-increment: %" PRIu64 "%-d => %" PRIu64 ", overflow",
|
log_extra("keygen-increment: %" PRIu64 "%-d => %" PRIu64 ", overflow",
|
||||||
serial, delta, target);
|
serial, delta, target);
|
||||||
|
@ -127,7 +127,6 @@ public:
|
|||||||
serial_t value_age, const bool keylen_changeable);
|
serial_t value_age, const bool keylen_changeable);
|
||||||
void setup(const config::actor_params_pod &actor, unsigned actor_id,
|
void setup(const config::actor_params_pod &actor, unsigned actor_id,
|
||||||
unsigned thread_number);
|
unsigned thread_number);
|
||||||
void make_linear();
|
|
||||||
bool is_unordered() const;
|
bool is_unordered() const;
|
||||||
|
|
||||||
bool increment(serial_t &serial, int delta) const;
|
bool increment(serial_t &serial, int delta) const;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user