1+ // #=##=##=#==#=#==#===#+==#+==========+==+=+=+=+=+=++=+++=+++++=-++++=-+++++++++++
2+ //
3+ // Part of the LLFS Project, under Apache License v2.0.
4+ // See https://www.apache.org/licenses/LICENSE-2.0 for license information.
5+ // SPDX short identifier: Apache-2.0
6+ //
7+ // +++++++++++-+-+--+----- --- -- - - - -
8+
9+ #pragma once
10+ #ifndef LLFS_NO_OUTGOING_REFS_CACHE_HPP
11+ #define LLFS_NO_OUTGOING_REFS_CACHE_HPP
12+
13+ #include < llfs/api_types.hpp>
14+ #include < llfs/page_id_factory.hpp>
15+
16+ #include < batteries/bool_status.hpp>
17+
18+ #include < atomic>
19+ #include < vector>
20+
21+ namespace llfs {
22+
23+ // =#=#==#==#===============+=+=+=+=++=++++++++++++++-++-+--+-+----+---------------
24+ /* * \brief A cache to store information about a page's outgoing references to other pages. Can be
25+ * used by an implementer of PageTracer as a way to organize and look up this information on the
26+ * PageDevice level. This cache is implemented as a vector of unsigned 64-bit integers, where every
27+ * element of the vector represents the outgoing refs "state" of a physical page in a PageDevice.
28+ * The lowest bit in an element represents if the page has no outgoing refs. The second lowest bit
29+ * represents the validity of the page's state to help determine if a page's outgoing refs have ever
30+ * been traced. The remaining upper 62 bits are used to store the generation of the physical page.
31+ *
32+ * Example cache entry: 0000000000000000000000000000000000000000000000000000000000000110
33+ * The upper 62 bits represent generation, which in this case is 1. The second lowest bit is the
34+ * validity bit, which is 1 here. This indicates that the page has been traced and therefore the
35+ * cache entry contains valid information for the page of this generation. The lowest bit is 0,
36+ * which indicates that the page has outgoing references to other pages.
37+ */
38+ class NoOutgoingRefsCache
39+ {
40+ public:
41+ explicit NoOutgoingRefsCache (const PageIdFactory& page_ids) noexcept ;
42+
43+ NoOutgoingRefsCache (const NoOutgoingRefsCache&) = delete ;
44+ NoOutgoingRefsCache& operator =(const NoOutgoingRefsCache&) = delete ;
45+
46+ // ----- --- -- - - - -
47+ /* * \brief Sets the two outgoing refs state bits for the given `page_id` based on
48+ * whether the page has outgoing refs or not, as indicated by `new_has_outgoing_refs_state`. This
49+ * function also updates the generation stored in the cache for the physical page associated with
50+ * `page_id`.
51+ *
52+ * @param page_id The id of the page whose outgoing refs information we are storing.
53+ *
54+ * @param new_has_outgoing_refs_state The status to store, indicating whether or not the page has
55+ * outgoing refs. A value of `false` indicates that the page does not have any outgoing refs, and
56+ * a value of `true` indicates that a page does have outgoing refs.
57+ */
58+ void set_page_state (PageId page_id, HasOutgoingRefs new_has_outgoing_refs_state) noexcept ;
59+
60+ // ----- --- -- - - - -
61+ /* * \brief Queries for whether or not the page with id `page_id` contains outgoing references to
62+ * other pages.
63+ *
64+ * \return Returns a `batt::BoolStatus` type, where `kFalse` indicates that the page has no
65+ * outgoing refs, `kTrue` indicates that the page does have outgoing refs, and `kUnknown`
66+ * indicates that the cache entry for the given page does not have any valid information stored in
67+ * it currently.
68+ */
69+ batt::BoolStatus has_outgoing_refs (PageId page_id) const noexcept ;
70+
71+ private:
72+ /* * \brief A mask to retrieve the lowest two outgoing refs state bits.
73+ */
74+ static constexpr u64 kOutgoingRefsStatusBitsMask = 0b11 ;
75+
76+ /* * \brief A mask to access the "valid" bit of the two outgoing refs state bits. This is the
77+ * higher of the two bits.
78+ */
79+ static constexpr u64 kValidBitMask = 0b10 ;
80+
81+ /* * \brief A mask to access the "has no outgoing references" bit of the two outgoing refs state
82+ * bits. This is the lower of the two bits.
83+ */
84+ static constexpr u64 kHasNoOutgoingRefsBitMask = 0b01 ;
85+
86+ /* * \brief A constant representing the number of bits to shift a cache entry in order retrieve the
87+ * generation stored.
88+ */
89+ static constexpr u8 kGenerationShift = 2 ;
90+
91+ /* * \brief A PageIdFactory object to help resolve physical page and generation values from a
92+ * PageId object.
93+ */
94+ const PageIdFactory page_ids_;
95+
96+ /* * \brief The vector storing the cache entries, indexed by physical page id.
97+ */
98+ std::vector<std::atomic<u64 >> cache_;
99+ };
100+ } // namespace llfs
101+
102+ #endif // LLFS_NO_OUTGOING_REFS_CACHE_HPP
0 commit comments