From bf6dbf0e42c081c7b75bea9bb59ffbd0c0d6b529 Mon Sep 17 00:00:00 2001 From: Martchus Date: Mon, 21 Feb 2022 23:46:32 +0100 Subject: [PATCH] Improve comments --- lmdb-safe.hh | 32 +++++++++++-- lmdb-typed.hh | 130 +++++++++++++++++++++++++++++++++----------------- 2 files changed, 115 insertions(+), 47 deletions(-) diff --git a/lmdb-safe.hh b/lmdb-safe.hh index 5c3c0fc..690261e 100644 --- a/lmdb-safe.hh +++ b/lmdb-safe.hh @@ -40,6 +40,9 @@ using string_view = boost::string_ref; #endif #endif +/*! + * \brief The LMDBError class is thrown when an error happens. + */ class LMDB_SAFE_EXPORT LMDBError : public std::runtime_error { public: explicit LMDBError(const std::string &error) noexcept @@ -79,19 +82,24 @@ public: class MDBRWTransactionImpl; class MDBROTransactionImpl; - using MDBROTransaction = std::unique_ptr; using MDBRWTransaction = std::unique_ptr; +/*! + * \brief The MDBEnv class is a handle to an MDB environment. + */ class LMDB_SAFE_EXPORT MDBEnv { public: MDBEnv(const char *fname, unsigned int flags, mdb_mode_t mode, MDB_dbi maxDBs = 10); + /*! + * \brief Closes the MDB environment. + * \remarks Only a single thread may call this function. All transactions, databases, and cursors must already be closed + * before calling this function. + */ ~MDBEnv() { - // Only a single thread may call this function. All transactions, databases, and cursors must already be closed before calling this function mdb_env_close(d_env); - // but, elsewhere, docs say database handles do not need to be closed? } MDBDbi openDB(const string_view dbname, unsigned int flags); @@ -119,8 +127,14 @@ private: std::map d_ROtransactionsOut; }; +/*! + * \brief Opens an MDB environment for the specified database file. + */ LMDB_SAFE_EXPORT std::shared_ptr getMDBEnv(const char *fname, unsigned int flags, mdb_mode_t mode, MDB_dbi maxDBs = 128); +/*! + * \brief The MDBOutVal struct is the handle to an MDB value used as output. + */ struct LMDB_SAFE_EXPORT MDBOutVal { operator MDB_val &() { @@ -170,6 +184,9 @@ template <> inline string_view MDBOutVal::get() const return string_view(static_cast(d_mdbval.mv_data), d_mdbval.mv_size); } +/*! + * \brief The MDBInVal struct is the handle to an MDB value used as input. + */ class LMDB_SAFE_EXPORT MDBInVal { public: MDBInVal(const MDBOutVal &rhs) @@ -226,6 +243,9 @@ private: class MDBROCursor; +/*! + * \brief The MDBROTransactionImpl class wraps read operations. + */ class LMDB_SAFE_EXPORT MDBROTransactionImpl { protected: MDBROTransactionImpl(MDBEnv *parent, MDB_txn *txn); @@ -465,6 +485,9 @@ public: } }; +/*! + * \brief The MDBROCursor class represents a read-only cursor. + */ class LMDB_SAFE_EXPORT MDBROCursor : public MDBGenCursor { public: MDBROCursor() = default; @@ -478,6 +501,9 @@ public: class MDBRWCursor; +/*! + * \brief The MDBRWTransactionImpl class wraps write operations. + */ class LMDB_SAFE_EXPORT MDBRWTransactionImpl : public MDBROTransactionImpl { protected: MDBRWTransactionImpl(MDBEnv *parent, MDB_txn *txn); diff --git a/lmdb-typed.hh b/lmdb-typed.hh index 627ac4b..4507998 100644 --- a/lmdb-typed.hh +++ b/lmdb-typed.hh @@ -8,32 +8,37 @@ namespace LMDBSafe { -/* - Open issues: - Perhaps use the separate index concept from multi_index - perhaps get eiter to be of same type so for(auto& a : x) works - make it more value "like" with unique_ptr -*/ - /*! * \brief The type used to store IDs. "0" indicates "no such ID". */ using IDType = std::uint32_t; -/** Return the highest ID used in a database. Returns 0 for an empty DB. - This makes us start everything at ID=1, which might make it possible to - treat id 0 as special -*/ +/*! + * \brief Returns the highest ID used in a database. Returns 0 for an empty DB. + * \remarks + * This makes us start everything at ID "1", which might make it possible to + * treat id 0 as special. + */ LMDB_SAFE_EXPORT IDType MDBGetMaxID(MDBRWTransaction &txn, MDBDbi &dbi); -/** This is the serialization interface. - You need to define your these functions for the types you'd like to store. -*/ +/*! + * \brief Converts \a t to an std::string. + * + * This is the serialization interface. You need to define this function for the + * types you'd like to store. + */ template std::string serToString(const T &t); +/*! + * \brief Initializes \a ret from \a str. + * + * This is the deserialization interface. You need to define this function for the + * types you'd like to store. + */ template void serFromString(string_view str, T &ret); -// define some "shortcuts" (to avoid full-blown serialization stuff for trivial cases) +/// \cond +/// Define some "shortcuts" (to avoid full-blown serialization stuff for trivial cases): template <> inline std::string serToString(const std::string_view &t) { return std::string(t); @@ -107,9 +112,14 @@ template <> inline void serFromString<>(string_view str, std::uint64_t &ret) ret = CppUtilities::LE::toUInt64(str.data()); } -/** This is the serialization interface for keys. - You need to define your these functions for the types you'd like to use as keys. -*/ +/// \endcond + +/*! + * \brief Converts \a t to an std::string. + * + * This is the serialization interface for keys. You need to define your this function + * for the types you'd like to use as keys. + */ template inline std::string keyConv(const T &t); template ::value, T>::type * = nullptr> inline string_view keyConv(const T &t) @@ -117,6 +127,8 @@ template ::value, T>::typ return string_view(reinterpret_cast(&t), sizeof(t)); } +/// \cond +/// Define keyConv for trivial cases: template ::value, T>::type * = nullptr> inline string_view keyConv(const T &t) { return t; @@ -126,6 +138,7 @@ template ::value, { return t; } +/// \endcond /*! * \brief The LMDBIndexOps struct implements index operations, but only the operations that @@ -135,7 +148,7 @@ template ::value, * only includes calls that should be ignored for empty indexes. * * This class only needs methods that must happen for all indexes at once. So specifically, *not* - * size or get. People ask for those themselves, and should no do that on indexes that + * size or get. People ask for those themselves, and should not do that on indexes that * don't exist. */ template struct LMDB_SAFE_EXPORT LMDBIndexOps { @@ -170,8 +183,9 @@ template struct LMDB_SAFE_EXPORT L Parent *d_parent; }; -/** This is an index on a field in a struct, it derives from the LMDBIndexOps */ - +/*! + * \brief The index_on struct is used to declare an index on a member variable of a particular type. + */ template struct index_on : LMDBIndexOps> { index_on() : LMDBIndexOps>(this) @@ -185,7 +199,10 @@ template struct index_on typedef Type type; }; -/** This is a calculated index */ +/*! + * \brief The index_on_function struct is used to declare an index which is dynamically computed via + * a function. + */ template struct index_on_function : LMDBIndexOps> { index_on_function() : LMDBIndexOps>(this) @@ -204,6 +221,11 @@ template struct index_on_function : LMD * \brief The TypedDBI class is the main class. * \tparam T Specifies the type to store within the database. * \tparam I Specifies an index, should be an instantiation of index_on. + * + * Open issues: + * - Perhaps use the separate index concept from multi_index. + * - Perhaps get eiter to be of same type so for(auto& a : x) works + * make it more value "like" with unique_ptr. */ template class LMDB_SAFE_EXPORT TypedDBI { public: @@ -214,6 +236,7 @@ public: private: tuple_t d_tuple; + /// \cond template struct IndexIterator { static inline void apply(Tuple &tuple, auto &&func) { @@ -238,6 +261,7 @@ private: { IndexIterator>::apply(d_tuple, std::forward(func)); } + /// \endcond public: TypedDBI(std::shared_ptr env, string_view name) @@ -249,8 +273,9 @@ public: forEachIndex([&](auto &&i) { i.openDB(d_env, CppUtilities::argsToString(name, '_', index++), MDB_CREATE | MDB_DUPFIXED | MDB_DUPSORT); }); } - // We support readonly and rw transactions. Here we put the Readonly operations - // which get sourced by both kinds of transactions + /*! + * \brief The ReadonlyOperations struct defines read-only operations. + */ template struct ReadonlyOperations { ReadonlyOperations(Parent &parent) : d_parent(parent) @@ -309,7 +334,9 @@ public: return count; } - //! End iderator type + /*! + * \brief The eiter_t struct is the end iterator. + */ struct eiter_t { }; @@ -317,11 +344,18 @@ public: template struct DirectStorage { }; - // can be on main, or on an index - // when on main, return data directly - // when on index, indirect - // we can be limited to one key, or iterate over entire database - // iter requires you to put the cursor in the right place first! + /*! + * \brief The iter_t struct is the iterator type for walking through the database rows. + * \remarks + * - The iterator can be on the main database or on an index. It returns the data directly on + * the main database and indirectly when on an index. + * - An iterator can be limited to one key or iterate over the entire database. + * - The iter_t struct requires you to put the cursor in the right place first. + * - The object can be stored as direct member of iter_t or as std::unique_ptr or std::shared_ptr + * by specifying the corresponding template as \tp ElementType. The pointer can then be accessed + * via getPointer(). Note that the returned pointer object is re-used when the iterator is incremented + * or decremented unless the owned object is moved into another pointer object. + */ template