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