Line data Source code
1 : //! Common traits and structs for layers
2 :
3 : pub mod delta_layer;
4 : pub mod filter_iterator;
5 : pub mod image_layer;
6 : pub mod inmemory_layer;
7 : pub(crate) mod layer;
8 : mod layer_desc;
9 : mod layer_name;
10 : pub mod merge_iterator;
11 : pub mod split_writer;
12 :
13 : use crate::context::{AccessStatsBehavior, RequestContext};
14 : use crate::repository::Value;
15 : use crate::walrecord::NeonWalRecord;
16 : use bytes::Bytes;
17 : use pageserver_api::key::Key;
18 : use pageserver_api::keyspace::{KeySpace, KeySpaceRandomAccum};
19 : use std::cmp::{Ordering, Reverse};
20 : use std::collections::hash_map::Entry;
21 : use std::collections::{BinaryHeap, HashMap};
22 : use std::ops::Range;
23 : use std::sync::Arc;
24 : use std::time::{Duration, SystemTime, UNIX_EPOCH};
25 :
26 : use utils::lsn::Lsn;
27 :
28 : pub use delta_layer::{DeltaLayer, DeltaLayerWriter, ValueRef};
29 : pub use image_layer::{ImageLayer, ImageLayerWriter};
30 : pub use inmemory_layer::InMemoryLayer;
31 : pub use layer_desc::{PersistentLayerDesc, PersistentLayerKey};
32 : pub use layer_name::{DeltaLayerName, ImageLayerName, LayerName};
33 :
34 : pub(crate) use layer::{EvictionError, Layer, ResidentLayer};
35 :
36 : use self::inmemory_layer::InMemoryLayerFileId;
37 :
38 : use super::timeline::GetVectoredError;
39 : use super::PageReconstructError;
40 :
41 0 : pub fn range_overlaps<T>(a: &Range<T>, b: &Range<T>) -> bool
42 0 : where
43 0 : T: PartialOrd<T>,
44 0 : {
45 0 : if a.start < b.start {
46 0 : a.end > b.start
47 : } else {
48 0 : b.end > a.start
49 : }
50 0 : }
51 :
52 : /// Struct used to communicate across calls to 'get_value_reconstruct_data'.
53 : ///
54 : /// Before first call, you can fill in 'page_img' if you have an older cached
55 : /// version of the page available. That can save work in
56 : /// 'get_value_reconstruct_data', as it can stop searching for page versions
57 : /// when all the WAL records going back to the cached image have been collected.
58 : ///
59 : /// When get_value_reconstruct_data returns Complete, 'img' is set to an image
60 : /// of the page, or the oldest WAL record in 'records' is a will_init-type
61 : /// record that initializes the page without requiring a previous image.
62 : ///
63 : /// If 'get_page_reconstruct_data' returns Continue, some 'records' may have
64 : /// been collected, but there are more records outside the current layer. Pass
65 : /// the same ValueReconstructState struct in the next 'get_value_reconstruct_data'
66 : /// call, to collect more records.
67 : ///
68 : #[derive(Debug, Default)]
69 : pub(crate) struct ValueReconstructState {
70 : pub(crate) records: Vec<(Lsn, NeonWalRecord)>,
71 : pub(crate) img: Option<(Lsn, Bytes)>,
72 : }
73 :
74 : #[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
75 : pub(crate) enum ValueReconstructSituation {
76 : Complete,
77 : #[default]
78 : Continue,
79 : }
80 :
81 : /// Reconstruct data accumulated for a single key during a vectored get
82 : #[derive(Debug, Default, Clone)]
83 : pub(crate) struct VectoredValueReconstructState {
84 : pub(crate) records: Vec<(Lsn, NeonWalRecord)>,
85 : pub(crate) img: Option<(Lsn, Bytes)>,
86 :
87 : situation: ValueReconstructSituation,
88 : }
89 :
90 : impl VectoredValueReconstructState {
91 40329 : fn get_cached_lsn(&self) -> Option<Lsn> {
92 40329 : self.img.as_ref().map(|img| img.0)
93 40329 : }
94 : }
95 :
96 : impl From<VectoredValueReconstructState> for ValueReconstructState {
97 666816 : fn from(mut state: VectoredValueReconstructState) -> Self {
98 666816 : // walredo expects the records to be descending in terms of Lsn
99 666816 : state.records.sort_by_key(|(lsn, _)| Reverse(*lsn));
100 666816 :
101 666816 : ValueReconstructState {
102 666816 : records: state.records,
103 666816 : img: state.img,
104 666816 : }
105 666816 : }
106 : }
107 :
108 : /// Bag of data accumulated during a vectored get..
109 : pub(crate) struct ValuesReconstructState {
110 : /// The keys will be removed after `get_vectored` completes. The caller outside `Timeline`
111 : /// should not expect to get anything from this hashmap.
112 : pub(crate) keys: HashMap<Key, Result<VectoredValueReconstructState, PageReconstructError>>,
113 : /// The keys which are already retrieved
114 : keys_done: KeySpaceRandomAccum,
115 :
116 : /// The keys covered by the image layers
117 : keys_with_image_coverage: Option<Range<Key>>,
118 :
119 : // Statistics that are still accessible as a caller of `get_vectored_impl`.
120 : layers_visited: u32,
121 : delta_layers_visited: u32,
122 : }
123 :
124 : impl ValuesReconstructState {
125 626720 : pub(crate) fn new() -> Self {
126 626720 : Self {
127 626720 : keys: HashMap::new(),
128 626720 : keys_done: KeySpaceRandomAccum::new(),
129 626720 : keys_with_image_coverage: None,
130 626720 : layers_visited: 0,
131 626720 : delta_layers_visited: 0,
132 626720 : }
133 626720 : }
134 :
135 : /// Associate a key with the error which it encountered and mark it as done
136 0 : pub(crate) fn on_key_error(&mut self, key: Key, err: PageReconstructError) {
137 0 : let previous = self.keys.insert(key, Err(err));
138 0 : if let Some(Ok(state)) = previous {
139 0 : if state.situation == ValueReconstructSituation::Continue {
140 0 : self.keys_done.add_key(key);
141 0 : }
142 0 : }
143 0 : }
144 :
145 818299 : pub(crate) fn on_layer_visited(&mut self, layer: &ReadableLayer) {
146 818299 : self.layers_visited += 1;
147 818299 : if let ReadableLayer::PersistentLayer(layer) = layer {
148 212049 : if layer.layer_desc().is_delta() {
149 204092 : self.delta_layers_visited += 1;
150 204092 : }
151 606250 : }
152 818299 : }
153 :
154 194 : pub(crate) fn get_delta_layers_visited(&self) -> u32 {
155 194 : self.delta_layers_visited
156 194 : }
157 :
158 626490 : pub(crate) fn get_layers_visited(&self) -> u32 {
159 626490 : self.layers_visited
160 626490 : }
161 :
162 : /// This function is called after reading a keyspace from a layer.
163 : /// It checks if the read path has now moved past the cached Lsn for any keys.
164 : ///
165 : /// Implementation note: We intentionally iterate over the keys for which we've
166 : /// already collected some reconstruct data. This avoids scaling complexity with
167 : /// the size of the search space.
168 810342 : pub(crate) fn on_lsn_advanced(&mut self, keyspace: &KeySpace, advanced_to: Lsn) {
169 810342 : for (key, value) in self.keys.iter_mut() {
170 691101 : if !keyspace.contains(key) {
171 42144 : continue;
172 648957 : }
173 :
174 648957 : if let Ok(state) = value {
175 648957 : if state.situation != ValueReconstructSituation::Complete
176 324 : && state.get_cached_lsn() >= Some(advanced_to)
177 0 : {
178 0 : state.situation = ValueReconstructSituation::Complete;
179 0 : self.keys_done.add_key(*key);
180 648957 : }
181 0 : }
182 : }
183 810342 : }
184 :
185 : /// On hitting image layer, we can mark all keys in this range as done, because
186 : /// if the image layer does not contain a key, it is deleted/never added.
187 7969 : pub(crate) fn on_image_layer_visited(&mut self, key_range: &Range<Key>) {
188 7969 : let prev_val = self.keys_with_image_coverage.replace(key_range.clone());
189 7969 : assert_eq!(
190 : prev_val, None,
191 0 : "should consume the keyspace before the next iteration"
192 : );
193 7969 : }
194 :
195 : /// Update the state collected for a given key.
196 : /// Returns true if this was the last value needed for the key and false otherwise.
197 : ///
198 : /// If the key is done after the update, mark it as such.
199 667306 : pub(crate) fn update_key(
200 667306 : &mut self,
201 667306 : key: &Key,
202 667306 : lsn: Lsn,
203 667306 : value: Value,
204 667306 : ) -> ValueReconstructSituation {
205 667306 : let state = self
206 667306 : .keys
207 667306 : .entry(*key)
208 667306 : .or_insert(Ok(VectoredValueReconstructState::default()));
209 :
210 667306 : if let Ok(state) = state {
211 667306 : let key_done = match state.situation {
212 0 : ValueReconstructSituation::Complete => unreachable!(),
213 667306 : ValueReconstructSituation::Continue => match value {
214 666882 : Value::Image(img) => {
215 666882 : state.img = Some((lsn, img));
216 666882 : true
217 : }
218 424 : Value::WalRecord(rec) => {
219 424 : debug_assert!(
220 424 : Some(lsn) > state.get_cached_lsn(),
221 0 : "Attempt to collect a record below cached LSN for walredo: {} < {}",
222 0 : lsn,
223 0 : state
224 0 : .get_cached_lsn()
225 0 : .expect("Assertion can only fire if a cached lsn is present")
226 : );
227 :
228 424 : let will_init = rec.will_init();
229 424 : state.records.push((lsn, rec));
230 424 : will_init
231 : }
232 : },
233 : };
234 :
235 667306 : if key_done && state.situation == ValueReconstructSituation::Continue {
236 666886 : state.situation = ValueReconstructSituation::Complete;
237 666886 : self.keys_done.add_key(*key);
238 666886 : }
239 :
240 667306 : state.situation
241 : } else {
242 0 : ValueReconstructSituation::Complete
243 : }
244 667306 : }
245 :
246 : /// Returns the Lsn at which this key is cached if one exists.
247 : /// The read path should go no further than this Lsn for the given key.
248 1082231 : pub(crate) fn get_cached_lsn(&self, key: &Key) -> Option<Lsn> {
249 1082231 : self.keys
250 1082231 : .get(key)
251 1082231 : .and_then(|k| k.as_ref().ok())
252 1082231 : .and_then(|state| state.get_cached_lsn())
253 1082231 : }
254 :
255 : /// Returns the key space describing the keys that have
256 : /// been marked as completed since the last call to this function.
257 : /// Returns individual keys done, and the image layer coverage.
258 1671244 : pub(crate) fn consume_done_keys(&mut self) -> (KeySpace, Option<Range<Key>>) {
259 1671244 : (
260 1671244 : self.keys_done.consume_keyspace(),
261 1671244 : self.keys_with_image_coverage.take(),
262 1671244 : )
263 1671244 : }
264 : }
265 :
266 : impl Default for ValuesReconstructState {
267 240 : fn default() -> Self {
268 240 : Self::new()
269 240 : }
270 : }
271 :
272 : /// A key that uniquely identifies a layer in a timeline
273 : #[derive(Debug, PartialEq, Eq, Clone, Hash)]
274 : pub(crate) enum LayerId {
275 : PersitentLayerId(PersistentLayerKey),
276 : InMemoryLayerId(InMemoryLayerFileId),
277 : }
278 :
279 : /// Uniquely identify a layer visit by the layer
280 : /// and LSN floor (or start LSN) of the reads.
281 : /// The layer itself is not enough since we may
282 : /// have different LSN lower bounds for delta layer reads.
283 : #[derive(Debug, PartialEq, Eq, Clone, Hash)]
284 : struct LayerToVisitId {
285 : layer_id: LayerId,
286 : lsn_floor: Lsn,
287 : }
288 :
289 : /// Layer wrapper for the read path. Note that it is valid
290 : /// to use these layers even after external operations have
291 : /// been performed on them (compaction, freeze, etc.).
292 : #[derive(Debug)]
293 : pub(crate) enum ReadableLayer {
294 : PersistentLayer(Layer),
295 : InMemoryLayer(Arc<InMemoryLayer>),
296 : }
297 :
298 : /// A partial description of a read to be done.
299 : #[derive(Debug, Clone)]
300 : struct LayerVisit {
301 : /// An id used to resolve the readable layer within the fringe
302 : layer_to_visit_id: LayerToVisitId,
303 : /// Lsn range for the read, used for selecting the next read
304 : lsn_range: Range<Lsn>,
305 : }
306 :
307 : /// Data structure which maintains a fringe of layers for the
308 : /// read path. The fringe is the set of layers which intersects
309 : /// the current keyspace that the search is descending on.
310 : /// Each layer tracks the keyspace that intersects it.
311 : ///
312 : /// The fringe must appear sorted by Lsn. Hence, it uses
313 : /// a two layer indexing scheme.
314 : #[derive(Debug)]
315 : pub(crate) struct LayerFringe {
316 : planned_visits_by_lsn: BinaryHeap<LayerVisit>,
317 : visit_reads: HashMap<LayerToVisitId, LayerVisitReads>,
318 : }
319 :
320 : #[derive(Debug)]
321 : struct LayerVisitReads {
322 : layer: ReadableLayer,
323 : target_keyspace: KeySpaceRandomAccum,
324 : }
325 :
326 : impl LayerFringe {
327 852945 : pub(crate) fn new() -> Self {
328 852945 : LayerFringe {
329 852945 : planned_visits_by_lsn: BinaryHeap::new(),
330 852945 : visit_reads: HashMap::new(),
331 852945 : }
332 852945 : }
333 :
334 1671244 : pub(crate) fn next_layer(&mut self) -> Option<(ReadableLayer, KeySpace, Range<Lsn>)> {
335 1671244 : let read_desc = match self.planned_visits_by_lsn.pop() {
336 818299 : Some(desc) => desc,
337 852945 : None => return None,
338 : };
339 :
340 818299 : let removed = self.visit_reads.remove_entry(&read_desc.layer_to_visit_id);
341 818299 :
342 818299 : match removed {
343 : Some((
344 : _,
345 : LayerVisitReads {
346 818299 : layer,
347 818299 : mut target_keyspace,
348 818299 : },
349 818299 : )) => Some((
350 818299 : layer,
351 818299 : target_keyspace.consume_keyspace(),
352 818299 : read_desc.lsn_range,
353 818299 : )),
354 0 : None => unreachable!("fringe internals are always consistent"),
355 : }
356 1671244 : }
357 :
358 882038 : pub(crate) fn update(
359 882038 : &mut self,
360 882038 : layer: ReadableLayer,
361 882038 : keyspace: KeySpace,
362 882038 : lsn_range: Range<Lsn>,
363 882038 : ) {
364 882038 : let layer_to_visit_id = LayerToVisitId {
365 882038 : layer_id: layer.id(),
366 882038 : lsn_floor: lsn_range.start,
367 882038 : };
368 882038 :
369 882038 : let entry = self.visit_reads.entry(layer_to_visit_id.clone());
370 882038 : match entry {
371 63739 : Entry::Occupied(mut entry) => {
372 63739 : entry.get_mut().target_keyspace.add_keyspace(keyspace);
373 63739 : }
374 818299 : Entry::Vacant(entry) => {
375 818299 : self.planned_visits_by_lsn.push(LayerVisit {
376 818299 : lsn_range,
377 818299 : layer_to_visit_id: layer_to_visit_id.clone(),
378 818299 : });
379 818299 : let mut accum = KeySpaceRandomAccum::new();
380 818299 : accum.add_keyspace(keyspace);
381 818299 : entry.insert(LayerVisitReads {
382 818299 : layer,
383 818299 : target_keyspace: accum,
384 818299 : });
385 818299 : }
386 : }
387 882038 : }
388 : }
389 :
390 : impl Default for LayerFringe {
391 0 : fn default() -> Self {
392 0 : Self::new()
393 0 : }
394 : }
395 :
396 : impl Ord for LayerVisit {
397 22 : fn cmp(&self, other: &Self) -> Ordering {
398 22 : let ord = self.lsn_range.end.cmp(&other.lsn_range.end);
399 22 : if ord == std::cmp::Ordering::Equal {
400 18 : self.lsn_range.start.cmp(&other.lsn_range.start).reverse()
401 : } else {
402 4 : ord
403 : }
404 22 : }
405 : }
406 :
407 : impl PartialOrd for LayerVisit {
408 22 : fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
409 22 : Some(self.cmp(other))
410 22 : }
411 : }
412 :
413 : impl PartialEq for LayerVisit {
414 0 : fn eq(&self, other: &Self) -> bool {
415 0 : self.lsn_range == other.lsn_range
416 0 : }
417 : }
418 :
419 : impl Eq for LayerVisit {}
420 :
421 : impl ReadableLayer {
422 882038 : pub(crate) fn id(&self) -> LayerId {
423 882038 : match self {
424 275788 : Self::PersistentLayer(layer) => LayerId::PersitentLayerId(layer.layer_desc().key()),
425 606250 : Self::InMemoryLayer(layer) => LayerId::InMemoryLayerId(layer.file_id()),
426 : }
427 882038 : }
428 :
429 818299 : pub(crate) async fn get_values_reconstruct_data(
430 818299 : &self,
431 818299 : keyspace: KeySpace,
432 818299 : lsn_range: Range<Lsn>,
433 818299 : reconstruct_state: &mut ValuesReconstructState,
434 818299 : ctx: &RequestContext,
435 818299 : ) -> Result<(), GetVectoredError> {
436 818299 : match self {
437 212049 : ReadableLayer::PersistentLayer(layer) => {
438 212049 : layer
439 212049 : .get_values_reconstruct_data(keyspace, lsn_range, reconstruct_state, ctx)
440 90213 : .await
441 : }
442 606250 : ReadableLayer::InMemoryLayer(layer) => {
443 606250 : layer
444 606250 : .get_values_reconstruct_data(keyspace, lsn_range.end, reconstruct_state, ctx)
445 87175 : .await
446 : }
447 : }
448 818299 : }
449 : }
450 :
451 : /// Layers contain a hint indicating whether they are likely to be used for reads.
452 : ///
453 : /// This is a hint rather than an authoritative value, so that we do not have to update it synchronously
454 : /// when changing the visibility of layers (for example when creating a branch that makes some previously
455 : /// covered layers visible). It should be used for cache management but not for correctness-critical checks.
456 : #[derive(Debug, Clone, PartialEq, Eq)]
457 : pub enum LayerVisibilityHint {
458 : /// A Visible layer might be read while serving a read, because there is not an image layer between it
459 : /// and a readable LSN (the tip of the branch or a child's branch point)
460 : Visible,
461 : /// A Covered layer probably won't be read right now, but _can_ be read in future if someone creates
462 : /// a branch or ephemeral endpoint at an LSN below the layer that covers this.
463 : Covered,
464 : }
465 :
466 : pub(crate) struct LayerAccessStats(std::sync::atomic::AtomicU64);
467 :
468 0 : #[derive(Clone, Copy, strum_macros::EnumString)]
469 : pub(crate) enum LayerAccessStatsReset {
470 : NoReset,
471 : AllStats,
472 : }
473 :
474 : impl Default for LayerAccessStats {
475 1716 : fn default() -> Self {
476 1716 : // Default value is to assume resident since creation time, and visible.
477 1716 : let (_mask, mut value) = Self::to_low_res_timestamp(Self::RTIME_SHIFT, SystemTime::now());
478 1716 : value |= 0x1 << Self::VISIBILITY_SHIFT;
479 1716 :
480 1716 : Self(std::sync::atomic::AtomicU64::new(value))
481 1716 : }
482 : }
483 :
484 : // Efficient store of two very-low-resolution timestamps and some bits. Used for storing last access time and
485 : // last residence change time.
486 : impl LayerAccessStats {
487 : // How many high bits to drop from a u32 timestamp?
488 : // - Only storing up to a u32 timestamp will work fine until 2038 (if this code is still in use
489 : // after that, this software has been very successful!)
490 : // - Dropping the top bit is implicitly safe because unix timestamps are meant to be
491 : // stored in an i32, so they never used it.
492 : // - Dropping the next two bits is safe because this code is only running on systems in
493 : // years >= 2024, and these bits have been 1 since 2021
494 : //
495 : // Therefore we may store only 28 bits for a timestamp with one second resolution. We do
496 : // this truncation to make space for some flags in the high bits of our u64.
497 : const TS_DROP_HIGH_BITS: u32 = u32::count_ones(Self::TS_ONES) + 1;
498 : const TS_MASK: u32 = 0x1f_ff_ff_ff;
499 : const TS_ONES: u32 = 0x60_00_00_00;
500 :
501 : const ATIME_SHIFT: u32 = 0;
502 : const RTIME_SHIFT: u32 = 32 - Self::TS_DROP_HIGH_BITS;
503 : const VISIBILITY_SHIFT: u32 = 64 - 2 * Self::TS_DROP_HIGH_BITS;
504 :
505 212545 : fn write_bits(&self, mask: u64, value: u64) -> u64 {
506 212545 : self.0
507 212545 : .fetch_update(
508 212545 : // TODO: decide what orderings are correct
509 212545 : std::sync::atomic::Ordering::Relaxed,
510 212545 : std::sync::atomic::Ordering::Relaxed,
511 212545 : |v| Some((v & !mask) | (value & mask)),
512 212545 : )
513 212545 : .expect("Inner function is infallible")
514 212545 : }
515 :
516 213935 : fn to_low_res_timestamp(shift: u32, time: SystemTime) -> (u64, u64) {
517 213935 : // Drop the low three bits of the timestamp, for an ~8s accuracy
518 213935 : let timestamp = time.duration_since(UNIX_EPOCH).unwrap().as_secs() & (Self::TS_MASK as u64);
519 213935 :
520 213935 : ((Self::TS_MASK as u64) << shift, timestamp << shift)
521 213935 : }
522 :
523 62 : fn read_low_res_timestamp(&self, shift: u32) -> Option<SystemTime> {
524 62 : let read = self.0.load(std::sync::atomic::Ordering::Relaxed);
525 62 :
526 62 : let ts_bits = (read & ((Self::TS_MASK as u64) << shift)) >> shift;
527 62 : if ts_bits == 0 {
528 24 : None
529 : } else {
530 38 : Some(UNIX_EPOCH + Duration::from_secs(ts_bits | (Self::TS_ONES as u64)))
531 : }
532 62 : }
533 :
534 : /// Record a change in layer residency.
535 : ///
536 : /// Recording the event must happen while holding the layer map lock to
537 : /// ensure that latest-activity-threshold-based layer eviction (eviction_task.rs)
538 : /// can do an "imitate access" to this layer, before it observes `now-latest_activity() > threshold`.
539 : ///
540 : /// If we instead recorded the residence event with a timestamp from before grabbing the layer map lock,
541 : /// the following race could happen:
542 : ///
543 : /// - Compact: Write out an L1 layer from several L0 layers. This records residence event LayerCreate with the current timestamp.
544 : /// - Eviction: imitate access logical size calculation. This accesses the L0 layers because the L1 layer is not yet in the layer map.
545 : /// - Compact: Grab layer map lock, add the new L1 to layer map and remove the L0s, release layer map lock.
546 : /// - Eviction: observes the new L1 layer whose only activity timestamp is the LayerCreate event.
547 26 : pub(crate) fn record_residence_event_at(&self, now: SystemTime) {
548 26 : let (mask, value) = Self::to_low_res_timestamp(Self::RTIME_SHIFT, now);
549 26 : self.write_bits(mask, value);
550 26 : }
551 :
552 24 : pub(crate) fn record_residence_event(&self) {
553 24 : self.record_residence_event_at(SystemTime::now())
554 24 : }
555 :
556 212193 : fn record_access_at(&self, now: SystemTime) -> bool {
557 212193 : let (mut mask, mut value) = Self::to_low_res_timestamp(Self::ATIME_SHIFT, now);
558 212193 :
559 212193 : // A layer which is accessed must be visible.
560 212193 : mask |= 0x1 << Self::VISIBILITY_SHIFT;
561 212193 : value |= 0x1 << Self::VISIBILITY_SHIFT;
562 212193 :
563 212193 : let old_bits = self.write_bits(mask, value);
564 2 : !matches!(
565 212193 : self.decode_visibility(old_bits),
566 : LayerVisibilityHint::Visible
567 : )
568 212193 : }
569 :
570 : /// Returns true if we modified the layer's visibility to set it to Visible implicitly
571 : /// as a result of this access
572 212463 : pub(crate) fn record_access(&self, ctx: &RequestContext) -> bool {
573 212463 : if ctx.access_stats_behavior() == AccessStatsBehavior::Skip {
574 276 : return false;
575 212187 : }
576 212187 :
577 212187 : self.record_access_at(SystemTime::now())
578 212463 : }
579 :
580 0 : fn as_api_model(
581 0 : &self,
582 0 : reset: LayerAccessStatsReset,
583 0 : ) -> pageserver_api::models::LayerAccessStats {
584 0 : let ret = pageserver_api::models::LayerAccessStats {
585 0 : access_time: self
586 0 : .read_low_res_timestamp(Self::ATIME_SHIFT)
587 0 : .unwrap_or(UNIX_EPOCH),
588 0 : residence_time: self
589 0 : .read_low_res_timestamp(Self::RTIME_SHIFT)
590 0 : .unwrap_or(UNIX_EPOCH),
591 0 : visible: matches!(self.visibility(), LayerVisibilityHint::Visible),
592 : };
593 0 : match reset {
594 0 : LayerAccessStatsReset::NoReset => {}
595 0 : LayerAccessStatsReset::AllStats => {
596 0 : self.write_bits((Self::TS_MASK as u64) << Self::ATIME_SHIFT, 0x0);
597 0 : self.write_bits((Self::TS_MASK as u64) << Self::RTIME_SHIFT, 0x0);
598 0 : }
599 : }
600 0 : ret
601 0 : }
602 :
603 : /// Get the latest access timestamp, falling back to latest residence event. The latest residence event
604 : /// will be this Layer's construction time, if its residence hasn't changed since then.
605 16 : pub(crate) fn latest_activity(&self) -> SystemTime {
606 16 : if let Some(t) = self.read_low_res_timestamp(Self::ATIME_SHIFT) {
607 6 : t
608 : } else {
609 10 : self.read_low_res_timestamp(Self::RTIME_SHIFT)
610 10 : .expect("Residence time is set on construction")
611 : }
612 16 : }
613 :
614 : /// Whether this layer has been accessed (excluding in [`AccessStatsBehavior::Skip`]).
615 : ///
616 : /// This indicates whether the layer has been used for some purpose that would motivate
617 : /// us to keep it on disk, such as for serving a getpage request.
618 18 : fn accessed(&self) -> bool {
619 18 : // Consider it accessed if the most recent access is more recent than
620 18 : // the most recent change in residence status.
621 18 : match (
622 18 : self.read_low_res_timestamp(Self::ATIME_SHIFT),
623 18 : self.read_low_res_timestamp(Self::RTIME_SHIFT),
624 : ) {
625 14 : (None, _) => false,
626 0 : (Some(_), None) => true,
627 4 : (Some(a), Some(r)) => a >= r,
628 : }
629 18 : }
630 :
631 : /// Helper for extracting the visibility hint from the literal value of our inner u64
632 213081 : fn decode_visibility(&self, bits: u64) -> LayerVisibilityHint {
633 213081 : match (bits >> Self::VISIBILITY_SHIFT) & 0x1 {
634 213059 : 1 => LayerVisibilityHint::Visible,
635 22 : 0 => LayerVisibilityHint::Covered,
636 0 : _ => unreachable!(),
637 : }
638 213081 : }
639 :
640 : /// Returns the old value which has been replaced
641 326 : pub(crate) fn set_visibility(&self, visibility: LayerVisibilityHint) -> LayerVisibilityHint {
642 326 : let value = match visibility {
643 274 : LayerVisibilityHint::Visible => 0x1 << Self::VISIBILITY_SHIFT,
644 52 : LayerVisibilityHint::Covered => 0x0,
645 : };
646 :
647 326 : let old_bits = self.write_bits(0x1 << Self::VISIBILITY_SHIFT, value);
648 326 : self.decode_visibility(old_bits)
649 326 : }
650 :
651 562 : pub(crate) fn visibility(&self) -> LayerVisibilityHint {
652 562 : let read = self.0.load(std::sync::atomic::Ordering::Relaxed);
653 562 : self.decode_visibility(read)
654 562 : }
655 : }
656 :
657 : /// Get a layer descriptor from a layer.
658 : pub(crate) trait AsLayerDesc {
659 : /// Get the layer descriptor.
660 : fn layer_desc(&self) -> &PersistentLayerDesc;
661 : }
662 :
663 : pub mod tests {
664 : use pageserver_api::shard::TenantShardId;
665 : use utils::id::TimelineId;
666 :
667 : use super::*;
668 :
669 : impl From<DeltaLayerName> for PersistentLayerDesc {
670 0 : fn from(value: DeltaLayerName) -> Self {
671 0 : PersistentLayerDesc::new_delta(
672 0 : TenantShardId::from([0; 18]),
673 0 : TimelineId::from_array([0; 16]),
674 0 : value.key_range,
675 0 : value.lsn_range,
676 0 : 233,
677 0 : )
678 0 : }
679 : }
680 :
681 : impl From<ImageLayerName> for PersistentLayerDesc {
682 0 : fn from(value: ImageLayerName) -> Self {
683 0 : PersistentLayerDesc::new_img(
684 0 : TenantShardId::from([0; 18]),
685 0 : TimelineId::from_array([0; 16]),
686 0 : value.key_range,
687 0 : value.lsn,
688 0 : 233,
689 0 : )
690 0 : }
691 : }
692 :
693 : impl From<LayerName> for PersistentLayerDesc {
694 0 : fn from(value: LayerName) -> Self {
695 0 : match value {
696 0 : LayerName::Delta(d) => Self::from(d),
697 0 : LayerName::Image(i) => Self::from(i),
698 : }
699 0 : }
700 : }
701 : }
702 :
703 : /// Range wrapping newtype, which uses display to render Debug.
704 : ///
705 : /// Useful with `Key`, which has too verbose `{:?}` for printing multiple layers.
706 : struct RangeDisplayDebug<'a, T: std::fmt::Display>(&'a Range<T>);
707 :
708 : impl<T: std::fmt::Display> std::fmt::Debug for RangeDisplayDebug<'_, T> {
709 0 : fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
710 0 : write!(f, "{}..{}", self.0.start, self.0.end)
711 0 : }
712 : }
|