mirror of
				https://github.com/isar/libmdbx.git
				synced 2025-10-31 03:29:01 +08:00 
			
		
		
		
	lmdb: Move code into mdb_txn_end(). Was mdb_txn_reset0.
Side effects: * Clean txn up a bit even before freeing it. * Tweak DEBUG output at txn end. Add DEBUG after commit(writer). Change-Id: Ia9905257893923bb14cdf33b60b6387af3121f81
This commit is contained in:
		
				
					committed by
					
						 Leo Yuriev
						Leo Yuriev
					
				
			
			
				
	
			
			
			
						parent
						
							23af429b3f
						
					
				
				
					commit
					e3c8fa8eba
				
			
							
								
								
									
										106
									
								
								mdb.c
									
									
									
									
									
								
							
							
						
						
									
										106
									
								
								mdb.c
									
									
									
									
									
								
							| @@ -1116,6 +1116,19 @@ static int  mdb_page_alloc(MDB_cursor *mc, int num, MDB_page **mp); | ||||
| static int  mdb_page_new(MDB_cursor *mc, uint32_t flags, int num, MDB_page **mp); | ||||
| static int  mdb_page_touch(MDB_cursor *mc); | ||||
|  | ||||
| #define MDB_END_NAMES {"committed", "empty-commit", "abort", "reset", \ | ||||
| 	"reset-tmp", "fail-begin", "fail-beginchild"} | ||||
| enum { | ||||
| 	/* mdb_txn_end operation number, for logging */ | ||||
| 	MDB_END_COMMITTED, MDB_END_EMPTY_COMMIT, MDB_END_ABORT, MDB_END_RESET, | ||||
| 	MDB_END_RESET_TMP, MDB_END_FAIL_BEGIN, MDB_END_FAIL_BEGINCHILD | ||||
| }; | ||||
| #define MDB_END_OPMASK	0x0F	/**< mask for #mdb_txn_end() operation number */ | ||||
| #define MDB_END_UPDATE	0x10	/**< update env state (DBIs) */ | ||||
| #define MDB_END_FREE	0x20	/**< free txn unless it is #MDB_env.%me_txn0 */ | ||||
| #define MDB_END_SLOT MDB_NOTLS	/**< release any reader slot if #MDB_NOTLS */ | ||||
| static void mdb_txn_end(MDB_txn *txn, unsigned mode); | ||||
|  | ||||
| static int  mdb_page_get(MDB_txn *txn, pgno_t pgno, MDB_page **mp, int *lvl); | ||||
| static int  mdb_page_search_root(MDB_cursor *mc, | ||||
| 			    MDB_val *key, int modify); | ||||
| @@ -2676,9 +2689,6 @@ mdb_cursors_close(MDB_txn *txn, unsigned merge) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| static void | ||||
| mdb_txn_reset0(MDB_txn *txn, const char *act); | ||||
|  | ||||
| /** Set or check a pid lock. Set returns 0 on success. | ||||
|  * Check returns 0 if the process is certainly dead, nonzero if it may | ||||
|  * be alive (the lock exists or an error happened so we do not know). | ||||
| @@ -2833,13 +2843,8 @@ mdb_txn_renew0(MDB_txn *txn) | ||||
| 	txn->mt_dbflags[MAIN_DBI] = DB_VALID|DB_USRVALID; | ||||
| 	txn->mt_dbflags[FREE_DBI] = DB_VALID; | ||||
|  | ||||
| 	if (env->me_maxpg < txn->mt_next_pgno) { | ||||
| 		mdb_txn_reset0(txn, "renew0-mapfail"); | ||||
| 		if (new_notls) { | ||||
| 			txn->mt_u.reader->mr_pid = 0; | ||||
| 			txn->mt_u.reader = NULL; | ||||
| 			mdb_coherent_barrier(); | ||||
| 		} | ||||
| 	if (unlikely(env->me_maxpg < txn->mt_next_pgno)) { | ||||
| 		mdb_txn_end(txn, new_notls /*0 or MDB_END_SLOT*/ | MDB_END_FAIL_BEGIN); | ||||
| 		return MDB_MAP_RESIZED; | ||||
| 	} | ||||
|  | ||||
| @@ -2951,16 +2956,16 @@ mdb_txn_begin(MDB_env *env, MDB_txn *parent, unsigned flags, MDB_txn **ret) | ||||
| 			else | ||||
| 				rc = ENOMEM; | ||||
| 		} | ||||
| 		if (!rc) | ||||
| 		if (likely(!rc)) | ||||
| 			rc = mdb_cursor_shadow(parent, txn); | ||||
| 		if (rc) | ||||
| 			mdb_txn_reset0(txn, "beginchild-fail"); | ||||
| 		if (unlikely(rc)) | ||||
| 			mdb_txn_end(txn, MDB_END_FAIL_BEGINCHILD); | ||||
| 	} else { /* MDB_RDONLY */ | ||||
| 		txn->mt_dbiseqs = env->me_dbiseqs; | ||||
| renew: | ||||
| 		rc = mdb_txn_renew0(txn); | ||||
| 	} | ||||
| 	if (rc) { | ||||
| 	if (unlikely(rc)) { | ||||
| 		if (txn != env->me_txn0) | ||||
| 			free(txn); | ||||
| 	} else { | ||||
| @@ -3038,35 +3043,45 @@ mdb_txn_straggler(MDB_txn *txn, int *percent) | ||||
| 	return (0 > (long) lag) ? ~0u >> 1: lag; | ||||
| } | ||||
|  | ||||
| /** Common code for #mdb_txn_reset() and #mdb_txn_abort(). | ||||
| /** End a transaction, except successful commit of a nested transaction. | ||||
|  * May be called twice for readonly txns: First reset it, then abort. | ||||
|  * @param[in] txn the transaction handle to reset | ||||
|  * @param[in] act why the transaction is being reset | ||||
|  * @param[in] txn the transaction handle to end | ||||
|  * @param[in] mode why and how to end the transaction | ||||
|  */ | ||||
| static void | ||||
| mdb_txn_reset0(MDB_txn *txn, const char *act_) | ||||
| mdb_txn_end(MDB_txn *txn, unsigned mode) | ||||
| { | ||||
| 	MDB_env	*env = txn->mt_env; | ||||
| #if MDB_DEBUG | ||||
| 	static const char *const names[] = MDB_END_NAMES; | ||||
| #endif | ||||
|  | ||||
| 	/* Close any DBI handles opened in this txn */ | ||||
| 	mdb_dbis_update(txn, 0); | ||||
| 	/* Export or close DBI handles opened in this txn */ | ||||
| 	mdb_dbis_update(txn, mode & MDB_END_UPDATE); | ||||
|  | ||||
| 	mdb_debug("%s txn %zu%c %p on mdbenv %p, root page %zu", | ||||
| 		act_, txn->mt_txnid, (txn->mt_flags & MDB_TXN_RDONLY) ? 'r' : 'w', | ||||
| 		names[mode & MDB_END_OPMASK], | ||||
| 		txn->mt_txnid, (txn->mt_flags & MDB_TXN_RDONLY) ? 'r' : 'w', | ||||
| 		(void *) txn, (void *)env, txn->mt_dbs[MAIN_DBI].md_root); | ||||
|  | ||||
| 	if (F_ISSET(txn->mt_flags, MDB_TXN_RDONLY)) { | ||||
| 		if (txn->mt_u.reader) { | ||||
| 			txn->mt_u.reader->mr_txnid = (txnid_t)-1; | ||||
| 			if (!(env->me_flags & MDB_NOTLS)) | ||||
| 			if (!(env->me_flags & MDB_NOTLS)) { | ||||
| 				txn->mt_u.reader = NULL; /* txn does not own reader */ | ||||
| 			} else if (mode & MDB_END_SLOT) { | ||||
| 				txn->mt_u.reader->mr_pid = 0; | ||||
| 				txn->mt_u.reader = NULL; | ||||
| 			} /* else txn owns the slot until it does MDB_END_SLOT */ | ||||
| 		} | ||||
| 		mdb_coherent_barrier(); | ||||
| 		txn->mt_numdbs = 0;		/* close nothing if called again */ | ||||
| 		txn->mt_dbxs = NULL;	/* mark txn as reset */ | ||||
| 	} else { | ||||
| 		pgno_t *pghead = env->me_pghead; | ||||
|  | ||||
| 		mdb_cursors_close(txn, 0); | ||||
| 		if (!(mode & MDB_END_UPDATE)) /* !(already closed cursors) */ | ||||
| 			mdb_cursors_close(txn, 0); | ||||
| 		if (!(env->me_flags & MDB_WRITEMAP)) { | ||||
| 			mdb_dlist_free(txn); | ||||
| 		} | ||||
| @@ -3087,6 +3102,8 @@ mdb_txn_reset0(MDB_txn *txn, const char *act_) | ||||
| 			env->me_pglast = 0; | ||||
|  | ||||
| 			env->me_txn = NULL; | ||||
| 			mode = 0;	/* txn == env->me_txn0, do not free() it */ | ||||
|  | ||||
| 			/* The writer mutex was locked in mdb_txn_begin. */ | ||||
| 			mdb_mutex_unlock(env, MDB_MUTEX(env, w)); | ||||
| 		} else { | ||||
| @@ -3099,6 +3116,9 @@ mdb_txn_reset0(MDB_txn *txn, const char *act_) | ||||
|  | ||||
| 		mdb_midl_free(pghead); | ||||
| 	} | ||||
|  | ||||
| 	if (mode & MDB_END_FREE) | ||||
| 		free(txn); | ||||
| } | ||||
|  | ||||
| void | ||||
| @@ -3111,7 +3131,7 @@ mdb_txn_reset(MDB_txn *txn) | ||||
| 	if (!(txn->mt_flags & MDB_TXN_RDONLY)) | ||||
| 		return; | ||||
|  | ||||
| 	mdb_txn_reset0(txn, "reset"); | ||||
| 	mdb_txn_end(txn, MDB_END_RESET); | ||||
| } | ||||
|  | ||||
| void | ||||
| @@ -3123,15 +3143,7 @@ mdb_txn_abort(MDB_txn *txn) | ||||
| 	if (txn->mt_child) | ||||
| 		mdb_txn_abort(txn->mt_child); | ||||
|  | ||||
| 	mdb_txn_reset0(txn, "abort"); | ||||
| 	/* Free reader slot tied to this txn (if MDB_NOTLS && writable FS) */ | ||||
| 	if ((txn->mt_flags & MDB_TXN_RDONLY) && txn->mt_u.reader) { | ||||
| 		txn->mt_u.reader->mr_pid = 0; | ||||
| 		mdb_coherent_barrier(); | ||||
| 	} | ||||
|  | ||||
| 	if (txn != txn->mt_env->me_txn0) | ||||
| 		free(txn); | ||||
| 	mdb_txn_end(txn, MDB_END_ABORT|MDB_END_SLOT|MDB_END_FREE); | ||||
| } | ||||
|  | ||||
| /** Save the freelist as of this transaction to the freeDB. | ||||
| @@ -3571,12 +3583,15 @@ int | ||||
| mdb_txn_commit(MDB_txn *txn) | ||||
| { | ||||
| 	int rc; | ||||
| 	unsigned i; | ||||
| 	unsigned i, end_mode; | ||||
| 	MDB_env	*env; | ||||
|  | ||||
| 	if (unlikely(txn == NULL)) | ||||
| 		return EINVAL; | ||||
|  | ||||
| 	/* mdb_txn_end() mode for a commit which writes nothing */ | ||||
| 	end_mode = MDB_END_EMPTY_COMMIT|MDB_END_UPDATE|MDB_END_SLOT|MDB_END_FREE; | ||||
|  | ||||
| 	if (txn->mt_child) { | ||||
| 		rc = mdb_txn_commit(txn->mt_child); | ||||
| 		txn->mt_child = NULL; | ||||
| @@ -3584,11 +3599,10 @@ mdb_txn_commit(MDB_txn *txn) | ||||
| 			goto fail; | ||||
| 	} | ||||
|  | ||||
| 	env = txn->mt_env; | ||||
|  | ||||
| 	if (unlikely(F_ISSET(txn->mt_flags, MDB_TXN_RDONLY))) { | ||||
| 		mdb_dbis_update(txn, 1); | ||||
| 		txn->mt_numdbs = 2; /* so txn_abort() doesn't close any new handles */ | ||||
| 		mdb_txn_abort(txn); | ||||
| 		return MDB_SUCCESS; | ||||
| 		goto done; | ||||
| 	} | ||||
|  | ||||
| 	if (F_ISSET(txn->mt_flags, MDB_TXN_ERROR)) { | ||||
| @@ -3769,7 +3783,6 @@ mdb_txn_commit(MDB_txn *txn) | ||||
| 	mdb_midl_free(env->me_pghead); | ||||
| 	env->me_pghead = NULL; | ||||
| 	mdb_midl_shrink(&txn->mt_free_pgs); | ||||
| 	env->me_free_pgs = txn->mt_free_pgs; | ||||
|  | ||||
| 	if (mdb_audit_enabled()) | ||||
| 		mdb_audit(txn); | ||||
| @@ -3787,19 +3800,10 @@ mdb_txn_commit(MDB_txn *txn) | ||||
| 	} | ||||
| 	if (unlikely(rc != MDB_SUCCESS)) | ||||
| 		goto fail; | ||||
|  | ||||
| 	/* Free P_LOOSE pages left behind in dirty_list */ | ||||
| 	if (!(env->me_flags & MDB_WRITEMAP)) | ||||
| 		mdb_dlist_free(txn); | ||||
| 	end_mode = MDB_END_COMMITTED|MDB_END_UPDATE; | ||||
|  | ||||
| done: | ||||
| 	env->me_pglast = 0; | ||||
| 	env->me_txn = NULL; | ||||
| 	mdb_dbis_update(txn, 1); | ||||
|  | ||||
| 	mdb_mutex_unlock(env, MDB_MUTEX(env, w)); | ||||
| 	if (txn != env->me_txn0) | ||||
| 		free(txn); | ||||
| 	mdb_txn_end(txn, end_mode); | ||||
| 	return MDB_SUCCESS; | ||||
|  | ||||
| fail: | ||||
| @@ -8804,7 +8808,7 @@ mdb_env_copyfd0(MDB_env *env, HANDLE fd) | ||||
| 		return rc; | ||||
|  | ||||
| 	/* We must start the actual read txn after blocking writers */ | ||||
| 	mdb_txn_reset0(txn, "reset-stage1"); | ||||
| 	mdb_txn_end(txn, MDB_END_RESET_TMP); | ||||
|  | ||||
| 	/* Temporarily block writers until we snapshot the meta pages */ | ||||
| 	wmutex = MDB_MUTEX(env, w); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user