mirror of
https://github.com/isar/libmdbx.git
synced 2024-12-30 03:34:13 +08:00
mdbx-test: доработка after-fork сценариев с устранением логической ошибки.
This commit is contained in:
parent
f0cfedc26f
commit
ba719ef12a
@ -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())
|
||||||
|
@ -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);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user