]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- |
2 | // vim: ts=8 sw=2 smarttab | |
3 | ||
4 | #ifndef CEPH_READAHEAD_H | |
5 | #define CEPH_READAHEAD_H | |
6 | ||
7c673cae | 7 | #include <list> |
11fdf7f2 TL |
8 | #include <vector> |
9 | ||
10 | #include "include/Context.h" | |
11 | #include "common/ceph_mutex.h" | |
7c673cae FG |
12 | |
13 | /** | |
14 | This class provides common state and logic for code that needs to perform readahead | |
15 | on linear things such as RBD images or files. | |
16 | Unless otherwise specified, all methods are thread-safe. | |
17 | ||
18 | Minimum and maximum readahead sizes may be violated by up to 50\% if alignment is enabled. | |
19 | Minimum readahead size may be violated if the end of the readahead target is reached. | |
20 | */ | |
21 | class Readahead { | |
22 | public: | |
23 | typedef std::pair<uint64_t, uint64_t> extent_t; | |
24 | ||
25 | // equal to UINT64_MAX | |
26 | static const uint64_t NO_LIMIT = 18446744073709551615ULL; | |
27 | ||
28 | Readahead(); | |
29 | ||
30 | ~Readahead(); | |
31 | ||
32 | /** | |
33 | Update state with new reads and return readahead to be performed. | |
34 | If the length of the returned extent is 0, no readahead should be performed. | |
35 | The readahead extent is guaranteed not to pass \c limit. | |
36 | ||
37 | Note that passing in NO_LIMIT as the limit and truncating the returned extent | |
38 | is not the same as passing in the correct limit, because the internal state | |
39 | will differ in the two cases. | |
40 | ||
41 | @param extents read operations since last call to update | |
42 | @param limit size of the thing readahead is being applied to | |
43 | */ | |
11fdf7f2 | 44 | extent_t update(const std::vector<extent_t>& extents, uint64_t limit); |
7c673cae FG |
45 | |
46 | /** | |
47 | Update state with a new read and return readahead to be performed. | |
48 | If the length of the returned extent is 0, no readahead should be performed. | |
49 | The readahead extent is guaranteed not to pass \c limit. | |
50 | ||
51 | Note that passing in NO_LIMIT as the limit and truncating the returned extent | |
52 | is not the same as passing in the correct limit, because the internal state | |
53 | will differ in the two cases. | |
54 | ||
55 | @param offset offset of the read operation | |
56 | @param length length of the read operation | |
57 | @param limit size of the thing readahead is being applied to | |
58 | */ | |
59 | extent_t update(uint64_t offset, uint64_t length, uint64_t limit); | |
60 | ||
61 | /** | |
62 | Increment the pending counter. | |
63 | */ | |
64 | void inc_pending(int count = 1); | |
65 | ||
66 | /** | |
67 | Decrement the pending counter. | |
68 | The counter must not be decremented below 0. | |
69 | */ | |
70 | void dec_pending(int count = 1); | |
71 | ||
72 | /** | |
73 | Waits until the pending count reaches 0. | |
74 | */ | |
75 | void wait_for_pending(); | |
76 | void wait_for_pending(Context *ctx); | |
77 | ||
78 | /** | |
79 | Sets the number of sequential requests necessary to trigger readahead. | |
80 | */ | |
81 | void set_trigger_requests(int trigger_requests); | |
82 | ||
83 | /** | |
84 | Gets the minimum size of a readahead request, in bytes. | |
85 | */ | |
86 | uint64_t get_min_readahead_size(void); | |
87 | ||
88 | /** | |
89 | Gets the maximum size of a readahead request, in bytes. | |
90 | */ | |
91 | uint64_t get_max_readahead_size(void); | |
92 | ||
93 | /** | |
94 | Sets the minimum size of a readahead request, in bytes. | |
95 | */ | |
96 | void set_min_readahead_size(uint64_t min_readahead_size); | |
97 | ||
98 | /** | |
99 | Sets the maximum size of a readahead request, in bytes. | |
100 | */ | |
101 | void set_max_readahead_size(uint64_t max_readahead_size); | |
102 | ||
103 | /** | |
104 | Sets the alignment units. | |
105 | If the end point of a readahead request can be aligned to an alignment unit | |
106 | by increasing or decreasing the size of the request by 50\% or less, it will. | |
107 | Alignments are tested in order, so larger numbers should almost always come first. | |
108 | */ | |
109 | void set_alignments(const std::vector<uint64_t> &alignments); | |
110 | ||
111 | private: | |
112 | /** | |
113 | Records that a read request has been received. | |
114 | m_lock must be held while calling. | |
115 | */ | |
116 | void _observe_read(uint64_t offset, uint64_t length); | |
117 | ||
118 | /** | |
119 | Computes the next readahead request. | |
120 | m_lock must be held while calling. | |
121 | */ | |
122 | extent_t _compute_readahead(uint64_t limit); | |
123 | ||
124 | /// Number of sequential requests necessary to trigger readahead | |
125 | int m_trigger_requests; | |
126 | ||
127 | /// Minimum size of a readahead request, in bytes | |
128 | uint64_t m_readahead_min_bytes; | |
129 | ||
130 | /// Maximum size of a readahead request, in bytes | |
131 | uint64_t m_readahead_max_bytes; | |
132 | ||
133 | /// Alignment units, in bytes | |
134 | std::vector<uint64_t> m_alignments; | |
135 | ||
136 | /// Held while reading/modifying any state except m_pending | |
11fdf7f2 | 137 | ceph::mutex m_lock = ceph::make_mutex("Readahead::m_lock"); |
7c673cae FG |
138 | |
139 | /// Number of consecutive read requests in the current sequential stream | |
140 | int m_nr_consec_read; | |
141 | ||
142 | /// Number of bytes read in the current sequenial stream | |
143 | uint64_t m_consec_read_bytes; | |
144 | ||
145 | /// Position of the read stream | |
146 | uint64_t m_last_pos; | |
147 | ||
148 | /// Position of the readahead stream | |
149 | uint64_t m_readahead_pos; | |
150 | ||
151 | /// When readahead is already triggered and the read stream crosses this point, readahead is continued | |
152 | uint64_t m_readahead_trigger_pos; | |
153 | ||
154 | /// Size of the next readahead request (barring changes due to alignment, etc.) | |
155 | uint64_t m_readahead_size; | |
156 | ||
157 | /// Number of pending readahead requests, as determined by inc_pending() and dec_pending() | |
158 | int m_pending; | |
159 | ||
160 | /// Lock for m_pending | |
11fdf7f2 | 161 | ceph::mutex m_pending_lock = ceph::make_mutex("Readahead::m_pending_lock"); |
7c673cae FG |
162 | |
163 | /// Waiters for pending readahead | |
164 | std::list<Context *> m_pending_waiting; | |
165 | }; | |
166 | ||
167 | #endif |