mirror of
https://github.com/isar/libmdbx.git
synced 2025-01-21 18:58:21 +08:00
mdbx: Merge branch 'devel'.
This commit is contained in:
commit
121f09af22
20
lmdb.h
20
lmdb.h
@ -1039,8 +1039,16 @@ size_t mdb_txn_id(MDB_txn *txn);
|
|||||||
*
|
*
|
||||||
* The transaction handle is freed. It and its cursors must not be used
|
* The transaction handle is freed. It and its cursors must not be used
|
||||||
* again after this call, except with #mdb_cursor_renew().
|
* again after this call, except with #mdb_cursor_renew().
|
||||||
* @note Earlier documentation incorrectly said all cursors would be freed.
|
*
|
||||||
|
* @note MDBX-mode:
|
||||||
|
* A cursor must be closed explicitly always, before
|
||||||
|
* or after its transaction ends. It can be reused with
|
||||||
|
* #mdb_cursor_renew() before finally closing it.
|
||||||
|
*
|
||||||
|
* @note LMDB-compatible mode:
|
||||||
|
* Earlier documentation incorrectly said all cursors would be freed.
|
||||||
* Only write-transactions free cursors.
|
* Only write-transactions free cursors.
|
||||||
|
*
|
||||||
* @param[in] txn A transaction handle returned by #mdb_txn_begin()
|
* @param[in] txn A transaction handle returned by #mdb_txn_begin()
|
||||||
* @return A non-zero error value on failure and 0 on success. Some possible
|
* @return A non-zero error value on failure and 0 on success. Some possible
|
||||||
* errors are:
|
* errors are:
|
||||||
@ -1057,8 +1065,16 @@ int mdb_txn_commit(MDB_txn *txn);
|
|||||||
*
|
*
|
||||||
* The transaction handle is freed. It and its cursors must not be used
|
* The transaction handle is freed. It and its cursors must not be used
|
||||||
* again after this call, except with #mdb_cursor_renew().
|
* again after this call, except with #mdb_cursor_renew().
|
||||||
* @note Earlier documentation incorrectly said all cursors would be freed.
|
*
|
||||||
|
* @note MDBX-mode:
|
||||||
|
* A cursor must be closed explicitly always, before
|
||||||
|
* or after its transaction ends. It can be reused with
|
||||||
|
* #mdb_cursor_renew() before finally closing it.
|
||||||
|
*
|
||||||
|
* @note LMDB-compatible mode:
|
||||||
|
* Earlier documentation incorrectly said all cursors would be freed.
|
||||||
* Only write-transactions free cursors.
|
* Only write-transactions free cursors.
|
||||||
|
*
|
||||||
* @param[in] txn A transaction handle returned by #mdb_txn_begin()
|
* @param[in] txn A transaction handle returned by #mdb_txn_begin()
|
||||||
*/
|
*/
|
||||||
int mdb_txn_abort(MDB_txn *txn);
|
int mdb_txn_abort(MDB_txn *txn);
|
||||||
|
32
mdb.c
32
mdb.c
@ -2700,8 +2700,9 @@ mdb_cursors_eot(MDB_txn *txn, unsigned merge)
|
|||||||
|
|
||||||
for (i = txn->mt_numdbs; --i >= 0; ) {
|
for (i = txn->mt_numdbs; --i >= 0; ) {
|
||||||
for (mc = cursors[i]; mc; mc = next) {
|
for (mc = cursors[i]; mc; mc = next) {
|
||||||
mdb_ensure(NULL, mc->mc_signature == MDBX_MC_SIGNATURE
|
unsigned stage = mc->mc_signature;
|
||||||
|| mc->mc_signature == MDBX_MC_WAIT4EOT);
|
mdb_ensure(NULL, stage == MDBX_MC_SIGNATURE
|
||||||
|
|| stage == MDBX_MC_WAIT4EOT);
|
||||||
next = mc->mc_next;
|
next = mc->mc_next;
|
||||||
if ((bk = mc->mc_backup) != NULL) {
|
if ((bk = mc->mc_backup) != NULL) {
|
||||||
if (merge) {
|
if (merge) {
|
||||||
@ -2714,10 +2715,8 @@ mdb_cursors_eot(MDB_txn *txn, unsigned merge)
|
|||||||
if ((mx = mc->mc_xcursor) != NULL)
|
if ((mx = mc->mc_xcursor) != NULL)
|
||||||
mx->mx_cursor.mc_txn = bk->mc_txn;
|
mx->mx_cursor.mc_txn = bk->mc_txn;
|
||||||
} else {
|
} else {
|
||||||
/* Abort nested txn, but save current cursor's stage */
|
/* Abort nested txn */
|
||||||
unsigned stage = mc->mc_signature;
|
|
||||||
*mc = *bk;
|
*mc = *bk;
|
||||||
mc->mc_signature = stage;
|
|
||||||
if ((mx = mc->mc_xcursor) != NULL)
|
if ((mx = mc->mc_xcursor) != NULL)
|
||||||
*mx = *(MDB_xcursor *)(bk+1);
|
*mx = *(MDB_xcursor *)(bk+1);
|
||||||
}
|
}
|
||||||
@ -2725,11 +2724,12 @@ mdb_cursors_eot(MDB_txn *txn, unsigned merge)
|
|||||||
bk->mc_signature = 0;
|
bk->mc_signature = 0;
|
||||||
free(bk);
|
free(bk);
|
||||||
}
|
}
|
||||||
if (mc->mc_signature == MDBX_MC_WAIT4EOT) {
|
if (stage == MDBX_MC_WAIT4EOT) {
|
||||||
mc->mc_signature = 0;
|
mc->mc_signature = 0;
|
||||||
free(mc);
|
free(mc);
|
||||||
} else {
|
} else {
|
||||||
mc->mc_signature = MDBX_MC_READY4CLOSE;
|
mc->mc_signature = MDBX_MC_READY4CLOSE;
|
||||||
|
mc->mc_flags = 0 /* reset C_UNTRACK */;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
mc = bk;
|
mc = bk;
|
||||||
@ -3244,7 +3244,12 @@ mdb_txn_reset(MDB_txn *txn)
|
|||||||
if (unlikely(!(txn->mt_flags & MDB_TXN_RDONLY)))
|
if (unlikely(!(txn->mt_flags & MDB_TXN_RDONLY)))
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
|
|
||||||
|
#if MDBX_MODE_ENABLED
|
||||||
|
/* LY: don't close DBI-handles in MDBX mode */
|
||||||
|
return mdb_txn_end(txn, MDB_END_RESET|MDB_END_UPDATE);
|
||||||
|
#else
|
||||||
return mdb_txn_end(txn, MDB_END_RESET);
|
return mdb_txn_end(txn, MDB_END_RESET);
|
||||||
|
#endif /* MDBX_MODE_ENABLED */
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
@ -3256,6 +3261,12 @@ mdb_txn_abort(MDB_txn *txn)
|
|||||||
if(unlikely(txn->mt_signature != MDBX_MT_SIGNATURE))
|
if(unlikely(txn->mt_signature != MDBX_MT_SIGNATURE))
|
||||||
return MDB_VERSION_MISMATCH;
|
return MDB_VERSION_MISMATCH;
|
||||||
|
|
||||||
|
#if MDBX_MODE_ENABLED
|
||||||
|
if (F_ISSET(txn->mt_flags, MDB_TXN_RDONLY))
|
||||||
|
/* LY: don't close DBI-handles in MDBX mode */
|
||||||
|
return mdb_txn_end(txn, MDB_END_ABORT|MDB_END_UPDATE|MDB_END_SLOT|MDB_END_FREE);
|
||||||
|
#endif /* MDBX_MODE_ENABLED */
|
||||||
|
|
||||||
if (txn->mt_child)
|
if (txn->mt_child)
|
||||||
mdb_txn_abort(txn->mt_child);
|
mdb_txn_abort(txn->mt_child);
|
||||||
|
|
||||||
@ -5763,7 +5774,7 @@ mdb_page_search(MDB_cursor *mc, MDB_val *key, int flags)
|
|||||||
return MDB_BAD_TXN;
|
return MDB_BAD_TXN;
|
||||||
} else {
|
} else {
|
||||||
/* Make sure we're using an up-to-date root */
|
/* Make sure we're using an up-to-date root */
|
||||||
if (*mc->mc_dbflag & DB_STALE) {
|
if (unlikely(*mc->mc_dbflag & DB_STALE)) {
|
||||||
MDB_cursor mc2;
|
MDB_cursor mc2;
|
||||||
if (unlikely(TXN_DBI_CHANGED(mc->mc_txn, mc->mc_dbi)))
|
if (unlikely(TXN_DBI_CHANGED(mc->mc_txn, mc->mc_dbi)))
|
||||||
return MDB_BAD_DBI;
|
return MDB_BAD_DBI;
|
||||||
@ -7826,15 +7837,14 @@ mdb_cursor_init(MDB_cursor *mc, MDB_txn *txn, MDB_dbi dbi, MDB_xcursor *mx)
|
|||||||
mc->mc_pg[0] = 0;
|
mc->mc_pg[0] = 0;
|
||||||
mc->mc_flags = 0;
|
mc->mc_flags = 0;
|
||||||
mc->mc_ki[0] = 0;
|
mc->mc_ki[0] = 0;
|
||||||
|
mc->mc_xcursor = NULL;
|
||||||
if (txn->mt_dbs[dbi].md_flags & MDB_DUPSORT) {
|
if (txn->mt_dbs[dbi].md_flags & MDB_DUPSORT) {
|
||||||
mdb_tassert(txn, mx != NULL);
|
mdb_tassert(txn, mx != NULL);
|
||||||
mx->mx_cursor.mc_signature = MDBX_MC_SIGNATURE;
|
mx->mx_cursor.mc_signature = MDBX_MC_SIGNATURE;
|
||||||
mc->mc_xcursor = mx;
|
mc->mc_xcursor = mx;
|
||||||
mdb_xcursor_init0(mc);
|
mdb_xcursor_init0(mc);
|
||||||
} else {
|
|
||||||
mc->mc_xcursor = NULL;
|
|
||||||
}
|
}
|
||||||
if (*mc->mc_dbflag & DB_STALE) {
|
if (unlikely(*mc->mc_dbflag & DB_STALE)) {
|
||||||
mdb_page_search(mc, NULL, MDB_PS_ROOTONLY);
|
mdb_page_search(mc, NULL, MDB_PS_ROOTONLY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -10226,7 +10236,7 @@ mdbx_stat(MDB_txn *txn, MDB_dbi dbi, MDBX_stat *arg, size_t bytes)
|
|||||||
if (unlikely(txn->mt_flags & MDB_TXN_BLOCKED))
|
if (unlikely(txn->mt_flags & MDB_TXN_BLOCKED))
|
||||||
return MDB_BAD_TXN;
|
return MDB_BAD_TXN;
|
||||||
|
|
||||||
if (txn->mt_dbflags[dbi] & DB_STALE) {
|
if (unlikely(txn->mt_dbflags[dbi] & DB_STALE)) {
|
||||||
MDB_cursor mc;
|
MDB_cursor mc;
|
||||||
MDB_xcursor mx;
|
MDB_xcursor mx;
|
||||||
/* Stale, must read the DB's root. cursor_init does it for us. */
|
/* Stale, must read the DB's root. cursor_init does it for us. */
|
||||||
|
51
mdbx.c
51
mdbx.c
@ -172,7 +172,7 @@ typedef struct mdb_walk_ctx {
|
|||||||
|
|
||||||
/** Depth-first tree traversal. */
|
/** Depth-first tree traversal. */
|
||||||
static int __cold
|
static int __cold
|
||||||
mdb_env_walk(mdb_walk_ctx_t *ctx, const char* dbi, pgno_t pg, int flags, int deep)
|
mdb_env_walk(mdb_walk_ctx_t *ctx, const char* dbi, pgno_t pg, int deep)
|
||||||
{
|
{
|
||||||
MDB_page *mp;
|
MDB_page *mp;
|
||||||
int rc, i, nkeys;
|
int rc, i, nkeys;
|
||||||
@ -238,7 +238,7 @@ mdb_env_walk(mdb_walk_ctx_t *ctx, const char* dbi, pgno_t pg, int flags, int dee
|
|||||||
payload_size += NODESIZE + node->mn_ksize;
|
payload_size += NODESIZE + node->mn_ksize;
|
||||||
|
|
||||||
if (IS_BRANCH(mp)) {
|
if (IS_BRANCH(mp)) {
|
||||||
rc = mdb_env_walk(ctx, dbi, NODEPGNO(node), flags, deep);
|
rc = mdb_env_walk(ctx, dbi, NODEPGNO(node), deep);
|
||||||
if (rc)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
continue;
|
continue;
|
||||||
@ -286,7 +286,7 @@ mdb_env_walk(mdb_walk_ctx_t *ctx, const char* dbi, pgno_t pg, int flags, int dee
|
|||||||
name[namelen] = 0;
|
name[namelen] = 0;
|
||||||
}
|
}
|
||||||
rc = mdb_env_walk(ctx, (name && name[0]) ? name : dbi,
|
rc = mdb_env_walk(ctx, (name && name[0]) ? name : dbi,
|
||||||
db->md_root, node->mn_flags & F_DUPDATA, deep + 1);
|
db->md_root, deep + 1);
|
||||||
if (rc)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
@ -314,9 +314,9 @@ mdbx_env_pgwalk(MDB_txn *txn, MDBX_pgvisitor_func* visitor, void* user)
|
|||||||
rc = visitor(0, 2, user, "lmdb", "meta", 2, sizeof(MDB_meta)*2, PAGEHDRSZ*2,
|
rc = visitor(0, 2, user, "lmdb", "meta", 2, sizeof(MDB_meta)*2, PAGEHDRSZ*2,
|
||||||
(txn->mt_env->me_psize - sizeof(MDB_meta) - PAGEHDRSZ) *2);
|
(txn->mt_env->me_psize - sizeof(MDB_meta) - PAGEHDRSZ) *2);
|
||||||
if (! rc)
|
if (! rc)
|
||||||
rc = mdb_env_walk(&ctx, "free", txn->mt_dbs[FREE_DBI].md_root, 0, 0);
|
rc = mdb_env_walk(&ctx, "free", txn->mt_dbs[FREE_DBI].md_root, 0);
|
||||||
if (! rc)
|
if (! rc)
|
||||||
rc = mdb_env_walk(&ctx, "main", txn->mt_dbs[MAIN_DBI].md_root, 0, 0);
|
rc = mdb_env_walk(&ctx, "main", txn->mt_dbs[MAIN_DBI].md_root, 0);
|
||||||
if (! rc)
|
if (! rc)
|
||||||
rc = visitor(P_INVALID, 0, user, NULL, NULL, 0, 0, 0, 0);
|
rc = visitor(P_INVALID, 0, user, NULL, NULL, 0, 0, 0, 0);
|
||||||
return rc;
|
return rc;
|
||||||
@ -354,6 +354,47 @@ size_t mdbx_canary_get(MDB_txn *txn, mdbx_canary* canary)
|
|||||||
return txn->mt_txnid;
|
return txn->mt_txnid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int mdbx_cursor_on_first(MDB_cursor *mc)
|
||||||
|
{
|
||||||
|
if (unlikely(mc == NULL))
|
||||||
|
return EINVAL;
|
||||||
|
|
||||||
|
if (unlikely(mc->mc_signature != MDBX_MC_SIGNATURE))
|
||||||
|
return MDB_VERSION_MISMATCH;
|
||||||
|
|
||||||
|
if (!(mc->mc_flags & C_INITIALIZED))
|
||||||
|
return MDBX_RESULT_FALSE;
|
||||||
|
|
||||||
|
unsigned i;
|
||||||
|
for(i = 0; i < mc->mc_snum; ++i) {
|
||||||
|
if (mc->mc_ki[i])
|
||||||
|
return MDBX_RESULT_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return MDBX_RESULT_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
int mdbx_cursor_on_last(MDB_cursor *mc)
|
||||||
|
{
|
||||||
|
if (unlikely(mc == NULL))
|
||||||
|
return EINVAL;
|
||||||
|
|
||||||
|
if (unlikely(mc->mc_signature != MDBX_MC_SIGNATURE))
|
||||||
|
return MDB_VERSION_MISMATCH;
|
||||||
|
|
||||||
|
if (!(mc->mc_flags & C_INITIALIZED))
|
||||||
|
return MDBX_RESULT_FALSE;
|
||||||
|
|
||||||
|
unsigned i;
|
||||||
|
for(i = 0; i < mc->mc_snum; ++i) {
|
||||||
|
unsigned nkeys = NUMKEYS(mc->mc_pg[i]);
|
||||||
|
if (mc->mc_ki[i] != nkeys - 1)
|
||||||
|
return MDBX_RESULT_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return MDBX_RESULT_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
int mdbx_cursor_eof(MDB_cursor *mc)
|
int mdbx_cursor_eof(MDB_cursor *mc)
|
||||||
{
|
{
|
||||||
if (unlikely(mc == NULL))
|
if (unlikely(mc == NULL))
|
||||||
|
13
mdbx.h
13
mdbx.h
@ -219,10 +219,19 @@ typedef struct mdbx_canary {
|
|||||||
int mdbx_canary_put(MDB_txn *txn, const mdbx_canary* canary);
|
int mdbx_canary_put(MDB_txn *txn, const mdbx_canary* canary);
|
||||||
size_t mdbx_canary_get(MDB_txn *txn, mdbx_canary* canary);
|
size_t mdbx_canary_get(MDB_txn *txn, mdbx_canary* canary);
|
||||||
|
|
||||||
/* Returns 1 when no more data available or cursor not positioned,
|
/* Returns:
|
||||||
* 0 otherwise or less that zero in error case. */
|
* - MDBX_RESULT_TRUE when no more data available
|
||||||
|
* or cursor not positioned;
|
||||||
|
* - MDBX_RESULT_FALSE when data available;
|
||||||
|
* - Otherwise the error code. */
|
||||||
int mdbx_cursor_eof(MDB_cursor *mc);
|
int mdbx_cursor_eof(MDB_cursor *mc);
|
||||||
|
|
||||||
|
/* Returns: MDBX_RESULT_TRUE, MDBX_RESULT_FALSE or Error code. */
|
||||||
|
int mdbx_cursor_on_first(MDB_cursor *mc);
|
||||||
|
|
||||||
|
/* Returns: MDBX_RESULT_TRUE, MDBX_RESULT_FALSE or Error code. */
|
||||||
|
int mdbx_cursor_on_last(MDB_cursor *mc);
|
||||||
|
|
||||||
#define MDBX_EMULTIVAL (MDB_LAST_ERRCODE - 42)
|
#define MDBX_EMULTIVAL (MDB_LAST_ERRCODE - 42)
|
||||||
#define MDBX_RESULT_FALSE MDB_SUCCESS
|
#define MDBX_RESULT_FALSE MDB_SUCCESS
|
||||||
#define MDBX_RESULT_TRUE (-1)
|
#define MDBX_RESULT_TRUE (-1)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user