mirror of
https://github.com/isar/libmdbx.git
synced 2025-01-30 22:47:16 +08:00
mdbx: Support for user-settable cursor context.
Change-Id: I9bd60c432924e39020b2d3af3280f13c44d6cd91
This commit is contained in:
parent
72e136b9da
commit
f6850f5367
@ -29,7 +29,7 @@ Added features:
|
|||||||
- Improved DB corruption detection by checking parent-page-txnid.
|
- Improved DB corruption detection by checking parent-page-txnid.
|
||||||
- Improved opening large DB (> 4Gb) from 32-bit code.
|
- Improved opening large DB (> 4Gb) from 32-bit code.
|
||||||
- Provided `pure-function` and `const-function` attributes to C API.
|
- Provided `pure-function` and `const-function` attributes to C API.
|
||||||
- Support for user-settable transaction context.
|
- Support for user-settable context for transactions & cursors.
|
||||||
- Revised API and documentation related to Handle-Slow-Readers callback feature.
|
- Revised API and documentation related to Handle-Slow-Readers callback feature.
|
||||||
|
|
||||||
Deprecated functions and flags:
|
Deprecated functions and flags:
|
||||||
|
29
mdbx.h
29
mdbx.h
@ -3562,8 +3562,35 @@ LIBMDBX_API int mdbx_del(MDBX_txn *txn, MDBX_dbi dbi, const MDBX_val *key,
|
|||||||
* which helps to avoid errors such as: use-after-free, double-free, i.e.
|
* which helps to avoid errors such as: use-after-free, double-free, i.e.
|
||||||
* memory corruption and segfaults.
|
* memory corruption and segfaults.
|
||||||
*
|
*
|
||||||
|
* \param [in] context A pointer to application context to be associated with
|
||||||
|
* created cursor and could be retrieved by
|
||||||
|
* \ref mdbx_cursor_get_userctx() until cursor closed.
|
||||||
|
*
|
||||||
* \returns Created cursor handle or NULL in case out of memory. */
|
* \returns Created cursor handle or NULL in case out of memory. */
|
||||||
LIBMDBX_API MDBX_cursor *mdbx_cursor_create(void);
|
LIBMDBX_API MDBX_cursor *mdbx_cursor_create(void *context);
|
||||||
|
|
||||||
|
/** \brief Set application information associated with the \ref MDBX_cursor.
|
||||||
|
* \ingroup c_crud
|
||||||
|
* \see mdbx_cursor_get_userctx()
|
||||||
|
*
|
||||||
|
* \param [in] cursor An cursor handle returned by \ref mdbx_cursor_create()
|
||||||
|
* or \ref mdbx_cursor_open().
|
||||||
|
* \param [in] ctx An arbitrary pointer for whatever the application needs.
|
||||||
|
*
|
||||||
|
* \returns A non-zero error value on failure and 0 on success. */
|
||||||
|
LIBMDBX_API int mdbx_cursor_set_userctx(MDBX_cursor *cursor, void *ctx);
|
||||||
|
|
||||||
|
/** \brief Get the application information associated with the MDBX_cursor.
|
||||||
|
* \ingroup c_crud
|
||||||
|
* \see mdbx_cursor_set_userctx()
|
||||||
|
*
|
||||||
|
* \param [in] cursor An cursor handle returned by \ref mdbx_cursor_create()
|
||||||
|
* or \ref mdbx_cursor_open().
|
||||||
|
* \returns The pointer which was passed via the `context` parameter
|
||||||
|
* of `mdbx_cursor_create()` or set by \ref mdbx_cursor_set_userctx(),
|
||||||
|
* or `NULL` if something wrong. */
|
||||||
|
MDBX_NOTHROW_PURE_FUNCTION LIBMDBX_API void *
|
||||||
|
mdbx_cursor_get_userctx(const MDBX_cursor *cursor);
|
||||||
|
|
||||||
/** \brief Bind cursor to specified transaction and DBI handle.
|
/** \brief Bind cursor to specified transaction and DBI handle.
|
||||||
* \ingroup c_cursors
|
* \ingroup c_cursors
|
||||||
|
2
mdbx.h++
2
mdbx.h++
@ -4396,7 +4396,7 @@ inline bool cursor::erase(bool whole_multivalue) {
|
|||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
inline cursor_managed::cursor_managed()
|
inline cursor_managed::cursor_managed()
|
||||||
: cursor_managed(::mdbx_cursor_create()) {
|
: cursor_managed(::mdbx_cursor_create(nullptr)) {
|
||||||
if (MDBX_UNLIKELY(!handle_))
|
if (MDBX_UNLIKELY(!handle_))
|
||||||
MDBX_CXX20_UNLIKELY error::throw_exception(MDBX_ENOMEM);
|
MDBX_CXX20_UNLIKELY error::throw_exception(MDBX_ENOMEM);
|
||||||
}
|
}
|
||||||
|
30
src/core.c
30
src/core.c
@ -13805,16 +13805,42 @@ static int mdbx_cursor_init(MDBX_cursor *mc, MDBX_txn *txn, MDBX_dbi dbi) {
|
|||||||
&txn->mt_dbistate[dbi]);
|
&txn->mt_dbistate[dbi]);
|
||||||
}
|
}
|
||||||
|
|
||||||
MDBX_cursor *mdbx_cursor_create(void) {
|
MDBX_cursor *mdbx_cursor_create(void *context) {
|
||||||
MDBX_cursor_couple *couple = mdbx_calloc(1, sizeof(MDBX_cursor_couple));
|
MDBX_cursor_couple *couple = mdbx_calloc(1, sizeof(MDBX_cursor_couple));
|
||||||
if (unlikely(!couple))
|
if (unlikely(!couple))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
couple->outer.mc_signature = MDBX_MC_READY4CLOSE;
|
couple->outer.mc_signature = MDBX_MC_READY4CLOSE;
|
||||||
couple->outer.mc_dbi = UINT_MAX;
|
couple->outer.mc_dbi = UINT_MAX;
|
||||||
|
couple->mc_userctx = context;
|
||||||
return &couple->outer;
|
return &couple->outer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int mdbx_cursor_set_userctx(MDBX_cursor *mc, void *ctx) {
|
||||||
|
if (unlikely(!mc))
|
||||||
|
return MDBX_EINVAL;
|
||||||
|
|
||||||
|
if (unlikely(mc->mc_signature != MDBX_MC_READY4CLOSE &&
|
||||||
|
mc->mc_signature != MDBX_MC_LIVE))
|
||||||
|
return MDBX_EINVAL;
|
||||||
|
|
||||||
|
MDBX_cursor_couple *couple = container_of(mc, MDBX_cursor_couple, outer);
|
||||||
|
couple->mc_userctx = ctx;
|
||||||
|
return MDBX_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *mdbx_cursor_get_userctx(const MDBX_cursor *mc) {
|
||||||
|
if (unlikely(!mc))
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
if (unlikely(mc->mc_signature != MDBX_MC_READY4CLOSE &&
|
||||||
|
mc->mc_signature != MDBX_MC_LIVE))
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
MDBX_cursor_couple *couple = container_of(mc, MDBX_cursor_couple, outer);
|
||||||
|
return couple->mc_userctx;
|
||||||
|
}
|
||||||
|
|
||||||
int mdbx_cursor_bind(MDBX_txn *txn, MDBX_cursor *mc, MDBX_dbi dbi) {
|
int mdbx_cursor_bind(MDBX_txn *txn, MDBX_cursor *mc, MDBX_dbi dbi) {
|
||||||
if (unlikely(!mc))
|
if (unlikely(!mc))
|
||||||
return MDBX_EINVAL;
|
return MDBX_EINVAL;
|
||||||
@ -13868,7 +13894,7 @@ int mdbx_cursor_open(MDBX_txn *txn, MDBX_dbi dbi, MDBX_cursor **ret) {
|
|||||||
return MDBX_EINVAL;
|
return MDBX_EINVAL;
|
||||||
*ret = NULL;
|
*ret = NULL;
|
||||||
|
|
||||||
MDBX_cursor *const mc = mdbx_cursor_create();
|
MDBX_cursor *const mc = mdbx_cursor_create(nullptr);
|
||||||
if (unlikely(!mc))
|
if (unlikely(!mc))
|
||||||
return MDBX_ENOMEM;
|
return MDBX_ENOMEM;
|
||||||
|
|
||||||
|
@ -917,6 +917,7 @@ typedef struct MDBX_xcursor {
|
|||||||
|
|
||||||
typedef struct MDBX_cursor_couple {
|
typedef struct MDBX_cursor_couple {
|
||||||
MDBX_cursor outer;
|
MDBX_cursor outer;
|
||||||
|
void *mc_userctx; /* User-settable context */
|
||||||
MDBX_xcursor inner;
|
MDBX_xcursor inner;
|
||||||
} MDBX_cursor_couple;
|
} MDBX_cursor_couple;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user