]>
Commit | Line | Data |
---|---|---|
7c673cae | 1 | // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- |
9f95a23c | 2 | // vim: ts=8 sw=2 smarttab ft=cpp |
7c673cae FG |
3 | |
4 | #ifndef RGW_PERIOD_HISTORY_H | |
5 | #define RGW_PERIOD_HISTORY_H | |
6 | ||
7 | #include <deque> | |
8 | #include <mutex> | |
9 | #include <system_error> | |
10 | #include <boost/intrusive/avl_set.hpp> | |
11fdf7f2 | 11 | #include "include/ceph_assert.h" |
7c673cae | 12 | #include "include/types.h" |
f67539c2 | 13 | #include "common/async/yield_context.h" |
b3b6e05e | 14 | #include "common/dout.h" |
7c673cae FG |
15 | |
16 | namespace bi = boost::intrusive; | |
17 | ||
18 | class RGWPeriod; | |
19 | ||
20 | /** | |
21 | * RGWPeriodHistory tracks the relative history of all inserted periods, | |
22 | * coordinates the pulling of missing intermediate periods, and provides a | |
23 | * Cursor object for traversing through the connected history. | |
24 | */ | |
25 | class RGWPeriodHistory final { | |
26 | private: | |
27 | /// an ordered history of consecutive periods | |
28 | class History; | |
29 | ||
30 | // comparisons for avl_set ordering | |
31 | friend bool operator<(const History& lhs, const History& rhs); | |
32 | friend struct NewestEpochLess; | |
33 | ||
34 | class Impl; | |
35 | std::unique_ptr<Impl> impl; | |
36 | ||
37 | public: | |
38 | /** | |
39 | * Puller is a synchronous interface for pulling periods from the master | |
40 | * zone. The abstraction exists mainly to support unit testing. | |
41 | */ | |
42 | class Puller { | |
43 | public: | |
44 | virtual ~Puller() = default; | |
45 | ||
b3b6e05e | 46 | virtual int pull(const DoutPrefixProvider *dpp, const std::string& period_id, RGWPeriod& period, |
f67539c2 | 47 | optional_yield y) = 0; |
7c673cae FG |
48 | }; |
49 | ||
50 | RGWPeriodHistory(CephContext* cct, Puller* puller, | |
51 | const RGWPeriod& current_period); | |
52 | ~RGWPeriodHistory(); | |
53 | ||
54 | /** | |
55 | * Cursor tracks a position in the period history and allows forward and | |
56 | * backward traversal. Only periods that are fully connected to the | |
57 | * current_period are reachable via a Cursor, because other histories are | |
58 | * temporary and can be merged away. Cursors to periods in disjoint | |
59 | * histories, as provided by insert() or lookup(), are therefore invalid and | |
60 | * their operator bool() will return false. | |
61 | */ | |
62 | class Cursor final { | |
63 | public: | |
64 | Cursor() = default; | |
65 | explicit Cursor(int error) : error(error) {} | |
66 | ||
67 | int get_error() const { return error; } | |
68 | ||
69 | /// return false for a default-constructed or error Cursor | |
70 | operator bool() const { return history != nullptr; } | |
71 | ||
72 | epoch_t get_epoch() const { return epoch; } | |
73 | const RGWPeriod& get_period() const; | |
74 | ||
75 | bool has_prev() const; | |
76 | bool has_next() const; | |
77 | ||
78 | void prev() { epoch--; } | |
79 | void next() { epoch++; } | |
80 | ||
81 | friend bool operator==(const Cursor& lhs, const Cursor& rhs); | |
82 | friend bool operator!=(const Cursor& lhs, const Cursor& rhs); | |
83 | ||
84 | private: | |
85 | // private constructors for RGWPeriodHistory | |
86 | friend class RGWPeriodHistory::Impl; | |
87 | ||
88 | Cursor(const History* history, std::mutex* mutex, epoch_t epoch) | |
89 | : history(history), mutex(mutex), epoch(epoch) {} | |
90 | ||
91 | int error{0}; | |
92 | const History* history{nullptr}; | |
93 | std::mutex* mutex{nullptr}; | |
94 | epoch_t epoch{0}; //< realm epoch of cursor position | |
95 | }; | |
96 | ||
97 | /// return a cursor to the current period | |
98 | Cursor get_current() const; | |
99 | ||
100 | /// build up a connected period history that covers the span between | |
101 | /// current_period and the given period, reading predecessor periods or | |
102 | /// fetching them from the master as necessary. returns a cursor at the | |
103 | /// given period that can be used to traverse the current_history | |
b3b6e05e | 104 | Cursor attach(const DoutPrefixProvider *dpp, RGWPeriod&& period, optional_yield y); |
7c673cae FG |
105 | |
106 | /// insert the given period into an existing history, or create a new | |
107 | /// unconnected history. similar to attach(), but it doesn't try to fetch | |
108 | /// missing periods. returns a cursor to the inserted period iff it's in | |
109 | /// the current_history | |
110 | Cursor insert(RGWPeriod&& period); | |
111 | ||
112 | /// search for a period by realm epoch, returning a valid Cursor iff it's in | |
113 | /// the current_history | |
114 | Cursor lookup(epoch_t realm_epoch); | |
115 | }; | |
116 | ||
117 | #endif // RGW_PERIOD_HISTORY_H |