mdbx: merge 'devel/b964b2abf' into master.

Change-Id: I0114bd59091044b56b72b3855b0a2e04da9c7eff
This commit is contained in:
Leonid Yuriev 2020-10-21 02:23:23 +03:00
commit f9a36f3eb1
28 changed files with 1638 additions and 442 deletions

View File

@ -2,3 +2,4 @@
^\.github/FUNDING\.yml
^\.travis\.yml$
\.def$
^packages/buildroot/

View File

@ -133,6 +133,7 @@ cadabra
callergraph
callgraph
calloc
cas
casename
cassert
castortech
@ -208,6 +209,7 @@ csrc
CSRSS
css
cstdarg
cstdatomic
cstddef
cstdint
cstr
@ -249,6 +251,7 @@ dbiseqs
dbistate
dbm
dbpath
dbs
dbsize
dbstate
DBT
@ -325,6 +328,7 @@ dpage
DPK
dpl
dprefix
DPs
dqiqg
dreamsxin
dsize
@ -426,6 +430,7 @@ errcode
errno
errnum
ERRORCHECK
errored
erthink
esac
eturn
@ -553,6 +558,7 @@ gitdir
github
githubusercontent
glibc
globals
gmail
gmake
gmx
@ -648,6 +654,7 @@ indx
INDXSIZE
ini
initd
INITED
initialiser
inl
inlined
@ -660,6 +667,7 @@ interprocedural
intlimits
intptr
intrin
intrinsics
inttypes
ioarena
IODQ
@ -734,6 +742,7 @@ klen
KMGTPEZY
knipp
kp
ks
ksize
kstat
kurt
@ -848,6 +857,7 @@ mathjax
mattr
MAXDATASIZE
maxdbs
maxed
maxgc
maxkey
maxkeysize
@ -1385,6 +1395,7 @@ semctl
semget
semid
semop
sems
sendfile
sepkey
SETALL
@ -1407,6 +1418,7 @@ Shipitsin
shm
showinitializer
showned
shrinked
sideeffect
sigaction
sigaddset
@ -1512,6 +1524,7 @@ strstr
strtol
strtoul
strtoull
structs
stylesheet
subalign
SUBDATA
@ -1662,6 +1675,7 @@ unregister
unspill
unsync
UNTRACK
updation
upsert
UPSERTING
upsertion
@ -1696,6 +1710,7 @@ valuemode
vasprintf
vedisdb
VERINFO
versioned
versioning
Veyor
vfprintf
@ -1744,6 +1759,7 @@ WIFSTOPPED
wiki
wikipedia
wiktionary
wildcards
WILLNEED
WINAPI
windowsbug

View File

@ -9,6 +9,11 @@ TODO:
- Finalize C++ API (few typos and trivia bugs are likely for now).
- Packages for ROSA Linux, ALT Linux, Fedora/RHEL, Debian/Ubuntu.
Added features:
- Provided package for [buildroot](https://buildroot.org/).
- Added `mdbx_env_delete()` for deletion an environment files in a proper and multiprocess-safe way.
- Added `mdbx_txn_commit_ex()` with collecting latency information.
Fixes:
- Fixed missing installation of `mdbx.h++`.
@ -21,6 +26,7 @@ Fixes:
- Fixed opening DB on a network shares (in the exclusive mode).
- Fixed copy&paste typos.
- Fixed minor false-positive GCC warning.
- Added workaround for broken `DEFINE_ENUM_FLAG_OPERATORS` from Windows SDK.
## v0.9.1 2020-09-30

View File

@ -87,7 +87,7 @@ ifeq ($(wildcard mdbx.c),mdbx.c)
#< dist-cutoff-end
################################################################################
# Amalgamated source code, i.e. distributed after `make dists`
# Amalgamated source code, i.e. distributed after `make dist`
MAN_SRCDIR := man1/
config.h: mdbx.c $(lastword $(MAKEFILE_LIST))

View File

@ -17,8 +17,8 @@ cmake_minimum_required(VERSION 3.8.2)
cmake_policy(PUSH)
cmake_policy(VERSION 3.8.2)
macro(add_compile_flags langs)
foreach(_lang ${langs})
macro(add_compile_flags languages)
foreach(_lang ${languages})
string(REPLACE ";" " " _flags "${ARGN}")
if(CMAKE_CXX_COMPILER_LOADED AND _lang STREQUAL "CXX")
set("${_lang}_FLAGS" "${${_lang}_FLAGS} ${_flags}")
@ -113,6 +113,17 @@ macro(fetch_version name source_root_directory parent_scope)
message(FATAL_ERROR "Please install latest version of git ('show --no-patch --format=%H HEAD' failed)")
endif()
execute_process(COMMAND ${GIT} describe --tags --abbrev=0 "--match=v[0-9]*"
OUTPUT_VARIABLE last_release_tag
OUTPUT_STRIP_TRAILING_WHITESPACE
WORKING_DIRECTORY ${source_root_directory}
RESULT_VARIABLE rc)
if(rc)
message(FATAL_ERROR "Please install latest version of git ('describe --tags --abbrev=0 --match=v[0-9]*' failed)")
endif()
if (last_release_tag)
set(git_revlist_arg "${last_release_tag}..HEAD")
else()
execute_process(COMMAND ${GIT} tag --sort=-version:refname
OUTPUT_VARIABLE tag_list
OUTPUT_STRIP_TRAILING_WHITESPACE
@ -122,7 +133,6 @@ macro(fetch_version name source_root_directory parent_scope)
message(FATAL_ERROR "Please install latest version of git ('tag --sort=-version:refname' failed)")
endif()
string(REGEX REPLACE "\n" ";" tag_list "${tag_list}")
set(last_release_tag "")
set(git_revlist_arg "HEAD")
foreach(tag IN LISTS tag_list)
if(NOT last_release_tag)
@ -130,6 +140,7 @@ macro(fetch_version name source_root_directory parent_scope)
set(git_revlist_arg "${tag}..HEAD")
endif()
endforeach(tag)
endif()
execute_process(COMMAND ${GIT} rev-list --count "${git_revlist_arg}"
OUTPUT_VARIABLE ${name}_GIT_REVISION
OUTPUT_STRIP_TRAILING_WHITESPACE

309
mdbx.h
View File

@ -350,6 +350,17 @@ typedef mode_t mdbx_mode_t;
#endif
#endif /* __dll_import */
/** \brief Auxiliary macro for robustly define the both inline version of API
* function and non-inline fallback dll-exported version for applications linked
* with old version of libmdbx, with a strictly ODR-common implementation. */
#if !defined(LIBMDBX_INTERNALS) || defined(DOXYGEN)
#define LIBMDBX_INLINE_API(TYPE, NAME, ARGS) static __inline TYPE NAME ARGS
#else
#define LIBMDBX_INLINE_API(TYPE, NAME, ARGS) \
/* proto of exported which uses common impl */ LIBMDBX_API TYPE NAME ARGS; \
/* definition of common impl */ static __inline TYPE __inline_##NAME ARGS
#endif /* LIBMDBX_INLINE_API */
/*----------------------------------------------------------------------------*/
#ifndef __cplusplus
@ -440,8 +451,27 @@ typedef mode_t mdbx_mode_t;
#endif
#endif /* MDBX_PRINTF_ARGS */
/* Oh, below are some songs and dances since:
* - C++ requires explicit definition of the necessary operators.
* - the proper implementation of DEFINE_ENUM_FLAG_OPERATORS for C++ required
* the constexpr feature which is broken in most old compilers;
* - DEFINE_ENUM_FLAG_OPERATORS may be defined broken as in the Windows SDK. */
#ifndef DEFINE_ENUM_FLAG_OPERATORS
#if defined(__cplusplus)
#ifdef __cplusplus
#if !defined(__cpp_constexpr) || __cpp_constexpr < 200704L || \
(defined(__LCC__) && __LCC__ < 124) || \
(defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ < 407) && \
!defined(__clang__) && !defined(__LCC__)) || \
(defined(_MSC_VER) && _MSC_VER < 1910) || \
(defined(__clang__) && __clang_major__ < 4)
/* The constexpr feature is not available or (may be) broken */
#define CONSTEXPR_ENUM_FLAGS_OPERATIONS 0
#else
/* C always allows these operators for enums */
#define CONSTEXPR_ENUM_FLAGS_OPERATIONS 1
#endif /* __cpp_constexpr */
/// Define operator overloads to enable bit operations on enum values that are
/// used to define flags (based on Microsoft's DEFINE_ENUM_FLAG_OPERATORS).
#define DEFINE_ENUM_FLAG_OPERATORS(ENUM) \
@ -463,8 +493,21 @@ typedef mode_t mdbx_mode_t;
MDBX_CXX14_CONSTEXPR ENUM &operator^=(ENUM &a, ENUM b) { return a = a ^ b; } \
}
#else /* __cplusplus */
#define DEFINE_ENUM_FLAG_OPERATORS(ENUM) /* nope, C allows these operators */
/* nope for C since it always allows these operators for enums */
#define DEFINE_ENUM_FLAG_OPERATORS(ENUM)
#define CONSTEXPR_ENUM_FLAGS_OPERATIONS 1
#endif /* !__cplusplus */
#elif !defined(CONSTEXPR_ENUM_FLAGS_OPERATIONS)
#ifdef __cplusplus
/* DEFINE_ENUM_FLAG_OPERATORS may be defined broken as in the Windows SDK */
#define CONSTEXPR_ENUM_FLAGS_OPERATIONS 0
#else
/* C always allows these operators for enums */
#define CONSTEXPR_ENUM_FLAGS_OPERATIONS 1
#endif
#endif /* DEFINE_ENUM_FLAG_OPERATORS */
/** @} end of Common Macros */
@ -1202,7 +1245,7 @@ enum MDBX_env_flags_t {
* - a system crash immediately after commit the write transaction
* high likely lead to database corruption.
* - successful completion of mdbx_env_sync(force = true) after one or
* more commited transactions guarantees consistency and durability.
* more committed transactions guarantees consistency and durability.
* - BUT by committing two or more transactions you back database into
* a weak state, in which a system crash may lead to database corruption!
* In case single transaction after mdbx_env_sync, you may lose transaction
@ -1251,10 +1294,10 @@ enum MDBX_txn_flags_t {
* will be ready for use with \ref mdbx_txn_renew(). This flag allows to
* preallocate memory and assign a reader slot, thus avoiding these operations
* at the next start of the transaction. */
#if defined(__cplusplus) && !defined(__cpp_constexpr) && !defined(DOXYGEN)
MDBX_TXN_RDONLY_PREPARE = uint32_t(MDBX_RDONLY) | uint32_t(MDBX_NOMEMINIT),
#else
#if CONSTEXPR_ENUM_FLAGS_OPERATIONS || defined(DOXYGEN)
MDBX_TXN_RDONLY_PREPARE = MDBX_RDONLY | MDBX_NOMEMINIT,
#else
MDBX_TXN_RDONLY_PREPARE = uint32_t(MDBX_RDONLY) | uint32_t(MDBX_NOMEMINIT),
#endif
/** Do not block when starting a write transaction. */
@ -1737,8 +1780,9 @@ LIBMDBX_API int mdbx_env_create(MDBX_env **penv);
* \param [in] env An environment handle returned
* by \ref mdbx_env_create()
*
* \param [in] pathname The directory in which the database files reside.
* This directory must already exist and be writable.
* \param [in] pathname The pathname for the database or the directory in which
* the database files reside. In the case of directory it
* must already exist and be writable.
*
* \param [in] flags Special options for this environment. This parameter
* must be set to 0 or by bitwise OR'ing together one
@ -1800,6 +1844,49 @@ LIBMDBX_API int mdbx_env_create(MDBX_env **penv);
LIBMDBX_API int mdbx_env_open(MDBX_env *env, const char *pathname,
MDBX_env_flags_t flags, mdbx_mode_t mode);
/** \brief Deletion modes for \ref mdbx_env_delete().
* \ingroup c_extra
* \see mdbx_env_delete() */
enum MDBX_env_delete_mode_t {
/** \brief Just delete the environment's files and directory if any.
* \note On POSIX systems, processes already working with the database will
* continue to work without interference until it close the environment.
* \note On Windows, the behavior of `MDB_ENV_JUST_DELETE` is different
* because the system does not support deleting files that are currently
* memory mapped. */
MDBX_ENV_JUST_DELETE = 0,
/** \brief Make sure that the environment is not being used by other
* processes, or return an error otherwise. */
MDBX_ENV_ENSURE_UNUSED = 1,
/** \brief Wait until other processes closes the environment before deletion.
*/
MDBX_ENV_WAIT_FOR_UNUSED = 2,
};
#ifndef __cplusplus
/** \c_extra c_statinfo */
typedef enum MDBX_env_delete_mode_t MDBX_env_delete_mode_t;
#endif
/** \brief Delete the environment's files in a proper and multiprocess-safe way.
* \ingroup c_extra
*
* \param [in] pathname The pathname for the database or the directory in which
* the database files reside.
*
* \param [in] mode Special deletion mode for the environment. This
* parameter must be set to one of the values described
* above in the \ref MDBX_env_delete_mode_t section.
*
* \note The \ref MDBX_ENV_JUST_DELETE don't supported on Windows since system
* unable to delete a memory-mapped files.
*
* \returns A non-zero error value on failure and 0 on success,
* some possible errors are:
* \retval MDBX_RESULT_TRUE No corresponding files or directories were found,
* so no deletion was performed. */
LIBMDBX_API int mdbx_env_delete(const char *pathname,
MDBX_env_delete_mode_t mode);
/** \brief Copy an MDBX environment to the specified path, with options.
* \ingroup c_extra
*
@ -1867,7 +1954,7 @@ struct MDBX_stat {
uint64_t ms_leaf_pages; /**< Number of leaf pages */
uint64_t ms_overflow_pages; /**< Number of overflow pages */
uint64_t ms_entries; /**< Number of data items */
uint64_t ms_mod_txnid; /**< Transaction ID of commited last modification */
uint64_t ms_mod_txnid; /**< Transaction ID of committed last modification */
};
#ifndef __cplusplus
/** \ingroup c_statinfo */
@ -1895,11 +1982,15 @@ typedef struct MDBX_stat MDBX_stat;
* \returns A non-zero error value on failure and 0 on success. */
LIBMDBX_API int mdbx_env_stat_ex(const MDBX_env *env, const MDBX_txn *txn,
MDBX_stat *stat, size_t bytes);
/** \brief Return statistics about the MDBX environment.
* \ingroup c_statinfo
* \deprecated Please use mdbx_env_stat_ex() instead. */
MDBX_DEPRECATED LIBMDBX_API int mdbx_env_stat(MDBX_env *env, MDBX_stat *stat,
size_t bytes);
MDBX_DEPRECATED LIBMDBX_INLINE_API(int, mdbx_env_stat,
(const MDBX_env *env, MDBX_stat *stat,
size_t bytes)) {
return mdbx_env_stat_ex(env, NULL, stat, bytes);
}
/** \brief Information about the environment
* \ingroup c_statinfo
@ -1985,8 +2076,11 @@ LIBMDBX_API int mdbx_env_info_ex(const MDBX_env *env, const MDBX_txn *txn,
/** \brief Return information about the MDBX environment.
* \ingroup c_statinfo
* \deprecated Please use mdbx_env_info_ex() instead. */
MDBX_DEPRECATED LIBMDBX_API int mdbx_env_info(MDBX_env *env, MDBX_envinfo *info,
size_t bytes);
MDBX_DEPRECATED LIBMDBX_INLINE_API(int, mdbx_env_info,
(const MDBX_env *env, MDBX_envinfo *info,
size_t bytes)) {
return mdbx_env_info_ex(env, NULL, info, bytes);
}
/** \brief Flush the environment data buffers to disk.
* \ingroup c_extra
@ -2028,12 +2122,16 @@ LIBMDBX_API int mdbx_env_sync_ex(MDBX_env *env, bool force, bool nonblock);
/** \brief The shortcut to calling \ref mdbx_env_sync_ex() with
* the `force=true` and `nonblock=false` arguments.
* \ingroup c_extra */
LIBMDBX_API int mdbx_env_sync(MDBX_env *env);
LIBMDBX_INLINE_API(int, mdbx_env_sync, (MDBX_env * env)) {
return mdbx_env_sync_ex(env, true, false);
}
/** \brief The shortcut to calling \ref mdbx_env_sync_ex() with
* the `force=false` and `nonblock=true` arguments.
* \ingroup c_extra */
LIBMDBX_API int mdbx_env_sync_poll(MDBX_env *env);
LIBMDBX_INLINE_API(int, mdbx_env_sync_poll, (MDBX_env * env)) {
return mdbx_env_sync_ex(env, false, true);
}
/** \brief Sets threshold to force flush the data buffers to disk, even any of
* \ref MDBX_SAFE_NOSYNC flag in the environment.
@ -2135,7 +2233,9 @@ LIBMDBX_API int mdbx_env_close_ex(MDBX_env *env, bool dont_sync);
/** \brief The shortcut to calling \ref mdbx_env_close_ex() with
* the `dont_sync=false` argument.
* \ingroup c_opening */
LIBMDBX_API int mdbx_env_close(MDBX_env *env);
LIBMDBX_INLINE_API(int, mdbx_env_close, (MDBX_env * env)) {
return mdbx_env_close_ex(env, false);
}
/** \brief Set environment flags.
* \ingroup c_settings
@ -2389,8 +2489,10 @@ LIBMDBX_API int mdbx_env_set_geometry(MDBX_env *env, intptr_t size_lower,
/** \deprecated Please use \ref mdbx_env_set_geometry() instead.
* \ingroup c_settings */
MDBX_DEPRECATED LIBMDBX_API int mdbx_env_set_mapsize(MDBX_env *env,
size_t size);
MDBX_DEPRECATED LIBMDBX_INLINE_API(int, mdbx_env_set_mapsize,
(MDBX_env * env, size_t size)) {
return mdbx_env_set_geometry(env, size, size, size, -1, -1, -1);
}
/** \brief Find out whether to use readahead or not, based on the given database
* size and the amount of available memory. \ingroup c_extra
@ -2411,13 +2513,15 @@ LIBMDBX_API int mdbx_is_readahead_reasonable(size_t volume,
/** \brief Returns the minimal database page size in bytes.
* \ingroup c_statinfo */
MDBX_NOTHROW_CONST_FUNCTION __inline intptr_t mdbx_limits_pgsize_min(void) {
MDBX_NOTHROW_CONST_FUNCTION LIBMDBX_INLINE_API(intptr_t, mdbx_limits_pgsize_min,
(void)) {
return MDBX_MIN_PAGESIZE;
}
/** \brief Returns the maximal database page size in bytes.
* \ingroup c_statinfo */
MDBX_NOTHROW_CONST_FUNCTION __inline intptr_t mdbx_limits_pgsize_max(void) {
MDBX_NOTHROW_CONST_FUNCTION LIBMDBX_INLINE_API(intptr_t, mdbx_limits_pgsize_max,
(void)) {
return MDBX_MAX_PAGESIZE;
}
@ -2574,60 +2678,6 @@ LIBMDBX_API int mdbx_env_set_userctx(MDBX_env *env, void *ctx);
MDBX_NOTHROW_PURE_FUNCTION LIBMDBX_API void *
mdbx_env_get_userctx(const MDBX_env *env);
/** \brief Create a transaction for use with the environment.
* \ingroup c_transactions
*
* The transaction handle may be discarded using \ref mdbx_txn_abort()
* or \ref mdbx_txn_commit().
* \see mdbx_txn_begin_ex()
*
* \note A transaction and its cursors must only be used by a single thread,
* and a thread may only have a single transaction at a time. If \ref MDBX_NOTLS
* is in use, this does not apply to read-only transactions.
*
* \note Cursors may not span transactions.
*
* \param [in] env An environment handle returned by \ref mdbx_env_create()
* \param [in] parent If this parameter is non-NULL, the new transaction will
* be a nested transaction, with the transaction indicated
* by parent as its parent. Transactions may be nested
* to any level. A parent transaction and its cursors may
* not issue any other operations than mdbx_txn_commit and
* \ref mdbx_txn_abort() while it has active child
* transactions.
* \param [in] flags Special options for this transaction. This parameter
* must be set to 0 or by bitwise OR'ing together one
* or more of the values described here:
* - \ref MDBX_RDONLY This transaction will not perform
* any write operations.
*
* - \ref MDBX_TXN_TRY Do not block when starting
* a write transaction.
*
* - \ref MDBX_SAFE_NOSYNC, \ref MDBX_NOMETASYNC.
* Do not sync data to disk corresponding
* to \ref MDBX_NOMETASYNC or \ref MDBX_SAFE_NOSYNC
* description. \see sync_modes
*
* \param [out] txn Address where the new MDBX_txn handle will be stored.
*
* \returns A non-zero error value on failure and 0 on success,
* some possible errors are:
* \retval MDBX_PANIC A fatal error occurred earlier and the
* environment must be shut down.
* \retval MDBX_UNABLE_EXTEND_MAPSIZE Another process wrote data beyond
* this MDBX_env's mapsize and this
* environment map must be resized as well.
* See \ref mdbx_env_set_mapsize().
* \retval MDBX_READERS_FULL A read-only transaction was requested and
* the reader lock table is full.
* See \ref mdbx_env_set_maxreaders().
* \retval MDBX_ENOMEM Out of memory.
* \retval MDBX_BUSY The write transaction is already started by the
* current thread. */
LIBMDBX_API int mdbx_txn_begin(MDBX_env *env, MDBX_txn *parent,
MDBX_txn_flags_t flags, MDBX_txn **txn);
/** \brief Create a transaction with a user provided context pointer
* for use with the environment.
* \ingroup c_transactions
@ -2690,6 +2740,65 @@ LIBMDBX_API int mdbx_txn_begin_ex(MDBX_env *env, MDBX_txn *parent,
MDBX_txn_flags_t flags, MDBX_txn **txn,
void *context);
/** \brief Create a transaction for use with the environment.
* \ingroup c_transactions
*
* The transaction handle may be discarded using \ref mdbx_txn_abort()
* or \ref mdbx_txn_commit().
* \see mdbx_txn_begin_ex()
*
* \note A transaction and its cursors must only be used by a single thread,
* and a thread may only have a single transaction at a time. If \ref MDBX_NOTLS
* is in use, this does not apply to read-only transactions.
*
* \note Cursors may not span transactions.
*
* \param [in] env An environment handle returned by \ref mdbx_env_create().
*
* \param [in] parent If this parameter is non-NULL, the new transaction will
* be a nested transaction, with the transaction indicated
* by parent as its parent. Transactions may be nested
* to any level. A parent transaction and its cursors may
* not issue any other operations than mdbx_txn_commit and
* \ref mdbx_txn_abort() while it has active child
* transactions.
*
* \param [in] flags Special options for this transaction. This parameter
* must be set to 0 or by bitwise OR'ing together one
* or more of the values described here:
* - \ref MDBX_RDONLY This transaction will not perform
* any write operations.
*
* - \ref MDBX_TXN_TRY Do not block when starting
* a write transaction.
*
* - \ref MDBX_SAFE_NOSYNC, \ref MDBX_NOMETASYNC.
* Do not sync data to disk corresponding
* to \ref MDBX_NOMETASYNC or \ref MDBX_SAFE_NOSYNC
* description. \see sync_modes
*
* \param [out] txn Address where the new MDBX_txn handle will be stored.
*
* \returns A non-zero error value on failure and 0 on success,
* some possible errors are:
* \retval MDBX_PANIC A fatal error occurred earlier and the
* environment must be shut down.
* \retval MDBX_UNABLE_EXTEND_MAPSIZE Another process wrote data beyond
* this MDBX_env's mapsize and this
* environment map must be resized as well.
* See \ref mdbx_env_set_mapsize().
* \retval MDBX_READERS_FULL A read-only transaction was requested and
* the reader lock table is full.
* See \ref mdbx_env_set_maxreaders().
* \retval MDBX_ENOMEM Out of memory.
* \retval MDBX_BUSY The write transaction is already started by the
* current thread. */
LIBMDBX_INLINE_API(int, mdbx_txn_begin,
(MDBX_env * env, MDBX_txn *parent, MDBX_txn_flags_t flags,
MDBX_txn **txn)) {
return mdbx_txn_begin_ex(env, parent, flags, txn, NULL);
}
/** \brief Set application information associated with the \ref MDBX_txn.
* \ingroup c_transactions
* \see mdbx_txn_get_userctx()
@ -2812,6 +2921,38 @@ MDBX_NOTHROW_PURE_FUNCTION LIBMDBX_API int mdbx_txn_flags(const MDBX_txn *txn);
MDBX_NOTHROW_PURE_FUNCTION LIBMDBX_API uint64_t
mdbx_txn_id(const MDBX_txn *txn);
/** \brief Latency of commit stages in 1/65536 of seconds units.
* \warning This structure may be changed in future releases.
* \see mdbx_txn_commit_ex() */
struct MDBX_commit_latency {
/** \brief Duration of preparation (commit child transactions, update
* sub-databases records and cursors destroying). */
uint32_t preparation;
/** \brief Duration of GC/freeDB handling & updation. */
uint32_t gc;
/** \brief Duration of internal audit if enabled. */
uint32_t audit;
/** \brief Duration of writing dirty/modified data pages. */
uint32_t write;
/** \brief Duration of syncing written data to the dist/storage. */
uint32_t sync;
/** \brief Duration of transaction ending (releasing resources). */
uint32_t ending;
/** \brief The total duration of a commit. */
uint32_t whole;
};
#ifndef __cplusplus
/** \ingroup c_statinfo */
typedef struct MDBX_commit_latency MDBX_commit_latency;
#endif
/** \brief Commit all the operations of a transaction into the database and
* collect latency information.
* \see mdbx_txn_commit()
* \ingroup c_statinfo
* \warning This function may be changed in future releases. */
LIBMDBX_API int mdbx_txn_commit_ex(MDBX_txn *txn, MDBX_commit_latency *latency);
/** \brief Commit all the operations of a transaction into the database.
* \ingroup c_transactions
*
@ -2849,7 +2990,9 @@ mdbx_txn_id(const MDBX_txn *txn);
* \retval MDBX_ENOSPC No more disk space.
* \retval MDBX_EIO A system-level I/O error occurred.
* \retval MDBX_ENOMEM Out of memory. */
LIBMDBX_API int mdbx_txn_commit(MDBX_txn *txn);
LIBMDBX_INLINE_API(int, mdbx_txn_commit, (MDBX_txn * txn)) {
return mdbx_txn_commit_ex(txn, NULL);
}
/** \brief Abandon all the operations of the transaction instead of saving them.
* \ingroup c_transactions
@ -3149,13 +3292,13 @@ mdbx_key_from_float(const float ieee754_32bit);
MDBX_NOTHROW_PURE_FUNCTION LIBMDBX_API uint32_t
mdbx_key_from_ptrfloat(const float *const ieee754_32bit);
MDBX_NOTHROW_CONST_FUNCTION __inline uint64_t
mdbx_key_from_int64(const int64_t i64) {
MDBX_NOTHROW_CONST_FUNCTION LIBMDBX_INLINE_API(uint64_t, mdbx_key_from_int64,
(const int64_t i64)) {
return UINT64_C(0x8000000000000000) + i64;
}
MDBX_NOTHROW_CONST_FUNCTION __inline uint32_t
mdbx_key_from_int32(const int32_t i32) {
MDBX_NOTHROW_CONST_FUNCTION LIBMDBX_INLINE_API(uint32_t, mdbx_key_from_int32,
(const int32_t i32)) {
return UINT32_C(0x80000000) + i32;
}
/** @} */
@ -3247,7 +3390,11 @@ LIBMDBX_API int mdbx_dbi_flags_ex(MDBX_txn *txn, MDBX_dbi dbi, unsigned *flags,
unsigned *state);
/** \brief The shortcut to calling \ref mdbx_dbi_flags_ex() with `state=NULL`
* for discarding it result. \ingroup c_statinfo */
LIBMDBX_API int mdbx_dbi_flags(MDBX_txn *txn, MDBX_dbi dbi, unsigned *flags);
LIBMDBX_INLINE_API(int, mdbx_dbi_flags,
(MDBX_txn * txn, MDBX_dbi dbi, unsigned *flags)) {
unsigned state;
return mdbx_dbi_flags_ex(txn, dbi, flags, &state);
}
/** \brief Close a database handle. Normally unnecessary.
* \ingroup c_dbi
@ -4251,7 +4398,7 @@ LIBMDBX_API int mdbx_thread_unregister(const MDBX_env *env);
* \param [in] pid A pid of the reader process.
* \param [in] tid A thread_id of the reader thread.
* \param [in] laggard An oldest read transaction number on which stalled.
* \param [in] gap A lag from the last commited txn.
* \param [in] gap A lag from the last committed txn.
* \param [in] space A space that actually become available for reuse after
* this reader finished. The callback function can take
* this value into account to evaluate the impact that

View File

@ -1563,14 +1563,7 @@ enum class value_mode {
///< lexicographic comparison like `std::memcmp()`.
///< In terms of keys, they are not unique, i.e. has
///< duplicates which are sorted by associated data values.
#if !defined(__cpp_constexpr) && !defined(DOXYGEN)
multi_reverse = uint32_t(MDBX_DUPSORT) | uint32_t(MDBX_REVERSEDUP),
multi_samelength = uint32_t(MDBX_DUPSORT) | uint32_t(MDBX_DUPFIXED),
multi_ordinal = uint32_t(MDBX_DUPSORT) | uint32_t(MDBX_DUPFIXED) |
uint32_t(MDBX_INTEGERDUP),
multi_reverse_samelength = uint32_t(MDBX_DUPSORT) |
uint32_t(MDBX_REVERSEDUP) | uint32_t(MDBX_DUPFIXED)
#else
#if CONSTEXPR_ENUM_FLAGS_OPERATIONS || defined(DOXYGEN)
multi_reverse =
MDBX_DUPSORT |
MDBX_REVERSEDUP, ///< A more than one data value could be associated with
@ -1617,6 +1610,13 @@ enum class value_mode {
///< In terms of keys, they are not unique, i.e. has duplicates
///< which are sorted by associated data values.
///< \note Not yet implemented and PRs are welcome.
#else
multi_reverse = uint32_t(MDBX_DUPSORT) | uint32_t(MDBX_REVERSEDUP),
multi_samelength = uint32_t(MDBX_DUPSORT) | uint32_t(MDBX_DUPFIXED),
multi_ordinal = uint32_t(MDBX_DUPSORT) | uint32_t(MDBX_DUPFIXED) |
uint32_t(MDBX_INTEGERDUP),
multi_reverse_samelength = uint32_t(MDBX_DUPSORT) |
uint32_t(MDBX_REVERSEDUP) | uint32_t(MDBX_DUPFIXED)
#endif
};
@ -1922,6 +1922,27 @@ public:
/// \brief Copy an environment to the specified file descriptor.
env &copy(filehandle fd, bool compactify, bool force_dynamic_size = false);
/// \brief Deletion modes for \ref remove().
enum remove_mode {
/// \brief Just delete the environment's files and directory if any.
/// \note On POSIX systems, processes already working with the database will
/// continue to work without interference until it close the environment.
/// \note On Windows, the behavior of `just_remove` is different
/// because the system does not support deleting files that are currently
/// memory mapped.
just_remove = MDBX_ENV_JUST_DELETE,
/// \brief Make sure that the environment is not being used by other
/// processes, or return an error otherwise.
ensure_unused = MDBX_ENV_ENSURE_UNUSED,
/// \brief Wait until other processes closes the environment before
/// deletion.
wait_for_unused = MDBX_ENV_WAIT_FOR_UNUSED
};
/// \brief Removes the environment's files in a proper and multiprocess-safe
/// way.
static bool remove(const path &, const remove_mode mode = just_remove);
/// \brief Statistics for a database in the MDBX environment.
using stat = ::MDBX_stat;
@ -2060,7 +2081,7 @@ public:
/// \ref MDBX_BAD_DBI (since the DB name is gone).
inline void close_map(const map_handle &);
/// \brief Readed information
/// \brief Reader information
struct reader_info {
int slot; ///< The reader lock table slot number.
mdbx_pid_t pid; ///< The reader process ID.

View File

@ -0,0 +1,255 @@
From 0bf9d06e8b090e2d9783d03074f3752ed708f6cf Mon Sep 17 00:00:00 2001
In-Reply-To: <CAO2+NUDJUL_FYfQ3E_cmmu20F3VOagxDpy_243a6mU3oAeASNA@mail.gmail.com>
References: <CAO2+NUDJUL_FYfQ3E_cmmu20F3VOagxDpy_243a6mU3oAeASNA@mail.gmail.com>
From: Leonid Yuriev <leo@yuriev.ru>
Date: Tue, 6 Oct 2020 22:19:56 +0300
Cc: Heiko Thiery <heiko.thiery@gmail.com>
Subject: [PATCH v4 0/1] package/libmdbx: new package (library/database)
This patch adds libmdbx v0.9.1 and below is a brief overview of libmdbx.
Changes v1 -> v2:
- libmdbx version v0.8.2 -> v0.9.1 (released 2020-09-30)
Changes v2 -> v3:
- removed outcommented stuff (suggested by Heiko Thiery).
- cleaned up and simplified the makefile (suggested by Heiko Thiery).
- added patch for C++ header installation.
- added patch with fix minor copy&paste typo.
- added patch with pthread workaround for buggy toolchain/cmake/buildroot.
- added patch for `pthread_yield()`.
- passed `utils/check-package package/libmdbx/*` (suggested by Heiko Thiery).
- passed `utils/test-pkg -a -p libmdbx` (suggested by Heiko Thiery).
Changes v3 -> v4:
- fix passing BR2_PACKAGE_LIBMDBX_TOOLS option to cmake.
- fix using `depend on` instead of `select`,
and add `comment` for C++ toolchain (suggested by Heiko Thiery).
- fix minor help typo.
Please merge.
Regards,
Leonid.
--
libmdbx is an extremely fast, compact, powerful, embedded, transactional
key-value database, with permissive license. libmdbx has a specific set
of properties and capabilities, focused on creating unique lightweight
solutions.
Historically, libmdbx (MDBX) is a deeply revised and extended descendant
of the legendary LMDB (Lightning Memory-Mapped Database). libmdbx
inherits all benefits from LMDB, but resolves some issues and adds a set
of improvements.
According to developers, for now libmdbx surpasses the LMDB in terms of
reliability, features and performance.
The most important differences MDBX from LMDB:
==============================================
1. More attention is paid to the quality of the code, to an
"unbreakability" of the API, to testing and automatic checks (i.e.
sanitizers, etc). So there:
- more control during operation;
- more checking parameters, internal audit of database structures;
- no warnings from compiler;
- no issues from ASAN, UBSAN, Valgrind, Coverity;
- etc.
2. Keys could be more than 2 times longer than LMDB.
3. Up to 20% faster than LMDB in CRUD benchmarks.
4. Automatic on-the-fly database size adjustment,
both increment and reduction.
5. Automatic continuous zero-overhead database compactification.
6. The same database format for 32- and 64-bit builds.
7. LIFO policy for Garbage Collection recycling (this can significantly
increase write performance due write-back disk cache up to several times
in a best case scenario).
8. Range query estimation.
9. Utility for checking the integrity of the database structure with
some recovery capabilities.
For more info please refer:
- https://github.com/erthink/libmdbx for source code and README.
- https://erthink.github.io/libmdbx for API description.
--
MDBX is a Btree-based database management library modeled loosely on the
BerkeleyDB API, but much simplified. The entire database (aka
"environment") is exposed in a memory map, and all data fetches return
data directly from the mapped memory, so no malloc's or memcpy's occur
during data fetches. As such, the library is extremely simple because it
requires no page caching layer of its own, and it is extremely high
performance and memory-efficient. It is also fully transactional with
full ACID semantics, and when the memory map is read-only, the database
integrity cannot be corrupted by stray pointer writes from application
code.
The library is fully thread-aware and supports concurrent read/write
access from multiple processes and threads. Data pages use a
copy-on-write strategy so no active data pages are ever overwritten,
which also provides resistance to corruption and eliminates the need of
any special recovery procedures after a system crash. Writes are fully
serialized; only one write transaction may be active at a time, which
guarantees that writers can never deadlock. The database structure is
multi-versioned so readers run with no locks; writers cannot block
readers, and readers don't block writers.
Unlike other well-known database mechanisms which use either write-ahead
transaction logs or append-only data writes, MDBX requires no
maintenance during operation. Both write-ahead loggers and append-only
databases require periodic checkpointing and/or compaction of their log
or database files otherwise they grow without bound. MDBX tracks
retired/freed pages within the database and re-uses them for new write
operations, so the database size does not grow without bound in normal
use.
The memory map can be used as a read-only or read-write map. It is
read-only by default as this provides total immunity to corruption.
Using read-write mode offers much higher write performance, but adds the
possibility for stray application writes thru pointers to silently
corrupt the database.
Features
========
- Key-value data model, keys are always sorted.
- Fully ACID-compliant, through to MVCC and CoW.
- Multiple key-value sub-databases within a single datafile.
- Range lookups, including range query estimation.
- Efficient support for short fixed length keys, including native
32/64-bit integers.
- Ultra-efficient support for multimaps. Multi-values sorted, searchable
and iterable. Keys stored without duplication.
- Data is memory-mapped and accessible directly/zero-copy. Traversal of
database records is extremely-fast.
- Transactions for readers and writers, ones do not block others.
- Writes are strongly serialized. No transaction conflicts nor
deadlocks.
- Readers are non-blocking, notwithstanding snapshot isolation.
- Nested write transactions.
- Reads scale linearly across CPUs.
- Continuous zero-overhead database compactification.
- Automatic on-the-fly database size adjustment.
- Customizable database page size.
- Olog(N) cost of lookup, insert, update, and delete operations by
virtue of B+ tree characteristics.
- Online hot backup.
- Append operation for efficient bulk insertion of pre-sorted data.
- No WAL nor any transaction journal. No crash recovery needed. No
maintenance is required.
- No internal cache and/or memory management, all done by basic OS
services.
Limitations
===========
- Page size: a power of 2, maximum 65536 bytes, default 4096 bytes.
- Key size: minimum 0, maximum ≈¼ pagesize (1300 bytes for default 4K
pagesize, 21780 bytes for 64K pagesize).
- Value size: minimum 0, maximum 2146435072 (0x7FF00000) bytes for maps,
≈¼ pagesize for multimaps (1348 bytes default 4K pagesize, 21828 bytes
for 64K pagesize).
- Write transaction size: up to 4194301 (0x3FFFFD) pages (16 GiB for
default 4K pagesize, 256 GiB for 64K pagesize).
- Database size: up to 2147483648 pages (8 TiB for default 4K pagesize,
128 TiB for 64K pagesize).
- Maximum sub-databases: 32765.
Gotchas
=======
- There cannot be more than one writer at a time, i.e. no more than one
write transaction at a time.
- libmdbx is based on B+ tree, so access to database pages is mostly
random. Thus SSDs provide a significant performance boost over
spinning disks for large databases.
- libmdbx uses shadow paging instead of WAL. Thus syncing data to disk
might be a bottleneck for write intensive workload.
- libmdbx uses copy-on-write for snapshot isolation during updates, but
read transactions prevents recycling an old retired/freed pages, since
it read ones. Thus altering of data during a parallel long-lived read
operation will increase the process work set, may exhaust entire free
database space, the database can grow quickly, and result in
performance degradation. Try to avoid long running read transactions.
- libmdbx is extraordinarily fast and provides minimal overhead for data
access, so you should reconsider using brute force techniques and
double check your code. On the one hand, in the case of libmdbx, a
simple linear search may be more profitable than complex indexes. On
the other hand, if you make something suboptimally, you can notice
detrimentally only on sufficiently large data.
--
Leonid Yuriev (1):
package/libmdbx: new package (library/database).
DEVELOPERS | 3 +
package/Config.in | 1 +
.../0001-mdbx-fix-minor-copy-paste-typo.patch | 27 ++++++++
...e-fix-missing-installation-of-mdbx.h.patch | 54 +++++++++++++++
.../0003-mdbx-fix-obsolete-__noreturn.patch | 27 ++++++++
...ield-instruction-on-ARM-if-unsupport.patch | 28 ++++++++
...fix-minor-false-positive-GCC-warning.patch | 27 ++++++++
...ad-workaround-for-buggy-toolchain-cm.patch | 65 +++++++++++++++++++
...mdbx-fix-pthread_yield-for-non-GLIBC.patch | 42 ++++++++++++
package/libmdbx/Config.in | 42 ++++++++++++
package/libmdbx/libmdbx.hash | 2 +
package/libmdbx/libmdbx.mk | 24 +++++++
12 files changed, 342 insertions(+)
create mode 100644 package/libmdbx/0001-mdbx-fix-minor-copy-paste-typo.patch
create mode 100644 package/libmdbx/0002-mdbx-cmake-fix-missing-installation-of-mdbx.h.patch
create mode 100644 package/libmdbx/0003-mdbx-fix-obsolete-__noreturn.patch
create mode 100644 package/libmdbx/0004-mdbx-don-t-use-yield-instruction-on-ARM-if-unsupport.patch
create mode 100644 package/libmdbx/0005-mdbx-load-fix-minor-false-positive-GCC-warning.patch
create mode 100644 package/libmdbx/0006-mdbx-cmake-pthread-workaround-for-buggy-toolchain-cm.patch
create mode 100644 package/libmdbx/0007-mdbx-fix-pthread_yield-for-non-GLIBC.patch
create mode 100644 package/libmdbx/Config.in
create mode 100644 package/libmdbx/libmdbx.hash
create mode 100644 package/libmdbx/libmdbx.mk
--
2.28.0

View File

@ -0,0 +1,490 @@
From 0bf9d06e8b090e2d9783d03074f3752ed708f6cf Mon Sep 17 00:00:00 2001
In-Reply-To: <CAO2+NUDJUL_FYfQ3E_cmmu20F3VOagxDpy_243a6mU3oAeASNA@mail.gmail.com>
References: <CAO2+NUDJUL_FYfQ3E_cmmu20F3VOagxDpy_243a6mU3oAeASNA@mail.gmail.com>
From: Leonid Yuriev <leo@yuriev.ru>
Date: Tue, 6 Oct 2020 22:10:00 +0300
Subject: [PATCH v4 1/1] package/libmdbx: new package (library/database).
This patch adds libmdbx v0.9.1:
- libmdbx is one of the fastest compact embeddable key-value ACID database.
- libmdbx has a specific set of properties and capabilities,
focused on creating unique lightweight solutions.
- libmdbx surpasses the legendary LMDB (Lightning Memory-Mapped Database)
in terms of reliability, features and performance.
https://github.com/erthink/libmdbx
---
Changes v1 -> v2:
- libmdbx version v0.8.2 -> v0.9.1 (released 2020-09-30)
Changes v2 -> v3:
- removed outcommented stuff (suggested by Heiko Thiery).
- cleaned up and simplified the makefile (suggested by Heiko Thiery).
- added patch for C++ header installation.
- added patch with fix minor copy&paste typo.
- added patch with pthread workaround for buggy toolchain/cmake/buildroot.
- added patch for `pthread_yield()`.
- passed `utils/check-package package/libmdbx/*` (suggested by Heiko Thiery)
- passed `utils/test-pkg -a -p libmdbx`,
except w/o threads & w/o MMU (suggested by Heiko Thiery).
Changes v3 -> v4:
- fix passing BR2_PACKAGE_LIBMDBX_TOOLS option to cmake.
- fix using `depend on` instead of `select`,
and add `comment` for C++ toolchain (suggested by Heiko Thiery).
- fix minor help typo.
Signed-off-by: Leonid Yuriev <leo@yuriev.ru>
---
DEVELOPERS | 3 +
package/Config.in | 1 +
.../0001-mdbx-fix-minor-copy-paste-typo.patch | 27 ++++++++
...e-fix-missing-installation-of-mdbx.h.patch | 54 +++++++++++++++
.../0003-mdbx-fix-obsolete-__noreturn.patch | 27 ++++++++
...ield-instruction-on-ARM-if-unsupport.patch | 28 ++++++++
...fix-minor-false-positive-GCC-warning.patch | 27 ++++++++
...ad-workaround-for-buggy-toolchain-cm.patch | 65 +++++++++++++++++++
...mdbx-fix-pthread_yield-for-non-GLIBC.patch | 42 ++++++++++++
package/libmdbx/Config.in | 42 ++++++++++++
package/libmdbx/libmdbx.hash | 2 +
package/libmdbx/libmdbx.mk | 24 +++++++
12 files changed, 342 insertions(+)
create mode 100644 package/libmdbx/0001-mdbx-fix-minor-copy-paste-typo.patch
create mode 100644 package/libmdbx/0002-mdbx-cmake-fix-missing-installation-of-mdbx.h.patch
create mode 100644 package/libmdbx/0003-mdbx-fix-obsolete-__noreturn.patch
create mode 100644 package/libmdbx/0004-mdbx-don-t-use-yield-instruction-on-ARM-if-unsupport.patch
create mode 100644 package/libmdbx/0005-mdbx-load-fix-minor-false-positive-GCC-warning.patch
create mode 100644 package/libmdbx/0006-mdbx-cmake-pthread-workaround-for-buggy-toolchain-cm.patch
create mode 100644 package/libmdbx/0007-mdbx-fix-pthread_yield-for-non-GLIBC.patch
create mode 100644 package/libmdbx/Config.in
create mode 100644 package/libmdbx/libmdbx.hash
create mode 100644 package/libmdbx/libmdbx.mk
diff --git a/DEVELOPERS b/DEVELOPERS
index f8655fa054..924e70e30c 100644
--- a/DEVELOPERS
+++ b/DEVELOPERS
@@ -1551,6 +1551,9 @@ N: Leon Anavi <leon.anavi@konsulko.com>
F: board/olimex/a10_olinuxino
F: configs/olimex_a10_olinuxino_lime_defconfig
+N: Leonid Yuriev <leo@yuriev.ru>
+F: package/libmdbx
+
N: Lionel Flandrin <lionel@svkt.org>
F: package/python-babel/
F: package/python-daemonize/
diff --git a/package/Config.in b/package/Config.in
index 51583d07d6..f87e0388a0 100644
--- a/package/Config.in
+++ b/package/Config.in
@@ -1370,6 +1370,7 @@ menu "Database"
source "package/kompexsqlite/Config.in"
source "package/leveldb/Config.in"
source "package/libgit2/Config.in"
+ source "package/libmdbx/Config.in"
source "package/libodb/Config.in"
source "package/libodb-boost/Config.in"
source "package/libodb-mysql/Config.in"
diff --git a/package/libmdbx/0001-mdbx-fix-minor-copy-paste-typo.patch b/package/libmdbx/0001-mdbx-fix-minor-copy-paste-typo.patch
new file mode 100644
index 0000000000..d9ff3c5e71
--- /dev/null
+++ b/package/libmdbx/0001-mdbx-fix-minor-copy-paste-typo.patch
@@ -0,0 +1,27 @@
+From 5807e2eda046bff35946972289236bbef5c0c597 Mon Sep 17 00:00:00 2001
+From: Leonid Yuriev <leo@yuriev.ru>
+Date: Thu, 1 Oct 2020 02:27:29 +0300
+Subject: [PATCH] mdbx++: fix minor copy&paste typo.
+
+Change-Id: I0af3e7ffbbd1231069a60f9f48880df3df2141d7
+Signed-off-by: Leonid Yuriev <leo@yuriev.ru>
+---
+ mdbx.h++ | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/mdbx.h++ b/mdbx.h++
+index 095ff9abb..2050f4b92 100644
+--- a/mdbx.h++
++++ b/mdbx.h++
+@@ -538,7 +538,7 @@ struct LIBMDBX_API_TYPE slice : public ::MDBX_val {
+ byte *from_base58(byte *dest, size_t dest_size,
+ bool ignore_spaces = false) const;
+
+- /// vReturns the buffer size in bytes needed for conversion
++ /// \brief Returns the buffer size in bytes needed for conversion
+ /// [Base58](https://en.wikipedia.org/wiki/Base58) dump to data.
+ MDBX_CXX11_CONSTEXPR size_t from_base58_bytes() const noexcept {
+ return length() / 11 * 8 + length() % 11 * 32 / 43;
+--
+2.28.0
+
diff --git a/package/libmdbx/0002-mdbx-cmake-fix-missing-installation-of-mdbx.h.patch b/package/libmdbx/0002-mdbx-cmake-fix-missing-installation-of-mdbx.h.patch
new file mode 100644
index 0000000000..df49342ccb
--- /dev/null
+++ b/package/libmdbx/0002-mdbx-cmake-fix-missing-installation-of-mdbx.h.patch
@@ -0,0 +1,54 @@
+From dc2cd19d566e84451ee47cf04277f97bc22771c5 Mon Sep 17 00:00:00 2001
+From: Leonid Yuriev <leo@yuriev.ru>
+Date: Fri, 2 Oct 2020 00:05:02 +0300
+Subject: [PATCH] mdbx-cmake: fix missing installation of `mdbx.h++`
+
+Change-Id: I41975e4eeff6583a266b273b9a4f8486982ede90
+Signed-off-by: Leonid Yuriev <leo@yuriev.ru>
+---
+ CMakeLists.txt | 8 +++++---
+ 1 file changed, 5 insertions(+), 3 deletions(-)
+
+diff --git a/CMakeLists.txt b/CMakeLists.txt
+index 28db425c5..95f116521 100644
+--- a/CMakeLists.txt
++++ b/CMakeLists.txt
+@@ -485,7 +485,8 @@ fetch_version(MDBX "${CMAKE_CURRENT_SOURCE_DIR}" FALSE)
+ message(STATUS "libmdbx version is ${MDBX_VERSION}")
+
+ # sources list
+-set(LIBMDBX_SOURCES mdbx.h "${CMAKE_CURRENT_BINARY_DIR}/config.h" )
++set(LIBMDBX_PUBLIC_HEADERS mdbx.h)
++set(LIBMDBX_SOURCES mdbx.h "${CMAKE_CURRENT_BINARY_DIR}/config.h")
+ if(MDBX_AMALGAMATED_SOURCE)
+ list(APPEND LIBMDBX_SOURCES mdbx.c)
+ else()
+@@ -511,6 +512,7 @@ else()
+ endif(MDBX_AMALGAMATED_SOURCE)
+ if(MDBX_BUILD_CXX)
+ message(STATUS "Use C${MDBX_C_STANDARD} and C++${MDBX_CXX_STANDARD} for libmdbx")
++ list(APPEND LIBMDBX_PUBLIC_HEADERS mdbx.h++)
+ list(APPEND LIBMDBX_SOURCES "${MDBX_SOURCE_DIR}/mdbx.c++" mdbx.h++)
+ else()
+ message(STATUS "Use C${MDBX_C_STANDARD} for libmdbx but C++ portion is disabled")
+@@ -561,7 +563,7 @@ if(MDBX_INSTALL_STATIC)
+ else()
+ add_library(mdbx-static STATIC EXCLUDE_FROM_ALL ${LIBMDBX_SOURCES})
+ endif()
+-set_target_properties(mdbx-static PROPERTIES PUBLIC_HEADER mdbx.h)
++set_target_properties(mdbx-static PROPERTIES PUBLIC_HEADER "${LIBMDBX_PUBLIC_HEADERS}")
+ target_compile_definitions(mdbx-static PRIVATE MDBX_BUILD_SHARED_LIBRARY=0)
+ target_setup_options(mdbx-static)
+ libmdbx_setup_libs(mdbx-static INTERFACE)
+@@ -576,7 +578,7 @@ endif()
+ # build shared library
+ if(MDBX_BUILD_SHARED_LIBRARY)
+ add_library(mdbx SHARED ${LIBMDBX_SOURCES})
+- set_target_properties(mdbx PROPERTIES PUBLIC_HEADER mdbx.h)
++ set_target_properties(mdbx PROPERTIES PUBLIC_HEADER "${LIBMDBX_PUBLIC_HEADERS}")
+ target_compile_definitions(mdbx PRIVATE LIBMDBX_EXPORTS MDBX_BUILD_SHARED_LIBRARY=1 INTERFACE LIBMDBX_IMPORTS)
+ target_setup_options(mdbx)
+ libmdbx_setup_libs(mdbx PRIVATE)
+--
+2.28.0
+
diff --git a/package/libmdbx/0003-mdbx-fix-obsolete-__noreturn.patch b/package/libmdbx/0003-mdbx-fix-obsolete-__noreturn.patch
new file mode 100644
index 0000000000..cb04334220
--- /dev/null
+++ b/package/libmdbx/0003-mdbx-fix-obsolete-__noreturn.patch
@@ -0,0 +1,27 @@
+From 280ed17ea2dff464c9688fcc92079f36d8b74621 Mon Sep 17 00:00:00 2001
+From: Leonid Yuriev <leo@yuriev.ru>
+Date: Sat, 3 Oct 2020 11:35:26 +0300
+Subject: [PATCH] mdbx: fix obsolete `__noreturn`.
+
+Change-Id: Ic78843d6f16de2a409c16ceecc7acb2ed8aa3e68
+Signed-off-by: Leonid Yuriev <leo@yuriev.ru>
+---
+ mdbx.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/mdbx.c b/mdbx.c
+index 04ea5140d..9212640fe 100644
+--- a/mdbx.c
++++ b/mdbx.c
+@@ -141,7 +141,7 @@ __extern_C void __assert(const char *, const char *, unsigned int, const char *)
+ #else
+ __nothrow
+ #endif /* __THROW */
+- __noreturn;
++ MDBX_NORETURN;
+ #define __assert_fail(assertion, file, line, function) \
+ __assert(assertion, file, line, function)
+
+--
+2.28.0
+
diff --git a/package/libmdbx/0004-mdbx-don-t-use-yield-instruction-on-ARM-if-unsupport.patch b/package/libmdbx/0004-mdbx-don-t-use-yield-instruction-on-ARM-if-unsupport.patch
new file mode 100644
index 0000000000..23f91d859b
--- /dev/null
+++ b/package/libmdbx/0004-mdbx-don-t-use-yield-instruction-on-ARM-if-unsupport.patch
@@ -0,0 +1,28 @@
+From 70b615e8d4d10cda2d961a815dd15eb87a1f3925 Mon Sep 17 00:00:00 2001
+From: Leonid Yuriev <leo@yuriev.ru>
+Date: Sun, 4 Oct 2020 14:54:11 +0300
+Subject: [PATCH] mdbx: don't use `yield` instruction on ARM if unsupported.
+
+Change-Id: I0b01d783fe4336b089f4b051fb61c203b5879aa5
+Signed-off-by: Leonid Yuriev <leo@yuriev.ru>
+---
+ mdbx.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/mdbx.c b/mdbx.c
+index aba445424..a9ba1ee85 100644
+--- a/mdbx.c
++++ b/mdbx.c
+@@ -763,7 +763,8 @@ static __always_inline void atomic_yield(void) {
+ #else
+ __asm__ __volatile__("hint @pause");
+ #endif
+-#elif defined(__arm__) || defined(__aarch64__)
++#elif defined(__aarch64__) || (defined(__ARM_ARCH) && __ARM_ARCH > 6) || \
++ defined(__ARM_ARCH_6K__)
+ #ifdef __CC_ARM
+ __yield();
+ #else
+--
+2.28.0
+
diff --git a/package/libmdbx/0005-mdbx-load-fix-minor-false-positive-GCC-warning.patch b/package/libmdbx/0005-mdbx-load-fix-minor-false-positive-GCC-warning.patch
new file mode 100644
index 0000000000..29d69e3faa
--- /dev/null
+++ b/package/libmdbx/0005-mdbx-load-fix-minor-false-positive-GCC-warning.patch
@@ -0,0 +1,27 @@
+From 8d4e7994c0c5c0cf69326139717e324f90bff65b Mon Sep 17 00:00:00 2001
+From: Leonid Yuriev <leo@yuriev.ru>
+Date: Mon, 5 Oct 2020 15:09:10 +0300
+Subject: [PATCH] mdbx-load: fix minor false-positive GCC warning.
+
+Change-Id: Ie75c793712d050e8d3da76a4d0a8df9b81dc5275
+Signed-off-by: Leonid Yuriev <leo@yuriev.ru>
+---
+ mdbx_load.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/mdbx_load.c b/mdbx_load.c
+index e5e72fc8f..54e179553 100644
+--- a/mdbx_load.c
++++ b/mdbx_load.c
+@@ -318,7 +318,7 @@ static int readhdr(void) {
+ }
+
+ for (int i = 0; dbflags[i].bit; i++) {
+- bool value;
++ bool value = false;
+ if (valbool(dbuf.iov_base, dbflags[i].name, &value)) {
+ if (value)
+ dbi_flags |= dbflags[i].bit;
+--
+2.28.0
+
diff --git a/package/libmdbx/0006-mdbx-cmake-pthread-workaround-for-buggy-toolchain-cm.patch b/package/libmdbx/0006-mdbx-cmake-pthread-workaround-for-buggy-toolchain-cm.patch
new file mode 100644
index 0000000000..37525cf0d5
--- /dev/null
+++ b/package/libmdbx/0006-mdbx-cmake-pthread-workaround-for-buggy-toolchain-cm.patch
@@ -0,0 +1,65 @@
+From 787eaaa373073e17f3a53658b085c255bc2c8ff8 Mon Sep 17 00:00:00 2001
+From: Leonid Yuriev <leo@yuriev.ru>
+Date: Mon, 5 Oct 2020 19:12:20 +0300
+Subject: [PATCH] mdbx-cmake: pthread workaround for buggy
+ toolchain/cmake/buildroot.
+
+Change-Id: I0d95e783abbd10a63cd1595a9de50593e814a967
+Signed-off-by: Leonid Yuriev <leo@yuriev.ru>
+---
+ CMakeLists.txt | 21 ++++++++++++++++++---
+ 1 file changed, 18 insertions(+), 3 deletions(-)
+
+diff --git a/CMakeLists.txt b/CMakeLists.txt
+index 95f116521..20a50a453 100644
+--- a/CMakeLists.txt
++++ b/CMakeLists.txt
+@@ -173,10 +173,27 @@ if(NOT CMAKE_BUILD_TYPE)
+ endif()
+ string(TOUPPER ${CMAKE_BUILD_TYPE} CMAKE_BUILD_TYPE_UPPERCASE)
+
++set(CMAKE_THREAD_PREFER_PTHREAD TRUE)
++set(THREADS_PREFER_PTHREAD_FLAG TRUE)
++find_package(Threads REQUIRED)
++
+ include(cmake/utils.cmake)
+ include(cmake/compiler.cmake)
+ include(cmake/profile.cmake)
+
++# Workaround for `-pthread` toolchain/cmake bug
++if(NOT APPLE AND NOT MSVC
++ AND CMAKE_USE_PTHREADS_INIT AND NOT CMAKE_THREAD_LIBS_INIT
++ AND (CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_CLANG))
++ check_compiler_flag("-pthread" CC_HAS_PTHREAD)
++ if(CC_HAS_PTHREAD AND NOT CMAKE_EXE_LINKER_FLAGS MATCHES "-pthread")
++ message(STATUS "Force add -pthread for linker flags to avoid troubles")
++ set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -pthread")
++ set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -pthread")
++ set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -pthread")
++ endif()
++endif()
++
+ CHECK_FUNCTION_EXISTS(pow NOT_NEED_LIBM)
+ if(NOT_NEED_LIBM)
+ set(LIB_MATH "")
+@@ -190,8 +207,6 @@ else()
+ endif()
+ endif()
+
+-find_package(Threads REQUIRED)
+-
+ if(SUBPROJECT)
+ if(NOT DEFINED BUILD_SHARED_LIBS)
+ option(BUILD_SHARED_LIBS "Build shared libraries (DLLs)" OFF)
+@@ -541,7 +556,7 @@ macro(target_setup_options TARGET)
+ endmacro()
+
+ macro(libmdbx_setup_libs TARGET MODE)
+- target_link_libraries(${TARGET} ${MODE} ${CMAKE_THREAD_LIBS_INIT})
++ target_link_libraries(${TARGET} ${MODE} Threads::Threads)
+ if(${CMAKE_SYSTEM_NAME} STREQUAL "Windows")
+ target_link_libraries(${TARGET} ${MODE} ntdll.lib)
+ if(MDBX_NTDLL_EXTRA_IMPLIB AND MDBX_AVOID_CRT)
+--
+2.28.0
+
diff --git a/package/libmdbx/0007-mdbx-fix-pthread_yield-for-non-GLIBC.patch b/package/libmdbx/0007-mdbx-fix-pthread_yield-for-non-GLIBC.patch
new file mode 100644
index 0000000000..5d7e83d4c7
--- /dev/null
+++ b/package/libmdbx/0007-mdbx-fix-pthread_yield-for-non-GLIBC.patch
@@ -0,0 +1,42 @@
+From 16d43332a9d28ba27aa3d127e8f6b77a87b2f5eb Mon Sep 17 00:00:00 2001
+From: Leonid Yuriev <leo@yuriev.ru>
+Date: Mon, 5 Oct 2020 21:08:09 +0300
+Subject: [PATCH] mdbx: fix `pthread_yield()` for non-GLIBC.
+
+Change-Id: I080e37a42b62e524896dea8747e9f23e2fcd584f
+Signed-off-by: Leonid Yuriev <leo@yuriev.ru>
+---
+ mdbx.c | 4 +++-
+ mdbx.c | 1 +
+ 2 files changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/mdbx.c b/mdbx.c
+index a9ba1ee85..ace6f2756 100644
+--- a/mdbx.c
++++ b/mdbx.c
+@@ -777,7 +777,9 @@ static __always_inline void atomic_yield(void) {
+ defined(__mips64__) || defined(_M_MRX000) || defined(_MIPS_) || \
+ defined(__MWERKS__) || defined(__sgi)
+ __asm__ __volatile__(".word 0x00000140");
+-#else
++#elif defined(__linux__) || defined(__gnu_linux__) || defined(_UNIX03_SOURCE)
++ sched_yield();
++#elif (defined(_GNU_SOURCE) && __GLIBC_PREREQ(2, 1)) || defined(_OPEN_THREADS)
+ pthread_yield();
+ #endif
+ }
+diff --git a/mdbx.c b/mdbx.c
+index 3509942dc..3af23ce0b 100644
+--- a/mdbx.c
++++ b/mdbx.c
+@@ -119,6 +119,7 @@
+
+ #if defined(__linux__) || defined(__gnu_linux__)
+ #include <linux/sysctl.h>
++#include <sched.h>
+ #include <sys/sendfile.h>
+ #include <sys/statfs.h>
+ #endif /* Linux */
+--
+2.28.0
+
diff --git a/package/libmdbx/Config.in b/package/libmdbx/Config.in
new file mode 100644
index 0000000000..dc36f12348
--- /dev/null
+++ b/package/libmdbx/Config.in
@@ -0,0 +1,42 @@
+config BR2_PACKAGE_LIBMDBX
+ bool "libmdbx"
+ depends on BR2_USE_MMU
+ depends on BR2_TOOLCHAIN_HAS_THREADS
+ depends on BR2_TOOLCHAIN_GCC_AT_LEAST_4_4
+ depends on BR2_TOOLCHAIN_HAS_SYNC_4
+ help
+ One of the fastest compact key-value ACID database
+ without WAL. libmdbx has a specific set of properties
+ and capabilities, focused on creating unique lightweight
+ solutions.
+
+ libmdbx surpasses the legendary LMDB in terms of
+ reliability, features and performance.
+
+ https://github.com/erthink/libmdbx
+
+if BR2_PACKAGE_LIBMDBX
+
+config BR2_PACKAGE_LIBMDBX_TOOLS
+ bool "install tools"
+ help
+ Install libmdbx tools for checking, dump, restore
+ and show statistics of databases.
+
+config BR2_PACKAGE_LIBMDBX_CXX
+ bool "C++ API"
+ depends on BR2_INSTALL_LIBSTDCPP
+ depends on BR2_TOOLCHAIN_GCC_AT_LEAST_4_8
+ help
+ Enable modern C++11/14/17/20 API for libmdbx.
+
+comment "libmdbx C++ support needs a toolchain w/ C++11, gcc >= 4.8"
+ depends on !BR2_INSTALL_LIBSTDCPP || \
+ !BR2_TOOLCHAIN_GCC_AT_LEAST_4_8
+
+endif
+
+comment "libmdbx needs a toolchain w/ threads, gcc >= 4.4"
+ depends on BR2_USE_MMU
+ depends on !BR2_TOOLCHAIN_HAS_THREADS || \
+ !BR2_TOOLCHAIN_GCC_AT_LEAST_4_4
diff --git a/package/libmdbx/libmdbx.hash b/package/libmdbx/libmdbx.hash
new file mode 100644
index 0000000000..f48cd81a7d
--- /dev/null
+++ b/package/libmdbx/libmdbx.hash
@@ -0,0 +1,2 @@
+sha256 310fe25c858a9515fc8c8d7d1f24a67c9496f84a91e0a0e41ea9975b1371e569 LICENSE
+sha256 c7fb24381eb4d92f2e2edc17e577cb721269683c816c6cca307c58f6f346e786 libmdbx-amalgamated-0.9.1.tar.gz
diff --git a/package/libmdbx/libmdbx.mk b/package/libmdbx/libmdbx.mk
new file mode 100644
index 0000000000..be0c2d7b06
--- /dev/null
+++ b/package/libmdbx/libmdbx.mk
@@ -0,0 +1,24 @@
+################################################################################
+#
+# libmdbx
+#
+################################################################################
+
+LIBMDBX_VERSION = 0.9.1
+LIBMDBX_SOURCE = libmdbx-amalgamated-$(LIBMDBX_VERSION).tar.gz
+LIBMDBX_SITE = https://github.com/erthink/libmdbx/releases/download/v$(LIBMDBX_VERSION)
+LIBMDBX_SUPPORTS_IN_SOURCE_BUILD = NO
+LIBMDBX_LICENSE = OLDAP-2.8
+LIBMDBX_LICENSE_FILES = LICENSE
+LIBMDBX_REDISTRIBUTE = YES
+LIBMDBX_STRIP_COMPONENTS = 0
+LIBMDBX_INSTALL_STAGING = YES
+
+LIBMDBX_CONF_OPTS = -DMDBX_INSTALL_MANPAGES=OFF -DBUILD_FOR_NATIVE_CPU=OFF \
+ -DMDBX_INSTALL_STATIC=$(if $(BR2_STATIC_LIBS),ON,OFF) \
+ -DMDBX_BUILD_SHARED_LIBRARY=$(if $(BR2_SHARED_LIBS),ON,OFF) \
+ -DMDBX_BUILD_CXX=$(if $(BR2_PACKAGE_LIBMDBX_CXX),ON,OFF) \
+ -DMDBX_BUILD_TOOLS=$(if $(BR2_PACKAGE_LIBMDBX_TOOLS),ON,OFF) \
+ -DMDBX_LINK_TOOLS_NONSTATIC=$(if $(BR2_SHARED_LIBS),ON,OFF)
+
+$(eval $(cmake-package))
--
2.28.0

34
src/bits.md Normal file
View File

@ -0,0 +1,34 @@
N | MASK | ENV | TXN | DB | PUT | DBI | NODE | PAGE |
--|---------|-----------|--------------|----------|-----------|------------|---------|----------|
0 |0000 0001| |TXN_FINISHED | | |DBI_DIRTY |F_BIGDATA|P_BRANCH
1 |0000 0002| |TXN_ERROR |REVERSEKEY| |DBI_STALE |F_SUBDATA|P_LEAF
2 |0000 0004| |TXN_DIRTY |DUPSORT | |DBI_FRESH |F_DUPDATA|P_OVERFLOW
3 |0000 0008| |TXN_SPILLS |INTEGERKEY| |DBI_CREAT | |P_META
4 |0000 0010| |TXN_HAS_CHILD |DUPFIXED |NOOVERWRITE|DBI_VALID | |P_DIRTY
5 |0000 0020| | |INTEGERDUP|NODUPDATA |DBI_USRVALID| |P_LEAF2
6 |0000 0040| | |REVERSEDUP|CURRENT |DBI_DUPDATA | |P_SUBP
7 |0000 0080| | | |ALLDUPS |DBI_AUDITED | |
8 |0000 0100| | | | | | |
9 |0000 0200| | | | | | |
10|0000 0400| | | | | | |
11|0000 0800| | | | | | |
12|0000 1000| | | | | | |
13|0000 2000| | | | | | |
14|0000 4000|NOSUBDIR | | | | | |P_LOOSE
15|0000 8000| | |DB_VALID | | | |P_KEEP
16|0001 0000|SAFE_NOSYNC|TXN_NOSYNC | |RESERVE | |RESERVE |
17|0002 0000|RDONLY |TXN_RDONLY | |APPEND | |APPEND |
18|0004 0000|NOMETASYNC |TXN_NOMETASYNC|CREATE |APPENDDUP
19|0008 0000|WRITEMAP |<= | |MULTIPLE
20|0010 0000|UTTERLY | |
21|0020 0000|NOTLS |<= |
22|0040 0000|EXCLUSIVE | |
23|0080 0000|NORDAHEAD | |
24|0100 0000|NOMEMINIT |TXN_PREPARE |
25|0200 0000|COALESCE | |
26|0400 0000|LIFORECLAIM| |
27|0800 0000|PAGEPERTURB| |
28|1000 0000|ENV_TXKEY |TXN_TRY |
29|2000 0000|ENV_ACTIVE | |
30|4000 0000|ACCEDE |SHRINK_ALLOWED|DB_ACCEDE
31|8000 0000|FATAL_ERROR| |

File diff suppressed because it is too large Load Diff

View File

@ -16,6 +16,11 @@
#include MDBX_CONFIG_H
#endif
#define LIBMDBX_INTERNALS
#ifdef MDBX_TOOLS
#define MDBX_DEPRECATED
#endif /* MDBX_TOOLS */
/* *INDENT-OFF* */
/* clang-format off */
@ -96,11 +101,6 @@
#pragma warning(disable : 4505) /* unreferenced local function has been removed */
#endif /* _MSC_VER (warnings) */
#if defined(MDBX_TOOLS)
#undef MDBX_DEPRECATED
#define MDBX_DEPRECATED
#endif /* MDBX_TOOLS */
#include "../mdbx.h"
#include "defs.h"
@ -287,7 +287,7 @@ typedef struct MDBX_db {
pgno_t md_overflow_pages; /* number of overflow pages */
uint64_t md_seq; /* table sequence counter */
uint64_t md_entries; /* number of data items */
uint64_t md_mod_txnid; /* txnid of last commited modification */
uint64_t md_mod_txnid; /* txnid of last committed modification */
} MDBX_db;
/* database size-related parameters */
@ -619,7 +619,7 @@ typedef struct MDBX_lockinfo {
#if defined(_WIN32) || defined(_WIN64)
#define MAX_MAPSIZE32 UINT32_C(0x38000000)
#else
#define MAX_MAPSIZE32 UINT32_C(0x7ff80000)
#define MAX_MAPSIZE32 UINT32_C(0x7f000000)
#endif
#define MAX_MAPSIZE64 (MAX_PAGENO * (uint64_t)MAX_PAGESIZE)
@ -943,7 +943,7 @@ struct MDBX_env {
#define me_lfd me_lck_mmap.fd
#define me_lck me_lck_mmap.lck
unsigned me_psize; /* DB page size, inited from me_os_psize */
unsigned me_psize; /* DB page size, initialized from me_os_psize */
uint8_t me_psize2log; /* log2 of DB page size */
int8_t me_stuck_meta; /* recovery-only: target meta page or less that zero */
unsigned me_os_psize; /* OS page size, from mdbx_syspagesize() */
@ -953,7 +953,7 @@ struct MDBX_env {
MDBX_dbi me_maxdbs; /* size of the DB table */
uint32_t me_pid; /* process ID of this env */
mdbx_thread_key_t me_txkey; /* thread-key for readers */
char *me_path; /* path to the DB files */
char *me_pathname; /* path to the DB files */
void *me_pbuf; /* scratch area for DUPSORT put() */
MDBX_txn *me_txn; /* current write transaction */
MDBX_txn *me_txn0; /* prealloc'd write transaction */

View File

@ -190,6 +190,14 @@ static int lck_op(mdbx_filehandle_t fd, int cmd, int lck, off_t offset,
}
}
MDBX_INTERNAL_FUNC int mdbx_lockfile(mdbx_filehandle_t fd, bool wait) {
#if MDBX_USE_OFDLOCKS
if (unlikely(op_setlk == 0))
choice_fcntl();
#endif /* MDBX_USE_OFDLOCKS */
return lck_op(fd, wait ? op_setlkw : op_setlk, F_WRLCK, 0, OFF_T_MAX);
}
MDBX_INTERNAL_FUNC int mdbx_rpid_set(MDBX_env *env) {
assert(env->me_lfd != INVALID_HANDLE_VALUE);
assert(env->me_pid > 0);

View File

@ -204,6 +204,15 @@ MDBX_INTERNAL_FUNC void mdbx_rdt_unlock(MDBX_env *env) {
mdbx_srwlock_ReleaseShared(&env->me_remap_guard);
}
MDBX_INTERNAL_FUNC int mdbx_lockfile(mdbx_filehandle_t fd, bool wait) {
return flock(fd,
wait ? LCK_EXCLUSIVE | LCK_WAITFOR
: LCK_EXCLUSIVE | LCK_DONTWAIT,
0, LCK_MAXLEN)
? MDBX_SUCCESS
: GetLastError();
}
static int suspend_and_append(mdbx_handle_array_t **array,
const DWORD ThreadId) {
const unsigned limit = (*array)->limit;

View File

@ -1119,6 +1119,12 @@ path env::get_path() const {
return pchar_to_path<path>(c_str);
}
bool env::remove(const path &pathname, const remove_mode mode) {
const path_to_pchar<path> utf8(pathname);
return error::boolean_or_throw(
::mdbx_env_delete(utf8, MDBX_env_delete_mode_t(mode)));
}
//------------------------------------------------------------------------------
static inline MDBX_env *create_env() {

View File

@ -678,7 +678,7 @@ int main(int argc, char *argv[]) {
if (present_sequence > sequence) {
fprintf(stderr,
"present sequence for '%s' value (%" PRIu64
") is greated than loaded (%" PRIu64 ")\n",
") is greater than loaded (%" PRIu64 ")\n",
dbi_name, present_sequence, sequence);
rc = MDBX_RESULT_TRUE;
goto txn_abort;

View File

@ -521,6 +521,20 @@ MDBX_INTERNAL_FUNC int mdbx_removefile(const char *pathname) {
#endif
}
MDBX_INTERNAL_FUNC int mdbx_removedirectory(const char *pathname) {
#if defined(_WIN32) || defined(_WIN64)
const size_t wlen = mbstowcs(nullptr, pathname, INT_MAX);
if (wlen < 1 || wlen > /* MAX_PATH */ INT16_MAX)
return ERROR_INVALID_NAME;
wchar_t *const pathnameW = _alloca((wlen + 1) * sizeof(wchar_t));
if (wlen != mbstowcs(pathnameW, pathname, wlen + 1))
return ERROR_INVALID_NAME;
return RemoveDirectoryW(pathnameW) ? MDBX_SUCCESS : GetLastError();
#else
return rmdir(pathname) ? errno : MDBX_SUCCESS;
#endif
}
MDBX_INTERNAL_FUNC int mdbx_openfile(const enum mdbx_openfile_purpose purpose,
const MDBX_env *env, const char *pathname,
mdbx_filehandle_t *fd,
@ -571,6 +585,12 @@ MDBX_INTERNAL_FUNC int mdbx_openfile(const enum mdbx_openfile_purpose purpose,
FlagsAndAttributes |=
(env->me_psize < env->me_os_psize) ? 0 : FILE_FLAG_NO_BUFFERING;
break;
case MDBX_OPEN_DELETE:
CreationDisposition = OPEN_EXISTING;
ShareMode |= FILE_SHARE_DELETE;
DesiredAccess =
FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES | DELETE | SYNCHRONIZE;
break;
}
*fd = CreateFileW(pathnameW, DesiredAccess, ShareMode, NULL,
@ -619,6 +639,9 @@ MDBX_INTERNAL_FUNC int mdbx_openfile(const enum mdbx_openfile_purpose purpose,
flags |= O_FSYNC;
#endif
break;
case MDBX_OPEN_DELETE:
flags = O_RDWR;
break;
}
const bool direct_nocache_for_copy =

View File

@ -283,7 +283,7 @@ typedef pthread_mutex_t mdbx_fastmutex_t;
defined(__amd64__) || defined(__amd64) || defined(_M_X64) || \
defined(_M_AMD64) || defined(__IA32__) || defined(__INTEL__)
#ifndef __ia32__
/* LY: define neutral __ia32__ for x86 and x86-64 archs */
/* LY: define neutral __ia32__ for x86 and x86-64 */
#define __ia32__ 1
#endif /* __ia32__ */
#if !defined(__amd64__) && (defined(__x86_64) || defined(__x86_64__) || \
@ -459,6 +459,35 @@ typedef union MDBX_srwlock {
#ifdef __cplusplus
extern void mdbx_osal_jitter(bool tiny);
#else
/*----------------------------------------------------------------------------*/
/* Atomics */
#if defined(__cplusplus) && !defined(__STDC_NO_ATOMICS__) && __has_include(<cstdatomic>)
#include <cstdatomic>
#elif !defined(__cplusplus) && (__STDC_VERSION__ >= 201112L) && \
!defined(__STDC_NO_ATOMICS__) && \
(__GNUC_PREREQ(4, 9) || __CLANG_PREREQ(3, 8) || \
!(defined(__GNUC__) || defined(__clang__)))
#include <stdatomic.h>
#elif defined(__GNUC__) || defined(__clang__)
/* LY: nothing required */
#elif defined(_MSC_VER)
#pragma warning(disable : 4163) /* 'xyz': not available as an intrinsic */
#pragma warning(disable : 4133) /* 'function': incompatible types - from \
'size_t' to 'LONGLONG' */
#pragma warning(disable : 4244) /* 'return': conversion from 'LONGLONG' to \
'std::size_t', possible loss of data */
#pragma warning(disable : 4267) /* 'function': conversion from 'size_t' to \
'long', possible loss of data */
#pragma intrinsic(_InterlockedExchangeAdd, _InterlockedCompareExchange)
#pragma intrinsic(_InterlockedExchangeAdd64, _InterlockedCompareExchange64)
#elif defined(__APPLE__)
#include <libkern/OSAtomic.h>
#else
#error FIXME atomic-ops
#endif
/*----------------------------------------------------------------------------*/
/* Memory/Compiler barriers, cache coherence */
@ -500,8 +529,8 @@ static __maybe_unused __inline void mdbx_compiler_barrier(void) {
}
static __maybe_unused __inline void mdbx_memory_barrier(void) {
#if __has_extension(c_atomic) || __has_extension(cxx_atomic)
__c11_atomic_thread_fence(__ATOMIC_SEQ_CST);
#if __has_extension(c_atomic) && !defined(__STDC_NO_ATOMICS__)
atomic_thread_fence(__ATOMIC_SEQ_CST);
#elif defined(__ATOMIC_SEQ_CST)
__atomic_thread_fence(__ATOMIC_SEQ_CST);
#elif defined(__clang__) || defined(__GNUC__)
@ -626,7 +655,8 @@ enum mdbx_openfile_purpose {
MDBX_OPEN_DXB_LAZY = 1,
MDBX_OPEN_DXB_DSYNC = 2,
MDBX_OPEN_LCK = 3,
MDBX_OPEN_COPY = 4
MDBX_OPEN_COPY = 4,
MDBX_OPEN_DELETE = 5
};
MDBX_INTERNAL_FUNC int mdbx_openfile(const enum mdbx_openfile_purpose purpose,
@ -635,7 +665,9 @@ MDBX_INTERNAL_FUNC int mdbx_openfile(const enum mdbx_openfile_purpose purpose,
mdbx_mode_t unix_mode_bits);
MDBX_INTERNAL_FUNC int mdbx_closefile(mdbx_filehandle_t fd);
MDBX_INTERNAL_FUNC int mdbx_removefile(const char *pathname);
MDBX_INTERNAL_FUNC int mdbx_removedirectory(const char *pathname);
MDBX_INTERNAL_FUNC int mdbx_is_pipe(mdbx_filehandle_t fd);
MDBX_INTERNAL_FUNC int mdbx_lockfile(mdbx_filehandle_t fd, bool wait);
#define MMAP_OPTION_TRUNCATE 1
#define MMAP_OPTION_SEMAPHORE 2
@ -895,32 +927,6 @@ MDBX_INTERNAL_VAR MDBX_RegGetValueA mdbx_RegGetValueA;
#endif /* Windows */
/*----------------------------------------------------------------------------*/
/* Atomics */
#if !defined(__cplusplus) && (__STDC_VERSION__ >= 201112L) && \
!defined(__STDC_NO_ATOMICS__) && \
(__GNUC_PREREQ(4, 9) || __CLANG_PREREQ(3, 8) || \
!(defined(__GNUC__) || defined(__clang__)))
#include <stdatomic.h>
#elif defined(__GNUC__) || defined(__clang__)
/* LY: nothing required */
#elif defined(_MSC_VER)
#pragma warning(disable : 4163) /* 'xyz': not available as an intrinsic */
#pragma warning(disable : 4133) /* 'function': incompatible types - from \
'size_t' to 'LONGLONG' */
#pragma warning(disable : 4244) /* 'return': conversion from 'LONGLONG' to \
'std::size_t', possible loss of data */
#pragma warning(disable : 4267) /* 'function': conversion from 'size_t' to \
'long', possible loss of data */
#pragma intrinsic(_InterlockedExchangeAdd, _InterlockedCompareExchange)
#pragma intrinsic(_InterlockedExchangeAdd64, _InterlockedCompareExchange64)
#elif defined(__APPLE__)
#include <libkern/OSAtomic.h>
#else
#error FIXME atomic-ops
#endif
#endif /* !__cplusplus */
/*----------------------------------------------------------------------------*/

View File

@ -43,8 +43,8 @@ bool testcase_append::run() {
uint64_t serial_count = 0;
unsigned txn_nops = 0;
uint64_t commited_inserted_number = inserted_number;
simple_checksum commited_inserted_checksum = inserted_checksum;
uint64_t committed_inserted_number = inserted_number;
simple_checksum committed_inserted_checksum = inserted_checksum;
while (should_continue()) {
const keygen::serial_t serial = serial_count;
if (!keyvalue_maker.increment(serial_count, 1)) {
@ -64,8 +64,8 @@ bool testcase_append::run() {
if (err == MDBX_MAP_FULL && config.params.ignore_dbfull) {
log_notice("append: bailout-insert due '%s'", mdbx_strerror(err));
txn_end(true);
inserted_number = commited_inserted_number;
inserted_checksum = commited_inserted_checksum;
inserted_number = committed_inserted_number;
inserted_checksum = committed_inserted_checksum;
break;
}
@ -89,12 +89,12 @@ bool testcase_append::run() {
err = breakable_restart();
if (unlikely(err != MDBX_SUCCESS)) {
log_notice("append: bailout-commit due '%s'", mdbx_strerror(err));
inserted_number = commited_inserted_number;
inserted_checksum = commited_inserted_checksum;
inserted_number = committed_inserted_number;
inserted_checksum = committed_inserted_checksum;
break;
}
commited_inserted_number = inserted_number;
commited_inserted_checksum = inserted_checksum;
committed_inserted_number = inserted_number;
committed_inserted_checksum = inserted_checksum;
txn_nops = 0;
}
@ -105,8 +105,8 @@ bool testcase_append::run() {
err = breakable_commit();
if (unlikely(err != MDBX_SUCCESS)) {
log_notice("append: bailout-commit due '%s'", mdbx_strerror(err));
inserted_number = commited_inserted_number;
inserted_checksum = commited_inserted_checksum;
inserted_number = committed_inserted_number;
inserted_checksum = committed_inserted_checksum;
}
}
//----------------------------------------------------------------------------

View File

@ -1,8 +1,8 @@
#include "test.h"
void testcase_copy::copy_db(const bool with_compaction) {
int err = osal_removefile(copy_pathname);
if (err != MDBX_SUCCESS && err != MDBX_ENOFILE)
int err = mdbx_env_delete(copy_pathname.c_str(), MDBX_ENV_JUST_DELETE);
if (err != MDBX_SUCCESS && err != MDBX_RESULT_TRUE)
failure_perror("mdbx_removefile()", err);
err = mdbx_env_copy(db_guard.get(), copy_pathname.c_str(),

View File

@ -21,7 +21,7 @@ bool testcase_hill::run() {
return false;
}
speculum.clear();
speculum_commited.clear();
speculum_committed.clear();
/* LY: тест "холмиком":
* - сначала наполняем таблицу циклическими CRUD-манипуляциями,
@ -62,7 +62,7 @@ bool testcase_hill::run() {
: MDBX_NODUPDATA;
uint64_t serial_count = 0;
uint64_t commited_serial = serial_count;
uint64_t committed_serial = serial_count;
unsigned txn_nops = 0;
bool rc = false;
@ -87,8 +87,8 @@ bool testcase_hill::run() {
if (err == MDBX_MAP_FULL && config.params.ignore_dbfull) {
log_notice("uphill: bailout at insert-a due '%s'", mdbx_strerror(err));
txn_restart(true, false);
serial_count = commited_serial;
speculum = speculum_commited;
serial_count = committed_serial;
speculum = speculum_committed;
break;
}
failure_perror("mdbx_put(insert-a.1)", err);
@ -102,12 +102,12 @@ bool testcase_hill::run() {
err = breakable_restart();
if (unlikely(err != MDBX_SUCCESS)) {
log_notice("uphill: bailout at commit due '%s'", mdbx_strerror(err));
serial_count = commited_serial;
speculum = speculum_commited;
serial_count = committed_serial;
speculum = speculum_committed;
break;
}
speculum_commited = speculum;
commited_serial = a_serial;
speculum_committed = speculum;
committed_serial = a_serial;
txn_nops = 0;
if (!speculum_verify()) {
log_notice("uphill: bailout after insert-a, after commit");
@ -123,8 +123,8 @@ bool testcase_hill::run() {
if (err == MDBX_MAP_FULL && config.params.ignore_dbfull) {
log_notice("uphill: bailout at insert-b due '%s'", mdbx_strerror(err));
txn_restart(true, false);
serial_count = commited_serial;
speculum = speculum_commited;
serial_count = committed_serial;
speculum = speculum_committed;
break;
}
failure_perror("mdbx_put(insert-b)", err);
@ -138,12 +138,12 @@ bool testcase_hill::run() {
err = breakable_restart();
if (unlikely(err != MDBX_SUCCESS)) {
log_notice("uphill: bailout at commit due '%s'", mdbx_strerror(err));
serial_count = commited_serial;
speculum = speculum_commited;
serial_count = committed_serial;
speculum = speculum_committed;
break;
}
speculum_commited = speculum;
commited_serial = a_serial;
speculum_committed = speculum;
committed_serial = a_serial;
txn_nops = 0;
if (!speculum_verify()) {
log_notice("uphill: bailout after insert-b, after commit");
@ -161,8 +161,8 @@ bool testcase_hill::run() {
if (err == MDBX_MAP_FULL && config.params.ignore_dbfull) {
log_notice("uphill: bailout at update-a due '%s'", mdbx_strerror(err));
txn_restart(true, false);
serial_count = commited_serial;
speculum = speculum_commited;
serial_count = committed_serial;
speculum = speculum_committed;
break;
}
failure_perror("mdbx_replace(update-a: 1->0)", err);
@ -176,12 +176,12 @@ bool testcase_hill::run() {
err = breakable_restart();
if (unlikely(err != MDBX_SUCCESS)) {
log_notice("uphill: bailout at commit due '%s'", mdbx_strerror(err));
serial_count = commited_serial;
speculum = speculum_commited;
serial_count = committed_serial;
speculum = speculum_committed;
break;
}
speculum_commited = speculum;
commited_serial = a_serial;
speculum_committed = speculum;
committed_serial = a_serial;
txn_nops = 0;
if (!speculum_verify()) {
log_notice("uphill: bailout after update-a, after commit");
@ -197,8 +197,8 @@ bool testcase_hill::run() {
if (err == MDBX_MAP_FULL && config.params.ignore_dbfull) {
log_notice("uphill: bailout at delete-b due '%s'", mdbx_strerror(err));
txn_restart(true, false);
serial_count = commited_serial;
speculum = speculum_commited;
serial_count = committed_serial;
speculum = speculum_committed;
break;
}
failure_perror("mdbx_del(b)", err);
@ -212,12 +212,12 @@ bool testcase_hill::run() {
err = breakable_restart();
if (unlikely(err != MDBX_SUCCESS)) {
log_notice("uphill: bailout at commit due '%s'", mdbx_strerror(err));
serial_count = commited_serial;
speculum = speculum_commited;
serial_count = committed_serial;
speculum = speculum_committed;
break;
}
speculum_commited = speculum;
commited_serial = a_serial;
speculum_committed = speculum;
committed_serial = a_serial;
txn_nops = 0;
if (!speculum_verify()) {
log_notice("uphill: bailout after delete-b, after commit");
@ -296,7 +296,7 @@ bool testcase_hill::run() {
log_notice("downhill: bailout at update-a due '%s'",
mdbx_strerror(err));
txn_end(true);
speculum = speculum_commited;
speculum = speculum_committed;
break;
}
failure_perror("mdbx_put(update-a: 0->1)", err);
@ -310,10 +310,10 @@ bool testcase_hill::run() {
err = breakable_restart();
if (unlikely(err != MDBX_SUCCESS)) {
log_notice("downhill: bailout at commit due '%s'", mdbx_strerror(err));
speculum = speculum_commited;
speculum = speculum_committed;
break;
}
speculum_commited = speculum;
speculum_committed = speculum;
txn_nops = 0;
if (!speculum_verify()) {
log_notice("downhill: bailout after update-a, after commit");
@ -330,7 +330,7 @@ bool testcase_hill::run() {
log_notice("downhill: bailout at insert-a due '%s'",
mdbx_strerror(err));
txn_end(true);
speculum = speculum_commited;
speculum = speculum_committed;
break;
}
failure_perror("mdbx_put(insert-b)", err);
@ -344,10 +344,10 @@ bool testcase_hill::run() {
err = breakable_restart();
if (unlikely(err != MDBX_SUCCESS)) {
log_notice("downhill: bailout at commit due '%s'", mdbx_strerror(err));
speculum = speculum_commited;
speculum = speculum_committed;
break;
}
speculum_commited = speculum;
speculum_committed = speculum;
txn_nops = 0;
if (!speculum_verify()) {
log_notice("downhill: bailout after insert-b, after commit");
@ -365,7 +365,7 @@ bool testcase_hill::run() {
log_notice("downhill: bailout at delete-a due '%s'",
mdbx_strerror(err));
txn_end(true);
speculum = speculum_commited;
speculum = speculum_committed;
break;
}
failure_perror("mdbx_del(a)", err);
@ -379,10 +379,10 @@ bool testcase_hill::run() {
err = breakable_restart();
if (unlikely(err != MDBX_SUCCESS)) {
log_notice("downhill: bailout at commit due '%s'", mdbx_strerror(err));
speculum = speculum_commited;
speculum = speculum_committed;
break;
}
speculum_commited = speculum;
speculum_committed = speculum;
txn_nops = 0;
if (!speculum_verify()) {
log_notice("downhill: bailout after delete-a, after commit");
@ -399,7 +399,7 @@ bool testcase_hill::run() {
log_notice("downhill: bailout at delete-b due '%s'",
mdbx_strerror(err));
txn_end(true);
speculum = speculum_commited;
speculum = speculum_committed;
break;
}
failure_perror("mdbx_del(b)", err);
@ -413,10 +413,10 @@ bool testcase_hill::run() {
err = breakable_restart();
if (unlikely(err != MDBX_SUCCESS)) {
log_notice("downhill: bailout at commit due '%s'", mdbx_strerror(err));
speculum = speculum_commited;
speculum = speculum_committed;
break;
}
speculum_commited = speculum;
speculum_committed = speculum;
txn_nops = 0;
if (!speculum_verify()) {
log_notice("downhill: bailout after delete-b, after commit");

View File

@ -212,24 +212,9 @@ std::string thunk_param(const actor_config &config) {
void cleanup() {
log_trace(">> cleanup");
const int is_dir =
#if defined(_WIN32) || defined(_WIN64)
ERROR_ACCESS_DENIED /* Windows API is mad */;
#else
EISDIR;
#endif
for (const auto &db_path : global::databases) {
int err = osal_removefile(db_path);
if (err == is_dir) {
err = osal_removefile(db_path + MDBX_LOCKNAME);
if (err == MDBX_SUCCESS || err == MDBX_ENOFILE)
err = osal_removefile(db_path + MDBX_DATANAME);
if (err == MDBX_SUCCESS || err == MDBX_ENOFILE)
err = osal_removedirectory(db_path);
} else if (err == MDBX_SUCCESS || err == MDBX_ENOFILE)
err = osal_removefile(db_path + MDBX_LOCK_SUFFIX);
if (err != MDBX_SUCCESS && err != MDBX_ENOFILE)
int err = mdbx_env_delete(db_path.c_str(), MDBX_ENV_JUST_DELETE);
if (err != MDBX_SUCCESS && err != MDBX_RESULT_TRUE)
failure_perror(db_path.c_str(), err);
}
log_trace("<< cleanup");

View File

@ -92,7 +92,7 @@ bool testcase_nested::pop_txn(bool abort) {
assert(txn_guard && !stack.empty());
bool should_continue = true;
MDBX_txn *txn = txn_guard.release();
bool commited = false;
bool committed = false;
if (abort) {
log_verbose(
"abort level#%zu txn #%" PRIu64 ", undo serial %" PRIu64 " <- %" PRIu64,
@ -105,7 +105,7 @@ bool testcase_nested::pop_txn(bool abort) {
stack.size(), serial, std::get<1>(stack.top()));
int err = mdbx_txn_commit(txn);
if (likely(err == MDBX_SUCCESS))
commited = true;
committed = true;
else {
should_continue = false;
if (err == MDBX_MAP_FULL && config.params.ignore_dbfull) {
@ -119,7 +119,7 @@ bool testcase_nested::pop_txn(bool abort) {
}
std::swap(txn_guard, std::get<0>(stack.top()));
if (!commited) {
if (!committed) {
serial = std::get<1>(stack.top());
std::swap(fifo, std::get<2>(stack.top()));
std::swap(speculum, std::get<3>(stack.top()));

View File

@ -164,7 +164,7 @@ void osal_setup(const std::vector<actor_config> &actors) {
,
-1, 0);
if (MAP_FAILED == (void *)shared)
failure_perror("mmap(shared_conds)", errno);
failure_perror("mmap(shared)", errno);
shared->count = actors.size() + 1;
@ -531,12 +531,4 @@ std::string osal_tempdir(void) {
return "";
}
int osal_removefile(const std::string &pathname) {
return unlink(pathname.c_str()) ? errno : MDBX_SUCCESS;
}
int osal_removedirectory(const std::string &pathname) {
return rmdir(pathname.c_str()) ? errno : MDBX_SUCCESS;
}
#endif /* !Windows */

View File

@ -452,12 +452,4 @@ std::string osal_tempdir(void) {
return std::string(buf, len);
}
int osal_removefile(const std::string &pathname) {
return DeleteFileA(pathname.c_str()) ? MDBX_SUCCESS : GetLastError();
}
int osal_removedirectory(const std::string &pathname) {
return RemoveDirectoryA(pathname.c_str()) ? MDBX_SUCCESS : GetLastError();
}
#endif /* Windows */

View File

@ -34,8 +34,6 @@ void osal_udelay(unsigned us);
void osal_yield(void);
bool osal_istty(int fd);
std::string osal_tempdir(void);
int osal_removefile(const std::string &pathname);
int osal_removedirectory(const std::string &pathname);
#ifdef _MSC_VER
#ifndef STDIN_FILENO

View File

@ -207,9 +207,9 @@ int testcase::breakable_commit() {
if (need_speculum_assign) {
need_speculum_assign = false;
if (unlikely(rc != MDBX_SUCCESS))
speculum = speculum_commited;
speculum = speculum_committed;
else
speculum_commited = speculum;
speculum_committed = speculum;
}
log_trace("<< txn_commit: %s", rc ? "failed" : "Ok");
@ -240,14 +240,14 @@ void testcase::txn_end(bool abort) {
if (unlikely(err != MDBX_SUCCESS))
failure_perror("mdbx_txn_abort()", err);
if (need_speculum_assign)
speculum = speculum_commited;
speculum = speculum_committed;
} else {
txn_inject_writefault(txn);
int err = mdbx_txn_commit(txn);
if (unlikely(err != MDBX_SUCCESS))
failure_perror("mdbx_txn_commit()", err);
if (need_speculum_assign)
speculum_commited = speculum;
speculum_committed = speculum;
}
log_trace("<< txn_end(%s)", abort ? "abort" : "commit");
@ -615,13 +615,13 @@ bool test_execute(const actor_config &config_const) {
}
if (config.params.nrepeat == 1)
log_verbose("test successed");
log_verbose("test successfully");
else {
if (config.params.nrepeat)
log_verbose("test successed (iteration %zi of %zi)", iter,
log_verbose("test successfully (iteration %zi of %zi)", iter,
size_t(config.params.nrepeat));
else
log_verbose("test successed (iteration %zi)", iter);
log_verbose("test successfully (iteration %zi)", iter);
config.params.keygen.seed += INT32_C(0xA4F4D37B);
}

View File

@ -158,7 +158,7 @@ protected:
MDBX_canary canary;
} last;
SET speculum{ItemCompare(this)}, speculum_commited{ItemCompare(this)};
SET speculum{ItemCompare(this)}, speculum_committed{ItemCompare(this)};
bool speculum_verify();
int insert(const keygen::buffer &akey, const keygen::buffer &adata,
MDBX_put_flags_t flags);