mirror of
https://github.com/isar/libmdbx.git
synced 2024-10-29 23:19:20 +08:00
mdbx-test: доработка after-fork сценариев с устранением логической ошибки.
This commit is contained in:
parent
f0cfedc26f
commit
ba719ef12a
@ -22,13 +22,58 @@
|
||||
class testcase_smoke4fork : public testcase {
|
||||
using inherited = testcase;
|
||||
|
||||
protected:
|
||||
bool dbi_invalid{true};
|
||||
bool dbi_stable{false};
|
||||
unsigned dbi_state{0};
|
||||
|
||||
public:
|
||||
testcase_smoke4fork(const actor_config &config, const mdbx_pid_t pid)
|
||||
: testcase(config, pid) {}
|
||||
virtual void txn_end(bool abort) override;
|
||||
bool run() override;
|
||||
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() {
|
||||
static std::vector<pid_t> history;
|
||||
const pid_t current_pid = getpid();
|
||||
@ -52,6 +97,7 @@ bool testcase_smoke4fork::run() {
|
||||
current_pid, mdbx_strerror(err));
|
||||
return false;
|
||||
}
|
||||
open_dbi();
|
||||
|
||||
if (flipcoin()) {
|
||||
if (!smoke()) {
|
||||
@ -65,11 +111,11 @@ bool testcase_smoke4fork::run() {
|
||||
log_verbose("%s[deep %d, pid %d] probe %s", "pre-fork", deep, current_pid,
|
||||
"skipped");
|
||||
#ifdef __SANITIZE_ADDRESS__
|
||||
const bool abort_txn_to_avoid_memleak = true;
|
||||
const bool commit_txn_to_avoid_memleak = true;
|
||||
#else
|
||||
const bool abort_txn_to_avoid_memleak = !RUNNING_ON_VALGRIND && flipcoin();
|
||||
const bool commit_txn_to_avoid_memleak = !RUNNING_ON_VALGRIND && flipcoin();
|
||||
#endif
|
||||
if (abort_txn_to_avoid_memleak && txn_guard)
|
||||
if (commit_txn_to_avoid_memleak && txn_guard)
|
||||
txn_end(false);
|
||||
}
|
||||
|
||||
@ -90,8 +136,14 @@ bool testcase_smoke4fork::run() {
|
||||
log_flush();
|
||||
if (err != MDBX_SUCCESS)
|
||||
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());
|
||||
}
|
||||
if (!smoke()) {
|
||||
log_notice("%s[deep %d, pid %d] probe %s", "fork-child", deep, new_pid,
|
||||
"failed");
|
||||
@ -182,9 +234,19 @@ bool testcase_forkread::smoke() {
|
||||
failure_perror("mdbx_env_info_ex()", err);
|
||||
|
||||
uint64_t seq;
|
||||
err = mdbx_dbi_sequence(txn_guard.get(), dbi, &seq, 0);
|
||||
if (unlikely(err != MDBX_SUCCESS))
|
||||
failure_perror("mdbx_dbi_sequence(get)", err);
|
||||
if (dbi_invalid) {
|
||||
err = mdbx_dbi_sequence(txn_guard.get(), dbi, &seq, 0);
|
||||
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);
|
||||
return true;
|
||||
}
|
||||
@ -210,10 +272,21 @@ bool testcase_forkwrite::smoke() {
|
||||
|
||||
if (!txn_guard)
|
||||
txn_begin(false);
|
||||
|
||||
uint64_t seq;
|
||||
int err = mdbx_dbi_sequence(txn_guard.get(), dbi, &seq, 1);
|
||||
if (unlikely(err != MDBX_SUCCESS))
|
||||
failure_perror("mdbx_dbi_sequence(inc)", err);
|
||||
if (dbi_invalid) {
|
||||
int err = mdbx_dbi_sequence(txn_guard.get(), dbi, &seq, 0);
|
||||
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);
|
||||
|
||||
if (!firstly_read && !testcase_forkread::smoke())
|
||||
|
@ -248,9 +248,10 @@ protected:
|
||||
void db_prepare();
|
||||
void db_open();
|
||||
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();
|
||||
void txn_end(bool abort);
|
||||
virtual void txn_end(bool abort);
|
||||
int breakable_restart();
|
||||
void txn_restart(bool abort, bool readonly,
|
||||
MDBX_txn_flags_t flags = MDBX_TXN_READWRITE);
|
||||
|
Loading…
Reference in New Issue
Block a user