mdbx-test: доработка after-fork сценариев с устранением логической ошибки.

This commit is contained in:
Леонид Юрьев (Leonid Yuriev) 2024-02-21 01:28:51 +03:00
parent f0cfedc26f
commit ba719ef12a
2 changed files with 86 additions and 12 deletions

View File

@ -22,13 +22,58 @@
class testcase_smoke4fork : public testcase { class testcase_smoke4fork : public testcase {
using inherited = testcase; using inherited = testcase;
protected:
bool dbi_invalid{true};
bool dbi_stable{false};
unsigned dbi_state{0};
public: public:
testcase_smoke4fork(const actor_config &config, const mdbx_pid_t pid) testcase_smoke4fork(const actor_config &config, const mdbx_pid_t pid)
: testcase(config, pid) {} : testcase(config, pid) {}
virtual void txn_end(bool abort) override;
bool run() override; bool run() override;
virtual bool smoke() = 0; virtual bool smoke() = 0;
bool open_dbi();
}; };
bool testcase_smoke4fork::open_dbi() {
if (!dbi || dbi_invalid) {
if (dbi_stable ||
(mdbx_txn_flags(txn_guard.get()) & int(MDBX_TXN_RDONLY)) == 0) {
dbi = db_table_open(!dbi_stable);
dbi_invalid = false;
}
}
dbi_state = 0;
if (dbi && !dbi_invalid) {
unsigned unused_dbi_flags;
int err =
mdbx_dbi_flags_ex(txn_guard.get(), dbi, &unused_dbi_flags, &dbi_state);
if (unlikely(err != MDBX_SUCCESS))
failure_perror("mdbx_dbi_flags_ex()", err);
if ((dbi_state & (MDBX_DBI_CREAT | MDBX_DBI_FRESH)) == 0)
dbi_stable = true;
}
return !dbi_invalid;
}
void testcase_smoke4fork::txn_end(bool abort) {
if (dbi) {
if (abort) {
if (dbi_state & MDBX_DBI_CREAT)
dbi_stable = false;
if (dbi_state & MDBX_DBI_FRESH)
dbi_invalid = true;
} else {
if (dbi_state & (MDBX_DBI_CREAT | MDBX_DBI_FRESH))
dbi_stable = true;
}
dbi_state = 0;
}
inherited::txn_end(abort);
}
bool testcase_smoke4fork::run() { bool testcase_smoke4fork::run() {
static std::vector<pid_t> history; static std::vector<pid_t> history;
const pid_t current_pid = getpid(); const pid_t current_pid = getpid();
@ -52,6 +97,7 @@ bool testcase_smoke4fork::run() {
current_pid, mdbx_strerror(err)); current_pid, mdbx_strerror(err));
return false; return false;
} }
open_dbi();
if (flipcoin()) { if (flipcoin()) {
if (!smoke()) { if (!smoke()) {
@ -65,11 +111,11 @@ bool testcase_smoke4fork::run() {
log_verbose("%s[deep %d, pid %d] probe %s", "pre-fork", deep, current_pid, log_verbose("%s[deep %d, pid %d] probe %s", "pre-fork", deep, current_pid,
"skipped"); "skipped");
#ifdef __SANITIZE_ADDRESS__ #ifdef __SANITIZE_ADDRESS__
const bool abort_txn_to_avoid_memleak = true; const bool commit_txn_to_avoid_memleak = true;
#else #else
const bool abort_txn_to_avoid_memleak = !RUNNING_ON_VALGRIND && flipcoin(); const bool commit_txn_to_avoid_memleak = !RUNNING_ON_VALGRIND && flipcoin();
#endif #endif
if (abort_txn_to_avoid_memleak && txn_guard) if (commit_txn_to_avoid_memleak && txn_guard)
txn_end(false); txn_end(false);
} }
@ -90,8 +136,14 @@ bool testcase_smoke4fork::run() {
log_flush(); log_flush();
if (err != MDBX_SUCCESS) if (err != MDBX_SUCCESS)
failure_perror("mdbx_env_resurrect_after_fork()", err); failure_perror("mdbx_env_resurrect_after_fork()", err);
if (txn_guard) if (txn_guard) {
if (dbi_state & MDBX_DBI_CREAT)
dbi_invalid = true;
// if (dbi_state & MDBX_DBI_FRESH)
// dbi_invalid = true;
dbi_state = 0;
mdbx_txn_abort(txn_guard.release()); mdbx_txn_abort(txn_guard.release());
}
if (!smoke()) { if (!smoke()) {
log_notice("%s[deep %d, pid %d] probe %s", "fork-child", deep, new_pid, log_notice("%s[deep %d, pid %d] probe %s", "fork-child", deep, new_pid,
"failed"); "failed");
@ -182,9 +234,19 @@ bool testcase_forkread::smoke() {
failure_perror("mdbx_env_info_ex()", err); failure_perror("mdbx_env_info_ex()", err);
uint64_t seq; uint64_t seq;
err = mdbx_dbi_sequence(txn_guard.get(), dbi, &seq, 0); if (dbi_invalid) {
if (unlikely(err != MDBX_SUCCESS)) err = mdbx_dbi_sequence(txn_guard.get(), dbi, &seq, 0);
failure_perror("mdbx_dbi_sequence(get)", err); if (unlikely(err != (dbi ? MDBX_BAD_DBI : MDBX_SUCCESS)))
failure("unexpected '%s' from mdbx_dbi_sequence(get, bad_dbi %d)",
mdbx_strerror(err), dbi);
open_dbi();
}
if (!dbi_invalid) {
err = mdbx_dbi_sequence(txn_guard.get(), dbi, &seq, 0);
if (unlikely(err != MDBX_SUCCESS))
failure("unexpected '%s' from mdbx_dbi_sequence(get, dbi %d)",
mdbx_strerror(err), dbi);
}
txn_end(false); txn_end(false);
return true; return true;
} }
@ -210,10 +272,21 @@ bool testcase_forkwrite::smoke() {
if (!txn_guard) if (!txn_guard)
txn_begin(false); txn_begin(false);
uint64_t seq; uint64_t seq;
int err = mdbx_dbi_sequence(txn_guard.get(), dbi, &seq, 1); if (dbi_invalid) {
if (unlikely(err != MDBX_SUCCESS)) int err = mdbx_dbi_sequence(txn_guard.get(), dbi, &seq, 0);
failure_perror("mdbx_dbi_sequence(inc)", err); if (unlikely(err != (dbi ? MDBX_BAD_DBI : MDBX_EACCESS)))
failure("unexpected '%s' from mdbx_dbi_sequence(get, bad_dbi %d)",
mdbx_strerror(err), dbi);
open_dbi();
}
if (!dbi_invalid) {
int err = mdbx_dbi_sequence(txn_guard.get(), dbi, &seq, 1);
if (unlikely(err != MDBX_SUCCESS))
failure("unexpected '%s' from mdbx_dbi_sequence(inc, dbi %d)",
mdbx_strerror(err), dbi);
}
txn_end(false); txn_end(false);
if (!firstly_read && !testcase_forkread::smoke()) if (!firstly_read && !testcase_forkread::smoke())

View File

@ -248,9 +248,10 @@ protected:
void db_prepare(); void db_prepare();
void db_open(); void db_open();
void db_close(); void db_close();
void txn_begin(bool readonly, MDBX_txn_flags_t flags = MDBX_TXN_READWRITE); virtual void txn_begin(bool readonly,
MDBX_txn_flags_t flags = MDBX_TXN_READWRITE);
int breakable_commit(); int breakable_commit();
void txn_end(bool abort); virtual void txn_end(bool abort);
int breakable_restart(); int breakable_restart();
void txn_restart(bool abort, bool readonly, void txn_restart(bool abort, bool readonly,
MDBX_txn_flags_t flags = MDBX_TXN_READWRITE); MDBX_txn_flags_t flags = MDBX_TXN_READWRITE);