From 94a2abaf31a293fb3eddc7fe3b61a1d846a60a0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9B=D0=B5=D0=BE=D0=BD=D0=B8=D0=B4=20=D0=AE=D1=80=D1=8C?= =?UTF-8?q?=D0=B5=D0=B2=20=28Leonid=20Yuriev=29?= Date: Tue, 4 Mar 2025 14:45:13 +0300 Subject: [PATCH] =?UTF-8?q?mdbx:=20=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=B2=20API=20`mdbx=5Ftxn=5Frelease?= =?UTF-8?q?=5Fall=5Fcursors=5Fex()`=20=D0=B8=20=D0=B8=D0=B7=D0=BC=D0=B5?= =?UTF-8?q?=D0=BD=D0=B5=D0=BD=D0=B8=D0=B5=20=D1=81=D0=B5=D0=BC=D0=B0=D0=BD?= =?UTF-8?q?=D1=82=D0=B8=D0=BA=D0=B8=20=D1=80=D0=B5=D0=B7=D1=83=D0=BB=D1=8C?= =?UTF-8?q?=D1=82=D0=B0=D1=82=D0=B0=20`mdbx=5Ftxn=5Frelease=5Fall=5Fcursor?= =?UTF-8?q?s()`=20(backport).?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit По недосмотру в выпусках остался предварительный/черновой вариант функции mdbx_txn_release_all_cursors(), который смешивает в возвращаемом значении информацию об ошибке/успехе и количество обработанных курсоров. За-за чего невозможно отличить одно от другого, например ошибку EPERM на Linux от одного успешно закрытого курсора. Теперь mdbx_txn_release_all_cursors() возвращает только код ошибки, а для получения кол-ва закрытых курсоров в API добавлена функция mdbx_txn_release_all_cursors_ex(). --- mdbx.h | 37 +++++++++++++++++++++++++++++++------ src/api-cursor.c | 8 +++++--- 2 files changed, 36 insertions(+), 9 deletions(-) diff --git a/mdbx.h b/mdbx.h index a0886799..99a34f49 100644 --- a/mdbx.h +++ b/mdbx.h @@ -5227,17 +5227,42 @@ LIBMDBX_API void mdbx_cursor_close(MDBX_cursor *cursor); * \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. + * \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. + * \param [in,out] count An optional pointer to return the number of cursors + * processed by the requested operation. * - * \returns A negative error value on failure or the number of closed cursors - * on success, some possible errors are: + * \returns A non-zero error value on failure and 0 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); +LIBMDBX_API int mdbx_txn_release_all_cursors_ex(const MDBX_txn *txn, bool unbind, size_t *count); + +/** \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 non-zero error value on failure and 0 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_INLINE_API(int, mdbx_txn_release_all_cursors, (const MDBX_txn *txn, bool unbind)) { + return mdbx_txn_release_all_cursors_ex(txn, unbind, NULL); +} /** \brief Renew a cursor handle for use within the given transaction. * \ingroup c_cursors diff --git a/src/api-cursor.c b/src/api-cursor.c index b925ac8b..1fefaf2a 100644 --- a/src/api-cursor.c +++ b/src/api-cursor.c @@ -216,14 +216,15 @@ again: return MDBX_SUCCESS; } -int mdbx_txn_release_all_cursors(const MDBX_txn *txn, bool unbind) { +int mdbx_txn_release_all_cursors_ex(const MDBX_txn *txn, bool unbind, size_t *count) { int rc = check_txn(txn, MDBX_TXN_FINISHED | MDBX_TXN_HAS_CHILD); + size_t n = 0; if (likely(rc == MDBX_SUCCESS)) { TXN_FOREACH_DBI_FROM(txn, i, MAIN_DBI) { while (txn->cursors[i]) { + ++n; MDBX_cursor *mc = txn->cursors[i]; ENSURE(nullptr, mc->signature == cur_signature_live && (mc->next != mc) && !mc->backup); - rc = likely(rc < INT_MAX) ? rc + 1 : rc; txn->cursors[i] = mc->next; mc->next = mc; if (unbind) { @@ -236,9 +237,10 @@ int mdbx_txn_release_all_cursors(const MDBX_txn *txn, bool unbind) { } } } else { - eASSERT(nullptr, rc < 0); LOG_IFERR(rc); } + if (count) + *count = n; return rc; }