mdbx: add mdbx_env_info2(txn) and mdbx_env_stat2(txn).

Change-Id: Ifd128185a084c9dc61da140eeeaaf4b6022d3537
This commit is contained in:
Leonid Yuriev 2019-08-11 23:22:51 +03:00
parent d6a2f98ef5
commit 17407c9ecc
2 changed files with 82 additions and 29 deletions

4
mdbx.h
View File

@ -735,6 +735,8 @@ LIBMDBX_API int mdbx_env_copy2fd(MDBX_env *env, mdbx_filehandle_t fd,
* [out] stat The address of an MDBX_stat structure where the statistics * [out] stat The address of an MDBX_stat structure where the statistics
* will be copied */ * will be copied */
LIBMDBX_API int mdbx_env_stat(MDBX_env *env, MDBX_stat *stat, size_t bytes); LIBMDBX_API int mdbx_env_stat(MDBX_env *env, MDBX_stat *stat, size_t bytes);
LIBMDBX_API int mdbx_env_stat2(const MDBX_env *env, const MDBX_txn *txn,
MDBX_stat *stat, size_t bytes);
/* Return information about the MDBX environment. /* Return information about the MDBX environment.
* *
@ -742,6 +744,8 @@ LIBMDBX_API int mdbx_env_stat(MDBX_env *env, MDBX_stat *stat, size_t bytes);
* [out] stat The address of an MDBX_envinfo structure * [out] stat The address of an MDBX_envinfo structure
* where the information will be copied */ * where the information will be copied */
LIBMDBX_API int mdbx_env_info(MDBX_env *env, MDBX_envinfo *info, size_t bytes); LIBMDBX_API int mdbx_env_info(MDBX_env *env, MDBX_envinfo *info, size_t bytes);
LIBMDBX_API int mdbx_env_info2(const MDBX_env *env, const MDBX_txn *txn,
MDBX_envinfo *info, size_t bytes);
/* Flush the data buffers to disk. /* Flush the data buffers to disk.
* *

View File

@ -11966,7 +11966,8 @@ int __cold mdbx_env_get_fd(MDBX_env *env, mdbx_filehandle_t *arg) {
* [in] db the MDBX_db record containing the stats to return. * [in] db the MDBX_db record containing the stats to return.
* [out] arg the address of an MDBX_stat structure to receive the stats. * [out] arg the address of an MDBX_stat structure to receive the stats.
* Returns 0, this function always succeeds. */ * Returns 0, this function always succeeds. */
static int __cold mdbx_stat0(MDBX_env *env, MDBX_db *db, MDBX_stat *arg) { static int __cold mdbx_stat0(const MDBX_env *env, const MDBX_db *db,
MDBX_stat *arg) {
arg->ms_psize = env->me_psize; arg->ms_psize = env->me_psize;
arg->ms_depth = db->md_depth; arg->ms_depth = db->md_depth;
arg->ms_branch_pages = db->md_branch_pages; arg->ms_branch_pages = db->md_branch_pages;
@ -11977,60 +11978,108 @@ static int __cold mdbx_stat0(MDBX_env *env, MDBX_db *db, MDBX_stat *arg) {
} }
int __cold mdbx_env_stat(MDBX_env *env, MDBX_stat *arg, size_t bytes) { int __cold mdbx_env_stat(MDBX_env *env, MDBX_stat *arg, size_t bytes) {
MDBX_meta *meta; return mdbx_env_stat2(env, NULL, arg, bytes);
}
if (unlikely(env == NULL || arg == NULL)) int __cold mdbx_env_stat2(const MDBX_env *env, const MDBX_txn *txn,
MDBX_stat *arg, size_t bytes) {
if (unlikely((env == NULL && txn == NULL) || arg == NULL))
return MDBX_EINVAL; return MDBX_EINVAL;
if (unlikely(env->me_signature != MDBX_ME_SIGNATURE)) if (txn) {
return MDBX_EBADSIGN; if (unlikely(txn->mt_signature != MDBX_MT_SIGNATURE))
return MDBX_EBADSIGN;
if (unlikely(txn->mt_owner != mdbx_thread_self()))
return MDBX_THREAD_MISMATCH;
}
if (env) {
if (unlikely(env->me_signature != MDBX_ME_SIGNATURE))
return MDBX_EBADSIGN;
if (txn && unlikely(txn->mt_env != env))
return MDBX_EINVAL;
}
if (unlikely(bytes != sizeof(MDBX_stat))) if (unlikely(bytes != sizeof(MDBX_stat)))
return MDBX_EINVAL; return MDBX_EINVAL;
meta = mdbx_meta_head(env); const MDBX_db *db =
return mdbx_stat0(env, &meta->mm_dbs[MAIN_DBI], arg); txn ? &txn->mt_dbs[MAIN_DBI] : &mdbx_meta_head(env)->mm_dbs[MAIN_DBI];
return mdbx_stat0(txn->mt_env, db, arg);
} }
int __cold mdbx_env_info(MDBX_env *env, MDBX_envinfo *arg, size_t bytes) { int __cold mdbx_env_info(MDBX_env *env, MDBX_envinfo *arg, size_t bytes) {
if (unlikely(env == NULL || arg == NULL)) return mdbx_env_info2(env, NULL, arg, bytes);
}
int __cold mdbx_env_info2(const MDBX_env *env, const MDBX_txn *txn,
MDBX_envinfo *arg, size_t bytes) {
if (unlikely((env == NULL && txn == NULL) || arg == NULL))
return MDBX_EINVAL; return MDBX_EINVAL;
if (unlikely(env->me_signature != MDBX_ME_SIGNATURE)) if (txn) {
return MDBX_EBADSIGN; if (unlikely(txn->mt_signature != MDBX_MT_SIGNATURE))
return MDBX_EBADSIGN;
if (unlikely(txn->mt_owner != mdbx_thread_self()))
return MDBX_THREAD_MISMATCH;
}
if (env) {
if (unlikely(env->me_signature != MDBX_ME_SIGNATURE))
return MDBX_EBADSIGN;
if (txn && unlikely(txn->mt_env != env))
return MDBX_EINVAL;
} else {
env = txn->mt_env;
}
if (bytes != sizeof(MDBX_envinfo)) if (unlikely(bytes != sizeof(MDBX_envinfo)))
return MDBX_EINVAL; return MDBX_EINVAL;
const MDBX_meta *const meta0 = METAPAGE(env, 0); const MDBX_meta *const meta0 = METAPAGE(env, 0);
const MDBX_meta *const meta1 = METAPAGE(env, 1); const MDBX_meta *const meta1 = METAPAGE(env, 1);
const MDBX_meta *const meta2 = METAPAGE(env, 2); const MDBX_meta *const meta2 = METAPAGE(env, 2);
const MDBX_meta *meta; while (1) {
do { if (unlikely(env->me_flags & MDBX_FATAL_ERROR))
meta = mdbx_meta_head(env); return MDBX_PANIC;
arg->mi_recent_txnid = mdbx_meta_txnid_fluid(env, meta);
const MDBX_meta *const recent_meta = mdbx_meta_head(env);
arg->mi_recent_txnid = mdbx_meta_txnid_fluid(env, recent_meta);
arg->mi_meta0_txnid = mdbx_meta_txnid_fluid(env, meta0); arg->mi_meta0_txnid = mdbx_meta_txnid_fluid(env, meta0);
arg->mi_meta0_sign = meta0->mm_datasync_sign; arg->mi_meta0_sign = meta0->mm_datasync_sign;
arg->mi_meta1_txnid = mdbx_meta_txnid_fluid(env, meta1); arg->mi_meta1_txnid = mdbx_meta_txnid_fluid(env, meta1);
arg->mi_meta1_sign = meta1->mm_datasync_sign; arg->mi_meta1_sign = meta1->mm_datasync_sign;
arg->mi_meta2_txnid = mdbx_meta_txnid_fluid(env, meta2); arg->mi_meta2_txnid = mdbx_meta_txnid_fluid(env, meta2);
arg->mi_meta2_sign = meta2->mm_datasync_sign; arg->mi_meta2_sign = meta2->mm_datasync_sign;
arg->mi_last_pgno = meta->mm_geo.next - 1;
arg->mi_geo.lower = pgno2bytes(env, meta->mm_geo.lower); const MDBX_meta *txn_meta = recent_meta;
arg->mi_geo.upper = pgno2bytes(env, meta->mm_geo.upper); arg->mi_last_pgno = txn_meta->mm_geo.next - 1;
arg->mi_geo.current = pgno2bytes(env, meta->mm_geo.now); arg->mi_geo.current = pgno2bytes(env, txn_meta->mm_geo.now);
arg->mi_geo.shrink = pgno2bytes(env, meta->mm_geo.shrink); if (txn) {
arg->mi_geo.grow = pgno2bytes(env, meta->mm_geo.grow); arg->mi_last_pgno = txn->mt_next_pgno - 1;
arg->mi_geo.current = pgno2bytes(env, txn->mt_end_pgno);
const txnid_t wanna_meta_txnid =
(txn->mt_flags & MDBX_RDONLY) ? txn->mt_txnid : txn->mt_txnid - 1;
txn_meta = (arg->mi_meta0_txnid == wanna_meta_txnid) ? meta0 : txn_meta;
txn_meta = (arg->mi_meta1_txnid == wanna_meta_txnid) ? meta1 : txn_meta;
txn_meta = (arg->mi_meta2_txnid == wanna_meta_txnid) ? meta2 : txn_meta;
}
arg->mi_geo.lower = pgno2bytes(env, txn_meta->mm_geo.lower);
arg->mi_geo.upper = pgno2bytes(env, txn_meta->mm_geo.upper);
arg->mi_geo.shrink = pgno2bytes(env, txn_meta->mm_geo.shrink);
arg->mi_geo.grow = pgno2bytes(env, txn_meta->mm_geo.grow);
arg->mi_mapsize = env->me_mapsize; arg->mi_mapsize = env->me_mapsize;
mdbx_compiler_barrier(); mdbx_compiler_barrier();
} while (unlikely(arg->mi_meta0_txnid != mdbx_meta_txnid_fluid(env, meta0) || if (likely(arg->mi_meta0_txnid == mdbx_meta_txnid_fluid(env, meta0) &&
arg->mi_meta0_sign != meta0->mm_datasync_sign || arg->mi_meta0_sign == meta0->mm_datasync_sign &&
arg->mi_meta1_txnid != mdbx_meta_txnid_fluid(env, meta1) || arg->mi_meta1_txnid == mdbx_meta_txnid_fluid(env, meta1) &&
arg->mi_meta1_sign != meta1->mm_datasync_sign || arg->mi_meta1_sign == meta1->mm_datasync_sign &&
arg->mi_meta2_txnid != mdbx_meta_txnid_fluid(env, meta2) || arg->mi_meta2_txnid == mdbx_meta_txnid_fluid(env, meta2) &&
arg->mi_meta2_sign != meta2->mm_datasync_sign || arg->mi_meta2_sign == meta2->mm_datasync_sign &&
meta != mdbx_meta_head(env) || recent_meta == mdbx_meta_head(env) &&
arg->mi_recent_txnid != mdbx_meta_txnid_fluid(env, meta))); arg->mi_recent_txnid == mdbx_meta_txnid_fluid(env, recent_meta)))
break;
}
arg->mi_maxreaders = env->me_maxreaders; arg->mi_maxreaders = env->me_maxreaders;
arg->mi_numreaders = env->me_lck ? env->me_lck->mti_numreaders : INT32_MAX; arg->mi_numreaders = env->me_lck ? env->me_lck->mti_numreaders : INT32_MAX;