mirror of
				https://github.com/isar/libmdbx.git
				synced 2025-10-31 03:29:01 +08:00 
			
		
		
		
	mdbx-test: доработка after-fork сценариев с устранением логической ошибки.
This commit is contained in:
		| @@ -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); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user