Line data Source code
1 : use core::fmt::Display;
2 : use pageserver_api::shard::TenantShardId;
3 : use std::ops::Range;
4 : use utils::{id::TimelineId, lsn::Lsn};
5 :
6 : use crate::repository::Key;
7 :
8 : use super::{DeltaLayerName, ImageLayerName, LayerName};
9 :
10 : use serde::{Deserialize, Serialize};
11 :
12 : #[cfg(test)]
13 : use utils::id::TenantId;
14 :
15 : /// A unique identifier of a persistent layer.
16 : ///
17 : /// This is different from `LayerDescriptor`, which is only used in the benchmarks.
18 : /// This struct contains all necessary information to find the image / delta layer. It also provides
19 : /// a unified way to generate layer information like file name.
20 0 : #[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize, Hash)]
21 : pub struct PersistentLayerDesc {
22 : pub tenant_shard_id: TenantShardId,
23 : pub timeline_id: TimelineId,
24 : /// Range of keys that this layer covers
25 : pub key_range: Range<Key>,
26 : /// Inclusive start, exclusive end of the LSN range that this layer holds.
27 : ///
28 : /// - For an open in-memory layer, the end bound is MAX_LSN
29 : /// - For a frozen in-memory layer or a delta layer, the end bound is a valid lsn after the
30 : /// range start
31 : /// - An image layer represents snapshot at one LSN, so end_lsn is always the snapshot LSN + 1
32 : pub lsn_range: Range<Lsn>,
33 : /// Whether this is a delta layer, and also, is this incremental.
34 : pub is_delta: bool,
35 : pub file_size: u64,
36 : }
37 :
38 : /// A unique identifier of a persistent layer within the context of one timeline.
39 : #[derive(Debug, PartialEq, Eq, Clone, Hash)]
40 : pub struct PersistentLayerKey {
41 : pub key_range: Range<Key>,
42 : pub lsn_range: Range<Lsn>,
43 : pub is_delta: bool,
44 : }
45 :
46 : impl std::fmt::Display for PersistentLayerKey {
47 48 : fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
48 48 : write!(
49 48 : f,
50 48 : "{}..{} {}..{} is_delta={}",
51 48 : self.key_range.start,
52 48 : self.key_range.end,
53 48 : self.lsn_range.start,
54 48 : self.lsn_range.end,
55 48 : self.is_delta
56 48 : )
57 48 : }
58 : }
59 :
60 : impl PersistentLayerDesc {
61 1683496 : pub fn key(&self) -> PersistentLayerKey {
62 1683496 : PersistentLayerKey {
63 1683496 : key_range: self.key_range.clone(),
64 1683496 : lsn_range: self.lsn_range.clone(),
65 1683496 : is_delta: self.is_delta,
66 1683496 : }
67 1683496 : }
68 :
69 5856 : pub fn short_id(&self) -> impl Display {
70 5856 : self.layer_name()
71 5856 : }
72 :
73 : #[cfg(test)]
74 30 : pub fn new_test(key_range: Range<Key>, lsn_range: Range<Lsn>, is_delta: bool) -> Self {
75 30 : Self {
76 30 : tenant_shard_id: TenantShardId::unsharded(TenantId::generate()),
77 30 : timeline_id: TimelineId::generate(),
78 30 : key_range,
79 30 : lsn_range,
80 30 : is_delta,
81 30 : file_size: 0,
82 30 : }
83 30 : }
84 :
85 972 : pub fn new_img(
86 972 : tenant_shard_id: TenantShardId,
87 972 : timeline_id: TimelineId,
88 972 : key_range: Range<Key>,
89 972 : lsn: Lsn,
90 972 : file_size: u64,
91 972 : ) -> Self {
92 972 : Self {
93 972 : tenant_shard_id,
94 972 : timeline_id,
95 972 : key_range,
96 972 : lsn_range: Self::image_layer_lsn_range(lsn),
97 972 : is_delta: false,
98 972 : file_size,
99 972 : }
100 972 : }
101 :
102 4314 : pub fn new_delta(
103 4314 : tenant_shard_id: TenantShardId,
104 4314 : timeline_id: TimelineId,
105 4314 : key_range: Range<Key>,
106 4314 : lsn_range: Range<Lsn>,
107 4314 : file_size: u64,
108 4314 : ) -> Self {
109 4314 : Self {
110 4314 : tenant_shard_id,
111 4314 : timeline_id,
112 4314 : key_range,
113 4314 : lsn_range,
114 4314 : is_delta: true,
115 4314 : file_size,
116 4314 : }
117 4314 : }
118 :
119 72 : pub fn from_filename(
120 72 : tenant_shard_id: TenantShardId,
121 72 : timeline_id: TimelineId,
122 72 : filename: LayerName,
123 72 : file_size: u64,
124 72 : ) -> Self {
125 72 : match filename {
126 12 : LayerName::Image(i) => {
127 12 : Self::new_img(tenant_shard_id, timeline_id, i.key_range, i.lsn, file_size)
128 : }
129 60 : LayerName::Delta(d) => Self::new_delta(
130 60 : tenant_shard_id,
131 60 : timeline_id,
132 60 : d.key_range,
133 60 : d.lsn_range,
134 60 : file_size,
135 60 : ),
136 : }
137 72 : }
138 :
139 : /// Get the LSN that the image layer covers.
140 7621608 : pub fn image_layer_lsn(&self) -> Lsn {
141 7621608 : assert!(!self.is_delta);
142 7621608 : assert!(self.lsn_range.start + 1 == self.lsn_range.end);
143 7621608 : self.lsn_range.start
144 7621608 : }
145 :
146 : /// Get the LSN range corresponding to a single image layer LSN.
147 5994 : pub fn image_layer_lsn_range(lsn: Lsn) -> Range<Lsn> {
148 5994 : lsn..(lsn + 1)
149 5994 : }
150 :
151 : /// Get a delta layer name for this layer.
152 : ///
153 : /// Panic: if this is not a delta layer.
154 19591 : pub fn delta_layer_name(&self) -> DeltaLayerName {
155 19591 : assert!(self.is_delta);
156 19591 : DeltaLayerName {
157 19591 : key_range: self.key_range.clone(),
158 19591 : lsn_range: self.lsn_range.clone(),
159 19591 : }
160 19591 : }
161 :
162 : /// Get a image layer name for this layer.
163 : ///
164 : /// Panic: if this is not an image layer, or the lsn range is invalid
165 3580 : pub fn image_layer_name(&self) -> ImageLayerName {
166 3580 : assert!(!self.is_delta);
167 3580 : assert!(self.lsn_range.start + 1 == self.lsn_range.end);
168 3580 : ImageLayerName {
169 3580 : key_range: self.key_range.clone(),
170 3580 : lsn: self.lsn_range.start,
171 3580 : }
172 3580 : }
173 :
174 23171 : pub fn layer_name(&self) -> LayerName {
175 23171 : if self.is_delta {
176 19591 : self.delta_layer_name().into()
177 : } else {
178 3580 : self.image_layer_name().into()
179 : }
180 23171 : }
181 :
182 : // TODO: remove this in the future once we refactor timeline APIs.
183 :
184 11206215 : pub fn get_lsn_range(&self) -> Range<Lsn> {
185 11206215 : self.lsn_range.clone()
186 11206215 : }
187 :
188 318084 : pub fn get_key_range(&self) -> Range<Key> {
189 318084 : self.key_range.clone()
190 318084 : }
191 :
192 0 : pub fn get_timeline_id(&self) -> TimelineId {
193 0 : self.timeline_id
194 0 : }
195 :
196 : /// Does this layer only contain some data for the key-range (incremental),
197 : /// or does it contain a version of every page? This is important to know
198 : /// for garbage collecting old layers: an incremental layer depends on
199 : /// the previous non-incremental layer.
200 15852 : pub fn is_incremental(&self) -> bool {
201 15852 : self.is_delta
202 15852 : }
203 :
204 17207289 : pub fn is_delta(&self) -> bool {
205 17207289 : self.is_delta
206 17207289 : }
207 :
208 48 : pub fn dump(&self) {
209 48 : if self.is_delta {
210 42 : println!(
211 42 : "----- delta layer for ten {} tli {} keys {}-{} lsn {}-{} is_incremental {} size {} ----",
212 42 : self.tenant_shard_id,
213 42 : self.timeline_id,
214 42 : self.key_range.start,
215 42 : self.key_range.end,
216 42 : self.lsn_range.start,
217 42 : self.lsn_range.end,
218 42 : self.is_incremental(),
219 42 : self.file_size,
220 42 : );
221 42 : } else {
222 6 : println!(
223 6 : "----- image layer for ten {} tli {} key {}-{} at {} is_incremental {} size {} ----",
224 6 : self.tenant_shard_id,
225 6 : self.timeline_id,
226 6 : self.key_range.start,
227 6 : self.key_range.end,
228 6 : self.image_layer_lsn(),
229 6 : self.is_incremental(),
230 6 : self.file_size
231 6 : );
232 6 : }
233 48 : }
234 :
235 312 : pub fn file_size(&self) -> u64 {
236 312 : self.file_size
237 312 : }
238 : }
|