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 1459921 : pub fn key(&self) -> PersistentLayerKey {
89 1459921 : PersistentLayerKey {
90 1459921 : key_range: self.key_range.clone(),
91 1459921 : lsn_range: self.lsn_range.clone(),
92 1459921 : is_delta: self.is_delta,
93 1459921 : }
94 1459921 : }
95 :
96 4420 : pub fn short_id(&self) -> impl Display {
97 4420 : self.layer_name()
98 4420 : }
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 812 : pub fn new_img(
113 812 : tenant_shard_id: TenantShardId,
114 812 : timeline_id: TimelineId,
115 812 : key_range: Range<Key>,
116 812 : lsn: Lsn,
117 812 : file_size: u64,
118 812 : ) -> Self {
119 812 : Self {
120 812 : tenant_shard_id,
121 812 : timeline_id,
122 812 : key_range,
123 812 : lsn_range: Self::image_layer_lsn_range(lsn),
124 812 : is_delta: false,
125 812 : file_size,
126 812 : }
127 812 : }
128 :
129 3192 : pub fn new_delta(
130 3192 : tenant_shard_id: TenantShardId,
131 3192 : timeline_id: TimelineId,
132 3192 : key_range: Range<Key>,
133 3192 : lsn_range: Range<Lsn>,
134 3192 : file_size: u64,
135 3192 : ) -> Self {
136 3192 : Self {
137 3192 : tenant_shard_id,
138 3192 : timeline_id,
139 3192 : key_range,
140 3192 : lsn_range,
141 3192 : is_delta: true,
142 3192 : file_size,
143 3192 : }
144 3192 : }
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 5081440 : pub fn image_layer_lsn(&self) -> Lsn {
168 5081440 : assert!(!self.is_delta);
169 5081440 : assert!(self.lsn_range.start + 1 == self.lsn_range.end);
170 5081440 : self.lsn_range.start
171 5081440 : }
172 :
173 : /// Get the LSN range corresponding to a single image layer LSN.
174 4824 : pub fn image_layer_lsn_range(lsn: Lsn) -> Range<Lsn> {
175 4824 : lsn..(lsn + 1)
176 4824 : }
177 :
178 : /// Get a delta layer name for this layer.
179 : ///
180 : /// Panic: if this is not a delta layer.
181 2380776 : pub fn delta_layer_name(&self) -> DeltaLayerName {
182 2380776 : assert!(self.is_delta);
183 2380776 : DeltaLayerName {
184 2380776 : key_range: self.key_range.clone(),
185 2380776 : lsn_range: self.lsn_range.clone(),
186 2380776 : }
187 2380776 : }
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 8013 : pub fn image_layer_name(&self) -> ImageLayerName {
193 8013 : assert!(!self.is_delta);
194 8013 : assert!(self.lsn_range.start + 1 == self.lsn_range.end);
195 8013 : ImageLayerName {
196 8013 : key_range: self.key_range.clone(),
197 8013 : lsn: self.lsn_range.start,
198 8013 : }
199 8013 : }
200 :
201 2388789 : pub fn layer_name(&self) -> LayerName {
202 2388789 : if self.is_delta {
203 2380776 : self.delta_layer_name().into()
204 : } else {
205 8013 : self.image_layer_name().into()
206 : }
207 2388789 : }
208 :
209 : // TODO: remove this in the future once we refactor timeline APIs.
210 :
211 12314579 : pub fn get_lsn_range(&self) -> Range<Lsn> {
212 12314579 : self.lsn_range.clone()
213 12314579 : }
214 :
215 189752 : pub fn get_key_range(&self) -> Range<Key> {
216 189752 : self.key_range.clone()
217 189752 : }
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 10896 : pub fn is_incremental(&self) -> bool {
228 10896 : self.is_delta
229 10896 : }
230 :
231 14795094 : pub fn is_delta(&self) -> bool {
232 14795094 : self.is_delta
233 14795094 : }
234 :
235 32 : pub fn dump(&self) {
236 32 : if self.is_delta {
237 28 : println!(
238 28 : "----- delta layer for ten {} tli {} keys {}-{} lsn {}-{} is_incremental {} size {} ----",
239 28 : self.tenant_shard_id,
240 28 : self.timeline_id,
241 28 : self.key_range.start,
242 28 : self.key_range.end,
243 28 : self.lsn_range.start,
244 28 : self.lsn_range.end,
245 28 : self.is_incremental(),
246 28 : self.file_size,
247 28 : );
248 28 : } 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 32 : }
261 :
262 456 : pub fn file_size(&self) -> u64 {
263 456 : self.file_size
264 456 : }
265 : }
|