]>
Commit | Line | Data |
---|---|---|
f67539c2 TL |
1 | // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:nil -*- |
2 | // vim: ts=8 sw=2 smarttab | |
3 | ||
4 | #pragma once | |
5 | ||
6 | #include <memory> | |
7 | ||
8 | #include "crimson/common/type_helpers.h" | |
9 | ||
10 | #include "fwd.h" | |
11 | ||
12 | namespace crimson::os::seastore::onode { | |
13 | ||
14 | class Node; | |
15 | class Super; | |
16 | ||
17 | /** | |
18 | * RootNodeTracker | |
19 | * | |
20 | * An abstracted tracker to get the root node by Transaction. | |
21 | */ | |
22 | class RootNodeTracker { | |
23 | public: | |
24 | virtual ~RootNodeTracker() = default; | |
25 | virtual bool is_clean() const = 0; | |
26 | virtual Ref<Node> get_root(Transaction&) const = 0; | |
27 | static RootNodeTrackerURef create(bool read_isolated); | |
28 | protected: | |
29 | RootNodeTracker() = default; | |
30 | RootNodeTracker(const RootNodeTracker&) = delete; | |
31 | RootNodeTracker(RootNodeTracker&&) = delete; | |
32 | RootNodeTracker& operator=(const RootNodeTracker&) = delete; | |
33 | RootNodeTracker& operator=(RootNodeTracker&&) = delete; | |
34 | virtual void do_track_super(Transaction&, Super&) = 0; | |
35 | virtual void do_untrack_super(Transaction&, Super&) = 0; | |
36 | friend class Super; | |
37 | }; | |
38 | ||
39 | /** | |
40 | * Super | |
41 | * | |
42 | * The parent of root node. It contains the relationship between a Transaction | |
43 | * and a root node address. | |
44 | */ | |
45 | class Super { | |
46 | public: | |
47 | using URef = std::unique_ptr<Super>; | |
48 | Super(const Super&) = delete; | |
49 | Super(Super&&) = delete; | |
50 | Super& operator=(const Super&) = delete; | |
51 | Super& operator=(Super&&) = delete; | |
52 | virtual ~Super() { | |
53 | assert(tracked_root_node == nullptr); | |
54 | tracker.do_untrack_super(t, *this); | |
55 | } | |
56 | ||
57 | virtual laddr_t get_root_laddr() const = 0; | |
58 | virtual void write_root_laddr(context_t, laddr_t) = 0; | |
59 | ||
60 | void do_track_root(Node& root) { | |
61 | assert(tracked_root_node == nullptr); | |
62 | tracked_root_node = &root; | |
63 | } | |
64 | void do_untrack_root(Node& root) { | |
65 | assert(tracked_root_node == &root); | |
66 | tracked_root_node = nullptr; | |
67 | } | |
68 | Node* get_p_root() const { | |
69 | assert(tracked_root_node != nullptr); | |
70 | return tracked_root_node; | |
71 | } | |
72 | ||
73 | protected: | |
74 | Super(Transaction& t, RootNodeTracker& tracker) | |
75 | : t{t}, tracker{tracker} { | |
76 | tracker.do_track_super(t, *this); | |
77 | } | |
78 | ||
79 | private: | |
80 | Transaction& t; | |
81 | RootNodeTracker& tracker; | |
82 | Node* tracked_root_node = nullptr; | |
83 | }; | |
84 | ||
85 | /** | |
86 | * RootNodeTrackerIsolated | |
87 | * | |
88 | * A concrete RootNodeTracker implementation which provides root node isolation | |
89 | * between Transactions for Seastore backend. | |
90 | */ | |
91 | class RootNodeTrackerIsolated final : public RootNodeTracker { | |
92 | public: | |
93 | ~RootNodeTrackerIsolated() override { assert(is_clean()); } | |
94 | protected: | |
95 | bool is_clean() const override { | |
96 | return tracked_supers.empty(); | |
97 | } | |
98 | void do_track_super(Transaction& t, Super& super) override { | |
99 | assert(tracked_supers.find(&t) == tracked_supers.end()); | |
100 | tracked_supers[&t] = &super; | |
101 | } | |
102 | void do_untrack_super(Transaction& t, Super& super) override { | |
103 | [[maybe_unused]] auto removed = tracked_supers.erase(&t); | |
104 | assert(removed); | |
105 | } | |
106 | ::Ref<Node> get_root(Transaction& t) const override; | |
107 | std::map<Transaction*, Super*> tracked_supers; | |
108 | }; | |
109 | ||
110 | /** | |
111 | * RootNodeTrackerShared | |
112 | * | |
113 | * A concrete RootNodeTracker implementation which has no isolation between | |
114 | * Transactions for Dummy backend. | |
115 | */ | |
116 | class RootNodeTrackerShared final : public RootNodeTracker { | |
117 | public: | |
118 | ~RootNodeTrackerShared() override { assert(is_clean()); } | |
119 | protected: | |
120 | bool is_clean() const override { | |
121 | return tracked_super == nullptr; | |
122 | } | |
123 | void do_track_super(Transaction&, Super& super) override { | |
124 | assert(is_clean()); | |
125 | tracked_super = &super; | |
126 | } | |
127 | void do_untrack_super(Transaction&, Super& super) override { | |
128 | assert(tracked_super == &super); | |
129 | tracked_super = nullptr; | |
130 | } | |
131 | ::Ref<Node> get_root(Transaction&) const override; | |
132 | Super* tracked_super = nullptr; | |
133 | }; | |
134 | ||
135 | inline RootNodeTrackerURef RootNodeTracker::create(bool read_isolated) { | |
136 | if (read_isolated) { | |
137 | return RootNodeTrackerURef(new RootNodeTrackerIsolated()); | |
138 | } else { | |
139 | return RootNodeTrackerURef(new RootNodeTrackerShared()); | |
140 | } | |
141 | } | |
142 | ||
143 | } |