diff --git a/mdbx.h b/mdbx.h index 2a6a2d78..7a1d9e5e 100644 --- a/mdbx.h +++ b/mdbx.h @@ -1793,6 +1793,24 @@ LIBMDBX_API const char *mdbx_strerror_r_ANSI2OEM(int errnum, char *buf, * \returns a non-zero error value on failure and 0 on success. */ LIBMDBX_API int mdbx_env_create(MDBX_env **penv); +/** \brief MDBX environment options. */ +enum MDBX_option_t { + MDBX_opt_sync_bytes, + MDBX_opt_sync_period, + MDBX_opt_max_dbx, + MDBX_opt_max_readers, +}; +#ifndef __cplusplus +/** \ingroup c_settings */ +typedef enum MDBX_option_t MDBX_option_t; +#endif + +LIBMDBX_API int mdbx_env_set_option(MDBX_env *env, const MDBX_option_t option, + const uint64_t value); +LIBMDBX_API int mdbx_env_get_option(const MDBX_env *env, + const MDBX_option_t option, + uint64_t *value); + /** \brief Open an environment instance. * \ingroup c_opening * @@ -2178,7 +2196,10 @@ LIBMDBX_INLINE_API(int, mdbx_env_sync_poll, (MDBX_env * env)) { * a synchronous flush would be made. * * \returns A non-zero error value on failure and 0 on success. */ -LIBMDBX_API int mdbx_env_set_syncbytes(MDBX_env *env, size_t threshold); +LIBMDBX_INLINE_API(int, mdbx_env_set_syncbytes, + (MDBX_env * env, size_t threshold)) { + return mdbx_env_set_option(env, MDBX_opt_sync_bytes, threshold); +} /** \brief Sets relative period since the last unsteady commit to force flush * the data buffers to disk, even of \ref MDBX_SAFE_NOSYNC flag in the @@ -2210,8 +2231,10 @@ LIBMDBX_API int mdbx_env_set_syncbytes(MDBX_env *env, size_t threshold); * the last unsteady commit. * * \returns A non-zero error value on failure and 0 on success. */ -LIBMDBX_API int mdbx_env_set_syncperiod(MDBX_env *env, - unsigned seconds_16dot16); +LIBMDBX_INLINE_API(int, mdbx_env_set_syncperiod, + (MDBX_env * env, unsigned seconds_16dot16)) { + return mdbx_env_set_option(env, MDBX_opt_sync_period, seconds_16dot16); +} /** \brief Close the environment and release the memory map. * \ingroup c_opening @@ -2603,7 +2626,10 @@ mdbx_limits_txnsize_max(intptr_t pagesize); * some possible errors are: * \retval MDBX_EINVAL An invalid parameter was specified. * \retval MDBX_EPERM The environment is already open. */ -LIBMDBX_API int mdbx_env_set_maxreaders(MDBX_env *env, unsigned readers); +LIBMDBX_INLINE_API(int, mdbx_env_set_maxreaders, + (MDBX_env * env, unsigned readers)) { + return mdbx_env_set_option(env, MDBX_opt_max_readers, readers); +} /** \brief Get the maximum number of threads/reader slots for the environment. * \ingroup c_statinfo @@ -2616,7 +2642,16 @@ LIBMDBX_API int mdbx_env_set_maxreaders(MDBX_env *env, unsigned readers); * \returns A non-zero error value on failure and 0 on success, * some possible errors are: * \retval MDBX_EINVAL An invalid parameter was specified. */ -LIBMDBX_API int mdbx_env_get_maxreaders(const MDBX_env *env, unsigned *readers); +LIBMDBX_INLINE_API(int, mdbx_env_get_maxreaders, + (const MDBX_env *env, unsigned *readers)) { + int rc = MDBX_EINVAL; + if (readers) { + uint64_t proxy = 0; + rc = mdbx_env_get_option(env, MDBX_opt_max_readers, &proxy); + *readers = (unsigned)proxy; + } + return rc; +} /** \brief Set the maximum number of named databases for the environment. * \ingroup c_settings @@ -2639,7 +2674,9 @@ LIBMDBX_API int mdbx_env_get_maxreaders(const MDBX_env *env, unsigned *readers); * some possible errors are: * \retval MDBX_EINVAL An invalid parameter was specified. * \retval MDBX_EPERM The environment is already open. */ -LIBMDBX_API int mdbx_env_set_maxdbs(MDBX_env *env, MDBX_dbi dbs); +LIBMDBX_INLINE_API(int, mdbx_env_set_maxdbs, (MDBX_env * env, MDBX_dbi dbs)) { + return mdbx_env_set_option(env, MDBX_opt_max_dbx, dbs); +} /** \brief Get the maximum number of named databases for the environment. * \ingroup c_statinfo @@ -2651,7 +2688,16 @@ LIBMDBX_API int mdbx_env_set_maxdbs(MDBX_env *env, MDBX_dbi dbs); * \returns A non-zero error value on failure and 0 on success, * some possible errors are: * \retval MDBX_EINVAL An invalid parameter was specified. */ -LIBMDBX_API int mdbx_env_get_maxdbs(MDBX_env *env, MDBX_dbi *dbs); +LIBMDBX_INLINE_API(int, mdbx_env_get_maxdbs, + (const MDBX_env *env, MDBX_dbi *dbs)) { + int rc = MDBX_EINVAL; + if (dbs) { + uint64_t proxy = 0; + rc = mdbx_env_get_option(env, MDBX_opt_max_dbx, &proxy); + *dbs = (MDBX_dbi)proxy; + } + return rc; +} /** \brief Get the maximum size of keys can write. * \ingroup c_statinfo diff --git a/src/core.c b/src/core.c index d72293c7..5333efd1 100644 --- a/src/core.c +++ b/src/core.c @@ -9625,57 +9625,19 @@ __cold int mdbx_env_set_mapsize(MDBX_env *env, size_t size) { } __cold int mdbx_env_set_maxdbs(MDBX_env *env, MDBX_dbi dbs) { - int rc = check_env(env); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - - if (unlikely(dbs > MDBX_MAX_DBI)) - return MDBX_EINVAL; - - if (unlikely(env->me_map)) - return MDBX_EPERM; - - env->me_maxdbs = dbs + CORE_DBS; - return MDBX_SUCCESS; + return __inline_mdbx_env_set_maxdbs(env, dbs); } -__cold int mdbx_env_get_maxdbs(MDBX_env *env, MDBX_dbi *dbs) { - int rc = check_env(env); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - - if (unlikely(!dbs)) - return MDBX_EINVAL; - - *dbs = env->me_maxdbs; - return MDBX_SUCCESS; +__cold int mdbx_env_get_maxdbs(const MDBX_env *env, MDBX_dbi *dbs) { + return __inline_mdbx_env_get_maxdbs(env, dbs); } __cold int mdbx_env_set_maxreaders(MDBX_env *env, unsigned readers) { - int rc = check_env(env); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - - if (unlikely(readers < 1 || readers > MDBX_READERS_LIMIT)) - return MDBX_EINVAL; - - if (unlikely(env->me_map)) - return MDBX_EPERM; - - env->me_maxreaders = readers; - return MDBX_SUCCESS; + return __inline_mdbx_env_set_maxreaders(env, readers); } __cold int mdbx_env_get_maxreaders(const MDBX_env *env, unsigned *readers) { - int rc = check_env(env); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - - if (unlikely(!readers)) - return MDBX_EINVAL; - - *readers = env->me_maxreaders; - return MDBX_SUCCESS; + return __inline_mdbx_env_get_maxreaders(env, readers); } /* Further setup required for opening an MDBX environment */ @@ -18256,43 +18218,11 @@ static txnid_t __cold mdbx_kick_longlived_readers(MDBX_env *env, } __cold int mdbx_env_set_syncbytes(MDBX_env *env, size_t threshold) { - int rc = check_env(env); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - - if (unlikely(env->me_flags & MDBX_RDONLY)) - return MDBX_EACCESS; - - if (unlikely(!env->me_map)) - return MDBX_EPERM; - - *env->me_autosync_threshold = bytes2pgno(env, threshold + env->me_psize - 1); - if (threshold) { - rc = mdbx_env_sync_poll(env); - if (unlikely(MDBX_IS_ERROR(rc))) - return rc; - } - return MDBX_SUCCESS; + return __inline_mdbx_env_set_syncbytes(env, threshold); } __cold int mdbx_env_set_syncperiod(MDBX_env *env, unsigned seconds_16dot16) { - int rc = check_env(env); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - - if (unlikely(env->me_flags & MDBX_RDONLY)) - return MDBX_EACCESS; - - if (unlikely(!env->me_map)) - return MDBX_EPERM; - - *env->me_autosync_period = mdbx_osal_16dot16_to_monotime(seconds_16dot16); - if (seconds_16dot16) { - rc = mdbx_env_sync_poll(env); - if (unlikely(MDBX_IS_ERROR(rc))) - return rc; - } - return MDBX_SUCCESS; + return __inline_mdbx_env_set_syncperiod(env, seconds_16dot16); } __cold int mdbx_env_set_hsr(MDBX_env *env, MDBX_hsr_func *hsr) { @@ -19696,6 +19626,102 @@ __cold MDBX_cmp_func *mdbx_get_datacmp(unsigned flags) { return get_default_datacmp(flags); } +__cold int mdbx_env_set_option(MDBX_env *env, const MDBX_option_t option, + const uint64_t value) { + int err = check_env(env); + if (unlikely(err != MDBX_SUCCESS)) + return err; + + switch (option) { + case MDBX_opt_sync_bytes: + if (unlikely(env->me_flags & MDBX_RDONLY)) + return MDBX_EACCESS; + if (unlikely(!env->me_autosync_threshold)) + return MDBX_EPERM; + if (sizeof(value) > sizeof(size_t) && unlikely(value != (size_t)value)) + return MDBX_TOO_LARGE; + if ((*env->me_autosync_threshold = + bytes2pgno(env, (size_t)value + env->me_psize - 1)) != 0) { + err = mdbx_env_sync_poll(env); + if (unlikely(MDBX_IS_ERROR(err))) + return err; + } + break; + + case MDBX_opt_sync_period: + if (unlikely(env->me_flags & MDBX_RDONLY)) + return MDBX_EACCESS; + if (unlikely(!env->me_autosync_period)) + return MDBX_EPERM; + if (unlikely(value > UINT32_MAX)) + return MDBX_TOO_LARGE; + if ((*env->me_autosync_period = + mdbx_osal_16dot16_to_monotime((uint32_t)value)) != 0) { + err = mdbx_env_sync_poll(env); + if (unlikely(MDBX_IS_ERROR(err))) + return err; + } + break; + + case MDBX_opt_max_dbx: + if (unlikely(value > MDBX_MAX_DBI)) + return MDBX_EINVAL; + if (unlikely(env->me_map)) + return MDBX_EPERM; + env->me_maxdbs = (unsigned)value + CORE_DBS; + break; + + case MDBX_opt_max_readers: + if (unlikely(value < 1 || value > MDBX_READERS_LIMIT)) + return MDBX_EINVAL; + if (unlikely(env->me_map)) + return MDBX_EPERM; + env->me_maxreaders = (unsigned)value; + break; + + default: + return MDBX_EINVAL; + } + + return err; +} + +__cold int mdbx_env_get_option(const MDBX_env *env, const MDBX_option_t option, + uint64_t *value) { + int err = check_env(env); + if (unlikely(err != MDBX_SUCCESS)) + return err; + if (unlikely(!value)) + return MDBX_EINVAL; + + switch (option) { + case MDBX_opt_sync_bytes: + if (unlikely(!env->me_autosync_threshold)) + return MDBX_EPERM; + *value = *env->me_autosync_threshold; + break; + + case MDBX_opt_sync_period: + if (unlikely(!env->me_autosync_period)) + return MDBX_EPERM; + *value = mdbx_osal_monotime_to_16dot16(*env->me_autosync_period); + break; + + case MDBX_opt_max_dbx: + *value = env->me_maxdbs - CORE_DBS; + break; + + case MDBX_opt_max_readers: + *value = env->me_maxreaders; + break; + + default: + return MDBX_EINVAL; + } + + return MDBX_SUCCESS; +} + /*** Attribute support functions for Nexenta **********************************/ #ifdef MDBX_NEXENTA_ATTRS