mdbx-PoC: preliminary-draft of mdbx_get_cached() (!!! DON'T USE SINCE NOT TESTED AT ALL !!!)

This commit is contained in:
Леонид Юрьев (Leonid Yuriev)
2025-09-14 23:59:35 +03:00
parent 48c3805a96
commit 07c5864b21
4 changed files with 403 additions and 0 deletions

123
mdbx.h
View File

@@ -4923,6 +4923,129 @@ LIBMDBX_API int mdbx_get_ex(const MDBX_txn *txn, MDBX_dbi dbi, MDBX_val *key, MD
* \retval MDBX_EINVAL An invalid parameter was specified. */
LIBMDBX_API int mdbx_get_equal_or_great(const MDBX_txn *txn, MDBX_dbi dbi, MDBX_val *key, MDBX_val *data);
/** \brief Lightweight transparent cache entry structure used by \ref mdbx_cache_get().
* \ingroup c_crud
*
* The approach of these caching is to preserve address of a value retrieved from the database with an extremely fast
* check of relevance it based on a transaction ID within an internal b-tree structures. Event a b-tree was modified
* then the search for the corresponding key from the root of the b-tree to leaf pages stops as soon as reaches a page
* that has not been modified after the last check of given cache entry. This way, the minimum actions is performed,
* which is no slower than a usual key search in the worst case, and at best, only a few lightweight checks will be do.
*
* \note The cache structure allows it to be placed in shared memory and used by multiple processes.
* However, such interaction and management are not provided by libmdbx in any way yet now.
*
* \note An each cache entry must be initialized by \ref mdbx_cache_init() before first use. */
typedef struct MDBX_cache_entry {
uint64_t trunk_txnid; /**< The transaction/MVCC-snapshot ID of a page or other internal DB structure
* that hold the cached data or reflect it state. */
uint64_t last_confirmed_txnid; /**< The recent transaction/MVCC-snapshot ID wherein the cache entry
* was checked and confirmed. */
size_t offset; /**< The offset of cached data value for a corresponding key.
* The zero value means \ref MDBX_NOTFOUND. */
uint32_t length; /**< The length of cached data value for a corresponding key. */
} MDBX_cache_entry;
/** \brief Initializes the cache entry before the first use.
* \ingroup c_crud
* \see MDBX_cache_entry
* \see mdbx_cache_get() */
LIBMDBX_INLINE_API(void, mdbx_cache_init, (MDBX_cache_entry * entry)) {
entry->offset = 0;
entry->length = 0;
entry->trunk_txnid = 0;
entry->last_confirmed_txnid = 0;
}
/** \brief Cache entry status returned by \ref mdbx_cache_get().
* \ingroup c_crud
* \see MDBX_cache_entry
* \see mdbx_cache_init() */
typedef enum MDBX_cache_status {
/** \brief The error other than \ref MDBX_NOTFOUND has occurred.
* \details There is no correct result since an error has occurred that is not related
* to the absence of the desired key-value pair.
* The given cache entry has not been changed. */
MDBX_CACHE_ERROR = -2,
/** \brief The result was obtained by bypassing the cache, because
* the transaction is too old to using the cache entry.
* \details The cache entry reflects a newer version of the data that is unavailable within
* an MVCC-snapshot used by current transaction.
* The given cache entry has not been changed.
* The result of getting a value is correct until the transaction end. */
MDBX_CACHE_BEHIND = -1,
/** \brief The result was obtained by bypassing the cache, because
* the given cache entry being updated by another thread.
* \details When accessing the cache entry, a race condition was detected with its update by another thread.
* Therefore, the result was obtained without using the cache entry and without affecting an operation of other
* threads using it, including the ones performing an update. For a read transaction, the result is correct until
* the transaction end. For a write transactions, the result is correct until the value is explicitly changed or
* the transaction is completed. */
MDBX_CACHE_RACE = 0,
/** \brief The result of getting a value is correct, but it cannot be cached since
* the changes have not been committed.
* \details The requested value of a pair is in a dirty state itself or on a dirty page with other updated items.
* This cache entry has not been changed because the corresponding data changes have not yet been committed
* and could be aborted.
* The result of the get operation and data value are valid within the current write transaction
* until any next modification. */
MDBX_CACHE_DIRTY = 1,
/** \brief The result of getting a value is correct and was retrieved from the cache entry which is untouched.
* \details There were no changes in the cached data after the last check.
* The given cache entry was not altered as it is complete up-to-date.
* For a read transaction, the result is correct until the transaction end.
* For a write transactions, the result is correct until the value is explicitly changed
* or the transaction is completed. */
MDBX_CACHE_HIT = 2,
/** \brief The result of getting a value is correct and has been retrieved from the cache, which has been
* altered to reflect recently committed transactions.
* \details There were no changes in the cached data after the last check.
* The given cache entry has been slightly updated to reflect the relevance of the data for recent committed
* transaction(s). For a read transaction, the result is correct until the transaction end. For a write transactions,
* the result is correct until the value is explicitly changed or the transaction is completed. */
MDBX_CACHE_CONFIRMED = 3,
/** \brief The result of getting a value is correct and corresponds to the fresh data readed from the database,
* which also putted into the cache entry.
* \details After the last check, either the value of the requested pair itself changed,
* or it was moved to a new page due to the updating of neighboring items.
* The given cache entry has been completely updated to reflect the actual data.
* For a read transaction, the result is correct until the transaction end.
* For a write transactions, the result is correct until the value is explicitly changed
* or the transaction is completed. */
MDBX_CACHE_REFRESHED = 4
} MDBX_cache_status_t;
/** \brief Pair of error code and cache status as a result of \ref mdbx_cache_get().
* \ingroup c_crud */
typedef struct MDBX_cache_result {
MDBX_error_t errcode;
MDBX_cache_status_t status;
} MDBX_cache_result_t;
/** \brief Get items from a table using cache.
* \ingroup c_crud
* \see mdbx_cache_get_SingleThreaded()
* \see MDBX_cache_entry
* \see mdbx_cache_init()
*/
LIBMDBX_API MDBX_cache_result_t mdbx_cache_get(const MDBX_txn *txn, MDBX_dbi dbi, const MDBX_val *key, MDBX_val *data,
volatile MDBX_cache_entry *entry);
/** \brief FIXME
* \ingroup c_crud
* \see mdbx_cache_get()
* \see MDBX_cache_entry
* \see mdbx_cache_init()
*/
LIBMDBX_API MDBX_cache_result_t mdbx_cache_get_SingleThreaded(const MDBX_txn *txn, MDBX_dbi dbi, const MDBX_val *key,
MDBX_val *data, MDBX_cache_entry *entry);
/** \brief Store items into a table.
* \ingroup c_crud
*