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