mirror of
https://github.com/isar/libmdbx.git
synced 2025-01-02 00:44:12 +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:
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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user