Line data Source code
1 : //! Common traits and structs for layers
2 :
3 : pub mod delta_layer;
4 : pub mod image_layer;
5 : pub mod inmemory_layer;
6 : pub(crate) mod layer;
7 : mod layer_desc;
8 : mod layer_name;
9 : pub mod merge_iterator;
10 :
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 121795 : fn get_cached_lsn(&self) -> Option<Lsn> {
92 121795 : self.img.as_ref().map(|img| img.0)
93 121795 : }
94 : }
95 :
96 : impl From<VectoredValueReconstructState> for ValueReconstructState {
97 2000442 : fn from(mut state: VectoredValueReconstructState) -> Self {
98 2000442 : // walredo expects the records to be descending in terms of Lsn
99 2000442 : state.records.sort_by_key(|(lsn, _)| Reverse(*lsn));
100 2000442 :
101 2000442 : ValueReconstructState {
102 2000442 : records: state.records,
103 2000442 : img: state.img,
104 2000442 : }
105 2000442 : }
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 1881072 : pub(crate) fn new() -> Self {
126 1881072 : Self {
127 1881072 : keys: HashMap::new(),
128 1881072 : keys_done: KeySpaceRandomAccum::new(),
129 1881072 : keys_with_image_coverage: None,
130 1881072 : layers_visited: 0,
131 1881072 : delta_layers_visited: 0,
132 1881072 : }
133 1881072 : }
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 2457616 : pub(crate) fn on_layer_visited(&mut self, layer: &ReadableLayer) {
146 2457616 : self.layers_visited += 1;
147 2457616 : if let ReadableLayer::PersistentLayer(layer) = layer {
148 638223 : if layer.layer_desc().is_delta() {
149 614121 : self.delta_layers_visited += 1;
150 614121 : }
151 1819393 : }
152 2457616 : }
153 :
154 588 : pub(crate) fn get_delta_layers_visited(&self) -> u32 {
155 588 : self.delta_layers_visited
156 588 : }
157 :
158 1880382 : pub(crate) fn get_layers_visited(&self) -> u32 {
159 1880382 : self.layers_visited
160 1880382 : }
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 2433514 : pub(crate) fn on_lsn_advanced(&mut self, keyspace: &KeySpace, advanced_to: Lsn) {
169 2433514 : for (key, value) in self.keys.iter_mut() {
170 2073490 : if !keyspace.contains(key) {
171 126990 : continue;
172 1946500 : }
173 :
174 1946500 : if let Ok(state) = value {
175 1946500 : if state.situation != ValueReconstructSituation::Complete
176 990 : && state.get_cached_lsn() >= Some(advanced_to)
177 0 : {
178 0 : state.situation = ValueReconstructSituation::Complete;
179 0 : self.keys_done.add_key(*key);
180 1946500 : }
181 0 : }
182 : }
183 2433514 : }
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 24138 : pub(crate) fn on_image_layer_visited(&mut self, key_range: &Range<Key>) {
188 24138 : let prev_val = self.keys_with_image_coverage.replace(key_range.clone());
189 24138 : assert_eq!(
190 : prev_val, None,
191 0 : "should consume the keyspace before the next iteration"
192 : );
193 24138 : }
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 2001876 : pub(crate) fn update_key(
200 2001876 : &mut self,
201 2001876 : key: &Key,
202 2001876 : lsn: Lsn,
203 2001876 : value: Value,
204 2001876 : ) -> ValueReconstructSituation {
205 2001876 : let state = self
206 2001876 : .keys
207 2001876 : .entry(*key)
208 2001876 : .or_insert(Ok(VectoredValueReconstructState::default()));
209 :
210 2001876 : if let Ok(state) = state {
211 2001876 : let key_done = match state.situation {
212 0 : ValueReconstructSituation::Complete => unreachable!(),
213 2001876 : ValueReconstructSituation::Continue => match value {
214 2000652 : Value::Image(img) => {
215 2000652 : state.img = Some((lsn, img));
216 2000652 : true
217 : }
218 1224 : Value::WalRecord(rec) => {
219 1224 : debug_assert!(
220 1224 : 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 1224 : let will_init = rec.will_init();
229 1224 : state.records.push((lsn, rec));
230 1224 : will_init
231 : }
232 : },
233 : };
234 :
235 2001876 : if key_done && state.situation == ValueReconstructSituation::Continue {
236 2000652 : state.situation = ValueReconstructSituation::Complete;
237 2000652 : self.keys_done.add_key(*key);
238 2000652 : }
239 :
240 2001876 : state.situation
241 : } else {
242 0 : ValueReconstructSituation::Complete
243 : }
244 2001876 : }
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 3248828 : pub(crate) fn get_cached_lsn(&self, key: &Key) -> Option<Lsn> {
249 3248828 : self.keys
250 3248828 : .get(key)
251 3248828 : .and_then(|k| k.as_ref().ok())
252 3248828 : .and_then(|state| state.get_cached_lsn())
253 3248828 : }
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 5016376 : pub(crate) fn consume_done_keys(&mut self) -> (KeySpace, Option<Range<Key>>) {
259 5016376 : (
260 5016376 : self.keys_done.consume_keyspace(),
261 5016376 : self.keys_with_image_coverage.take(),
262 5016376 : )
263 5016376 : }
264 : }
265 :
266 : impl Default for ValuesReconstructState {
267 762 : fn default() -> Self {
268 762 : Self::new()
269 762 : }
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 : /// Layer wrapper for the read path. Note that it is valid
280 : /// to use these layers even after external operations have
281 : /// been performed on them (compaction, freeze, etc.).
282 : #[derive(Debug)]
283 : pub(crate) enum ReadableLayer {
284 : PersistentLayer(Layer),
285 : InMemoryLayer(Arc<InMemoryLayer>),
286 : }
287 :
288 : /// A partial description of a read to be done.
289 : #[derive(Debug, Clone)]
290 : struct ReadDesc {
291 : /// An id used to resolve the readable layer within the fringe
292 : layer_id: LayerId,
293 : /// Lsn range for the read, used for selecting the next read
294 : lsn_range: Range<Lsn>,
295 : }
296 :
297 : /// Data structure which maintains a fringe of layers for the
298 : /// read path. The fringe is the set of layers which intersects
299 : /// the current keyspace that the search is descending on.
300 : /// Each layer tracks the keyspace that intersects it.
301 : ///
302 : /// The fringe must appear sorted by Lsn. Hence, it uses
303 : /// a two layer indexing scheme.
304 : #[derive(Debug)]
305 : pub(crate) struct LayerFringe {
306 : planned_reads_by_lsn: BinaryHeap<ReadDesc>,
307 : layers: HashMap<LayerId, LayerKeyspace>,
308 : }
309 :
310 : #[derive(Debug)]
311 : struct LayerKeyspace {
312 : layer: ReadableLayer,
313 : target_keyspace: KeySpaceRandomAccum,
314 : }
315 :
316 : impl LayerFringe {
317 2558760 : pub(crate) fn new() -> Self {
318 2558760 : LayerFringe {
319 2558760 : planned_reads_by_lsn: BinaryHeap::new(),
320 2558760 : layers: HashMap::new(),
321 2558760 : }
322 2558760 : }
323 :
324 5016376 : pub(crate) fn next_layer(&mut self) -> Option<(ReadableLayer, KeySpace, Range<Lsn>)> {
325 5016376 : let read_desc = match self.planned_reads_by_lsn.pop() {
326 2457616 : Some(desc) => desc,
327 2558760 : None => return None,
328 : };
329 :
330 2457616 : let removed = self.layers.remove_entry(&read_desc.layer_id);
331 2457616 :
332 2457616 : match removed {
333 : Some((
334 : _,
335 : LayerKeyspace {
336 2457616 : layer,
337 2457616 : mut target_keyspace,
338 2457616 : },
339 2457616 : )) => Some((
340 2457616 : layer,
341 2457616 : target_keyspace.consume_keyspace(),
342 2457616 : read_desc.lsn_range,
343 2457616 : )),
344 0 : None => unreachable!("fringe internals are always consistent"),
345 : }
346 5016376 : }
347 :
348 2649225 : pub(crate) fn update(
349 2649225 : &mut self,
350 2649225 : layer: ReadableLayer,
351 2649225 : keyspace: KeySpace,
352 2649225 : lsn_range: Range<Lsn>,
353 2649225 : ) {
354 2649225 : let layer_id = layer.id();
355 2649225 : let entry = self.layers.entry(layer_id.clone());
356 2649225 : match entry {
357 191609 : Entry::Occupied(mut entry) => {
358 191609 : entry.get_mut().target_keyspace.add_keyspace(keyspace);
359 191609 : }
360 2457616 : Entry::Vacant(entry) => {
361 2457616 : self.planned_reads_by_lsn.push(ReadDesc {
362 2457616 : lsn_range,
363 2457616 : layer_id: layer_id.clone(),
364 2457616 : });
365 2457616 : let mut accum = KeySpaceRandomAccum::new();
366 2457616 : accum.add_keyspace(keyspace);
367 2457616 : entry.insert(LayerKeyspace {
368 2457616 : layer,
369 2457616 : target_keyspace: accum,
370 2457616 : });
371 2457616 : }
372 : }
373 2649225 : }
374 : }
375 :
376 : impl Default for LayerFringe {
377 0 : fn default() -> Self {
378 0 : Self::new()
379 0 : }
380 : }
381 :
382 : impl Ord for ReadDesc {
383 48 : fn cmp(&self, other: &Self) -> Ordering {
384 48 : let ord = self.lsn_range.end.cmp(&other.lsn_range.end);
385 48 : if ord == std::cmp::Ordering::Equal {
386 48 : self.lsn_range.start.cmp(&other.lsn_range.start).reverse()
387 : } else {
388 0 : ord
389 : }
390 48 : }
391 : }
392 :
393 : impl PartialOrd for ReadDesc {
394 48 : fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
395 48 : Some(self.cmp(other))
396 48 : }
397 : }
398 :
399 : impl PartialEq for ReadDesc {
400 0 : fn eq(&self, other: &Self) -> bool {
401 0 : self.lsn_range == other.lsn_range
402 0 : }
403 : }
404 :
405 : impl Eq for ReadDesc {}
406 :
407 : impl ReadableLayer {
408 2649225 : pub(crate) fn id(&self) -> LayerId {
409 2649225 : match self {
410 829832 : Self::PersistentLayer(layer) => LayerId::PersitentLayerId(layer.layer_desc().key()),
411 1819393 : Self::InMemoryLayer(layer) => LayerId::InMemoryLayerId(layer.file_id()),
412 : }
413 2649225 : }
414 :
415 2457616 : pub(crate) async fn get_values_reconstruct_data(
416 2457616 : &self,
417 2457616 : keyspace: KeySpace,
418 2457616 : lsn_range: Range<Lsn>,
419 2457616 : reconstruct_state: &mut ValuesReconstructState,
420 2457616 : ctx: &RequestContext,
421 2457616 : ) -> Result<(), GetVectoredError> {
422 2457616 : match self {
423 638223 : ReadableLayer::PersistentLayer(layer) => {
424 638223 : layer
425 638223 : .get_values_reconstruct_data(keyspace, lsn_range, reconstruct_state, ctx)
426 286250 : .await
427 : }
428 1819393 : ReadableLayer::InMemoryLayer(layer) => {
429 1819393 : layer
430 1819393 : .get_values_reconstruct_data(keyspace, lsn_range.end, reconstruct_state, ctx)
431 264283 : .await
432 : }
433 : }
434 2457616 : }
435 : }
436 :
437 : /// Layers contain a hint indicating whether they are likely to be used for reads. This is a hint rather
438 : /// than an authoritative value, so that we do not have to update it synchronously when changing the visibility
439 : /// of layers (for example when creating a branch that makes some previously covered layers visible). It should
440 : /// be used for cache management but not for correctness-critical checks.
441 : #[derive(Debug, Clone, PartialEq, Eq)]
442 : pub enum LayerVisibilityHint {
443 : /// A Visible layer might be read while serving a read, because there is not an image layer between it
444 : /// and a readable LSN (the tip of the branch or a child's branch point)
445 : Visible,
446 : /// A Covered layer probably won't be read right now, but _can_ be read in future if someone creates
447 : /// a branch or ephemeral endpoint at an LSN below the layer that covers this.
448 : Covered,
449 : }
450 :
451 : pub(crate) struct LayerAccessStats(std::sync::atomic::AtomicU64);
452 :
453 0 : #[derive(Clone, Copy, strum_macros::EnumString)]
454 : pub(crate) enum LayerAccessStatsReset {
455 : NoReset,
456 : AllStats,
457 : }
458 :
459 : impl Default for LayerAccessStats {
460 5178 : fn default() -> Self {
461 5178 : // Default value is to assume resident since creation time, and visible.
462 5178 : let (_mask, mut value) = Self::to_low_res_timestamp(Self::RTIME_SHIFT, SystemTime::now());
463 5178 : value |= 0x1 << Self::VISIBILITY_SHIFT;
464 5178 :
465 5178 : Self(std::sync::atomic::AtomicU64::new(value))
466 5178 : }
467 : }
468 :
469 : // Efficient store of two very-low-resolution timestamps and some bits. Used for storing last access time and
470 : // last residence change time.
471 : impl LayerAccessStats {
472 : // How many high bits to drop from a u32 timestamp?
473 : // - Only storing up to a u32 timestamp will work fine until 2038 (if this code is still in use
474 : // after that, this software has been very successful!)
475 : // - Dropping the top bit is implicitly safe because unix timestamps are meant to be
476 : // stored in an i32, so they never used it.
477 : // - Dropping the next two bits is safe because this code is only running on systems in
478 : // years >= 2024, and these bits have been 1 since 2021
479 : //
480 : // Therefore we may store only 28 bits for a timestamp with one second resolution. We do
481 : // this truncation to make space for some flags in the high bits of our u64.
482 : const TS_DROP_HIGH_BITS: u32 = u32::count_ones(Self::TS_ONES) + 1;
483 : const TS_MASK: u32 = 0x1f_ff_ff_ff;
484 : const TS_ONES: u32 = 0x60_00_00_00;
485 :
486 : const ATIME_SHIFT: u32 = 0;
487 : const RTIME_SHIFT: u32 = 32 - Self::TS_DROP_HIGH_BITS;
488 : const VISIBILITY_SHIFT: u32 = 64 - 2 * Self::TS_DROP_HIGH_BITS;
489 :
490 646815 : fn write_bits(&self, mask: u64, value: u64) -> u64 {
491 646815 : self.0
492 646815 : .fetch_update(
493 646815 : // TODO: decide what orderings are correct
494 646815 : std::sync::atomic::Ordering::Relaxed,
495 646815 : std::sync::atomic::Ordering::Relaxed,
496 646815 : |v| Some((v & !mask) | (value & mask)),
497 646815 : )
498 646815 : .expect("Inner function is infallible")
499 646815 : }
500 :
501 643899 : fn to_low_res_timestamp(shift: u32, time: SystemTime) -> (u64, u64) {
502 643899 : // Drop the low three bits of the timestamp, for an ~8s accuracy
503 643899 : let timestamp = time.duration_since(UNIX_EPOCH).unwrap().as_secs() & (Self::TS_MASK as u64);
504 643899 :
505 643899 : ((Self::TS_MASK as u64) << shift, timestamp << shift)
506 643899 : }
507 :
508 186 : fn read_low_res_timestamp(&self, shift: u32) -> Option<SystemTime> {
509 186 : let read = self.0.load(std::sync::atomic::Ordering::Relaxed);
510 186 :
511 186 : let ts_bits = (read & ((Self::TS_MASK as u64) << shift)) >> shift;
512 186 : if ts_bits == 0 {
513 72 : None
514 : } else {
515 114 : Some(UNIX_EPOCH + Duration::from_secs(ts_bits | (Self::TS_ONES as u64)))
516 : }
517 186 : }
518 :
519 : /// Record a change in layer residency.
520 : ///
521 : /// Recording the event must happen while holding the layer map lock to
522 : /// ensure that latest-activity-threshold-based layer eviction (eviction_task.rs)
523 : /// can do an "imitate access" to this layer, before it observes `now-latest_activity() > threshold`.
524 : ///
525 : /// If we instead recorded the residence event with a timestamp from before grabbing the layer map lock,
526 : /// the following race could happen:
527 : ///
528 : /// - Compact: Write out an L1 layer from several L0 layers. This records residence event LayerCreate with the current timestamp.
529 : /// - Eviction: imitate access logical size calculation. This accesses the L0 layers because the L1 layer is not yet in the layer map.
530 : /// - Compact: Grab layer map lock, add the new L1 to layer map and remove the L0s, release layer map lock.
531 : /// - Eviction: observes the new L1 layer whose only activity timestamp is the LayerCreate event.
532 78 : pub(crate) fn record_residence_event_at(&self, now: SystemTime) {
533 78 : let (mask, value) = Self::to_low_res_timestamp(Self::RTIME_SHIFT, now);
534 78 : self.write_bits(mask, value);
535 78 : }
536 :
537 72 : pub(crate) fn record_residence_event(&self) {
538 72 : self.record_residence_event_at(SystemTime::now())
539 72 : }
540 :
541 638643 : fn record_access_at(&self, now: SystemTime) -> bool {
542 638643 : let (mut mask, mut value) = Self::to_low_res_timestamp(Self::ATIME_SHIFT, now);
543 638643 :
544 638643 : // A layer which is accessed must be visible.
545 638643 : mask |= 0x1 << Self::VISIBILITY_SHIFT;
546 638643 : value |= 0x1 << Self::VISIBILITY_SHIFT;
547 638643 :
548 638643 : let old_bits = self.write_bits(mask, value);
549 0 : !matches!(
550 638643 : self.decode_visibility(old_bits),
551 : LayerVisibilityHint::Visible
552 : )
553 638643 : }
554 :
555 : /// Returns true if we modified the layer's visibility to set it to Visible implicitly
556 : /// as a result of this access
557 639465 : pub(crate) fn record_access(&self, ctx: &RequestContext) -> bool {
558 639465 : if ctx.access_stats_behavior() == AccessStatsBehavior::Skip {
559 828 : return false;
560 638637 : }
561 638637 :
562 638637 : self.record_access_at(SystemTime::now())
563 639465 : }
564 :
565 0 : fn as_api_model(
566 0 : &self,
567 0 : reset: LayerAccessStatsReset,
568 0 : ) -> pageserver_api::models::LayerAccessStats {
569 0 : let ret = pageserver_api::models::LayerAccessStats {
570 0 : access_time: self
571 0 : .read_low_res_timestamp(Self::ATIME_SHIFT)
572 0 : .unwrap_or(UNIX_EPOCH),
573 0 : residence_time: self
574 0 : .read_low_res_timestamp(Self::RTIME_SHIFT)
575 0 : .unwrap_or(UNIX_EPOCH),
576 0 : visible: matches!(self.visibility(), LayerVisibilityHint::Visible),
577 : };
578 0 : match reset {
579 0 : LayerAccessStatsReset::NoReset => {}
580 0 : LayerAccessStatsReset::AllStats => {
581 0 : self.write_bits((Self::TS_MASK as u64) << Self::ATIME_SHIFT, 0x0);
582 0 : self.write_bits((Self::TS_MASK as u64) << Self::RTIME_SHIFT, 0x0);
583 0 : }
584 : }
585 0 : ret
586 0 : }
587 :
588 : /// Get the latest access timestamp, falling back to latest residence event. The latest residence event
589 : /// will be this Layer's construction time, if its residence hasn't changed since then.
590 48 : pub(crate) fn latest_activity(&self) -> SystemTime {
591 48 : if let Some(t) = self.read_low_res_timestamp(Self::ATIME_SHIFT) {
592 18 : t
593 : } else {
594 30 : self.read_low_res_timestamp(Self::RTIME_SHIFT)
595 30 : .expect("Residence time is set on construction")
596 : }
597 48 : }
598 :
599 : /// Whether this layer has been accessed (excluding in [`AccessStatsBehavior::Skip`]).
600 : ///
601 : /// This indicates whether the layer has been used for some purpose that would motivate
602 : /// us to keep it on disk, such as for serving a getpage request.
603 54 : fn accessed(&self) -> bool {
604 54 : // Consider it accessed if the most recent access is more recent than
605 54 : // the most recent change in residence status.
606 54 : match (
607 54 : self.read_low_res_timestamp(Self::ATIME_SHIFT),
608 54 : self.read_low_res_timestamp(Self::RTIME_SHIFT),
609 : ) {
610 42 : (None, _) => false,
611 0 : (Some(_), None) => true,
612 12 : (Some(a), Some(r)) => a >= r,
613 : }
614 54 : }
615 :
616 : /// Helper for extracting the visibility hint from the literal value of our inner u64
617 648461 : fn decode_visibility(&self, bits: u64) -> LayerVisibilityHint {
618 648461 : match (bits >> Self::VISIBILITY_SHIFT) & 0x1 {
619 648359 : 1 => LayerVisibilityHint::Visible,
620 102 : 0 => LayerVisibilityHint::Covered,
621 0 : _ => unreachable!(),
622 : }
623 648461 : }
624 :
625 : /// Returns the old value which has been replaced
626 8094 : pub(crate) fn set_visibility(&self, visibility: LayerVisibilityHint) -> LayerVisibilityHint {
627 8094 : let value = match visibility {
628 7914 : LayerVisibilityHint::Visible => 0x1 << Self::VISIBILITY_SHIFT,
629 180 : LayerVisibilityHint::Covered => 0x0,
630 : };
631 :
632 8094 : let old_bits = self.write_bits(0x1 << Self::VISIBILITY_SHIFT, value);
633 8094 : self.decode_visibility(old_bits)
634 8094 : }
635 :
636 1724 : pub(crate) fn visibility(&self) -> LayerVisibilityHint {
637 1724 : let read = self.0.load(std::sync::atomic::Ordering::Relaxed);
638 1724 : self.decode_visibility(read)
639 1724 : }
640 : }
641 :
642 : /// Get a layer descriptor from a layer.
643 : pub(crate) trait AsLayerDesc {
644 : /// Get the layer descriptor.
645 : fn layer_desc(&self) -> &PersistentLayerDesc;
646 : }
647 :
648 : pub mod tests {
649 : use pageserver_api::shard::TenantShardId;
650 : use utils::id::TimelineId;
651 :
652 : use super::*;
653 :
654 : impl From<DeltaLayerName> for PersistentLayerDesc {
655 0 : fn from(value: DeltaLayerName) -> Self {
656 0 : PersistentLayerDesc::new_delta(
657 0 : TenantShardId::from([0; 18]),
658 0 : TimelineId::from_array([0; 16]),
659 0 : value.key_range,
660 0 : value.lsn_range,
661 0 : 233,
662 0 : )
663 0 : }
664 : }
665 :
666 : impl From<ImageLayerName> for PersistentLayerDesc {
667 0 : fn from(value: ImageLayerName) -> Self {
668 0 : PersistentLayerDesc::new_img(
669 0 : TenantShardId::from([0; 18]),
670 0 : TimelineId::from_array([0; 16]),
671 0 : value.key_range,
672 0 : value.lsn,
673 0 : 233,
674 0 : )
675 0 : }
676 : }
677 :
678 : impl From<LayerName> for PersistentLayerDesc {
679 0 : fn from(value: LayerName) -> Self {
680 0 : match value {
681 0 : LayerName::Delta(d) => Self::from(d),
682 0 : LayerName::Image(i) => Self::from(i),
683 : }
684 0 : }
685 : }
686 : }
687 :
688 : /// Range wrapping newtype, which uses display to render Debug.
689 : ///
690 : /// Useful with `Key`, which has too verbose `{:?}` for printing multiple layers.
691 : struct RangeDisplayDebug<'a, T: std::fmt::Display>(&'a Range<T>);
692 :
693 : impl<'a, T: std::fmt::Display> std::fmt::Debug for RangeDisplayDebug<'a, T> {
694 0 : fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
695 0 : write!(f, "{}..{}", self.0.start, self.0.end)
696 0 : }
697 : }
|