mdbx: добавление mdbx_txn_release_all_cursors() в API.

This commit is contained in:
Леонид Юрьев (Leonid Yuriev) 2023-10-13 22:38:51 +03:00
parent d28a397b2d
commit 4d3f7e1edc
3 changed files with 63 additions and 0 deletions

21
mdbx.h
View File

@ -4803,6 +4803,27 @@ LIBMDBX_API int mdbx_cursor_open(MDBX_txn *txn, MDBX_dbi dbi,
* or \ref mdbx_cursor_create(). */
LIBMDBX_API void mdbx_cursor_close(MDBX_cursor *cursor);
/** \brief Unbind or closes all cursors of a given transaction.
* \ingroup c_cursors
*
* Unbinds either closes all cursors associated (opened or renewed) with
* a given transaction in a bulk with minimal overhead.
*
* \see mdbx_cursor_unbind()
* \see mdbx_cursor_close()
*
* \param [in] txn A transaction handle returned by \ref mdbx_txn_begin().
* \param [in] unbind If non-zero, unbinds cursors and leaves ones reusable.
* Otherwise close and dispose cursors.
*
* \returns A negative error value on failure or the number of closed cursors
* on success, some possible errors are:
* \retval MDBX_THREAD_MISMATCH Given transaction is not owned
* by current thread.
* \retval MDBX_BAD_TXN Given transaction is invalid or has
* a child/nested transaction transaction. */
LIBMDBX_API int mdbx_txn_release_all_cursors(const MDBX_txn *txn, bool unbind);
/** \brief Renew a cursor handle for use within the given transaction.
* \ingroup c_cursors
*

View File

@ -3841,6 +3841,15 @@ public:
/// \brief Opens cursor for specified key-value map handle.
inline cursor_managed open_cursor(map_handle map);
/// \brief Unbind or close all cursors.
inline size_t release_all_cursors(bool unbind) const;
/// \brief Close all cursors.
inline size_t close_all_cursors() const { return release_all_cursors(false); }
/// \brief Unbind all cursors.
inline size_t unbind_all_cursors() const { return release_all_cursors(true); }
/// \brief Open existing key-value map.
inline map_handle open_map(
const char *name,
@ -5466,6 +5475,13 @@ inline cursor_managed txn::open_cursor(map_handle map) {
return cursor_managed(ptr);
}
inline size_t txn::release_all_cursors(bool unbind) const {
int err = ::mdbx_txn_release_all_cursors(handle_, unbind);
if (MDBX_UNLIKELY(err < 0))
MDBX_CXX20_UNLIKELY error::throw_exception(err);
return size_t(err);
}
inline ::mdbx::map_handle
txn::open_map(const char *name, const ::mdbx::key_mode key_mode,
const ::mdbx::value_mode value_mode) const {

View File

@ -19019,6 +19019,32 @@ void mdbx_cursor_close(MDBX_cursor *mc) {
}
}
int mdbx_txn_release_all_cursors(const MDBX_txn *txn, bool unbind) {
int rc = check_txn(txn, MDBX_TXN_FINISHED | MDBX_TXN_HAS_CHILD);
if (likely(rc == MDBX_SUCCESS)) {
for (size_t i = FREE_DBI; i < txn->mt_numdbs; ++i) {
while (txn->mt_cursors[i]) {
MDBX_cursor *mc = txn->mt_cursors[i];
ENSURE(NULL, mc->mc_signature == MDBX_MC_LIVE &&
(mc->mc_flags & C_UNTRACK) && !mc->mc_backup);
rc = likely(rc < INT_MAX) ? rc + 1 : rc;
txn->mt_cursors[i] = mc->mc_next;
if (unbind) {
mc->mc_signature = MDBX_MC_READY4CLOSE;
mc->mc_flags = 0;
} else {
mc->mc_signature = 0;
mc->mc_next = mc;
osal_free(mc);
}
}
}
} else {
eASSERT(nullptr, rc < 0);
}
return rc;
}
MDBX_txn *mdbx_cursor_txn(const MDBX_cursor *mc) {
if (unlikely(!mc || mc->mc_signature != MDBX_MC_LIVE))
return NULL;