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 29 : fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
47 29 : write!(
48 29 : f,
49 29 : "{}..{} {}..{} is_delta={}",
50 : self.key_range.start,
51 : self.key_range.end,
52 : self.lsn_range.start,
53 : self.lsn_range.end,
54 : self.is_delta
55 : )
56 29 : }
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 443056 : pub fn key(&self) -> PersistentLayerKey {
89 443056 : PersistentLayerKey {
90 443056 : key_range: self.key_range.clone(),
91 443056 : lsn_range: self.lsn_range.clone(),
92 443056 : is_delta: self.is_delta,
93 443056 : }
94 443056 : }
95 :
96 1129 : pub fn short_id(&self) -> impl Display {
97 1129 : self.layer_name()
98 1129 : }
99 :
100 : #[cfg(test)]
101 34 : pub fn new_test(key_range: Range<Key>, lsn_range: Range<Lsn>, is_delta: bool) -> Self {
102 34 : Self {
103 34 : tenant_shard_id: TenantShardId::unsharded(TenantId::generate()),
104 34 : timeline_id: TimelineId::generate(),
105 34 : key_range,
106 34 : lsn_range,
107 34 : is_delta,
108 34 : file_size: 0,
109 34 : }
110 34 : }
111 :
112 213 : pub fn new_img(
113 213 : tenant_shard_id: TenantShardId,
114 213 : timeline_id: TimelineId,
115 213 : key_range: Range<Key>,
116 213 : lsn: Lsn,
117 213 : file_size: u64,
118 213 : ) -> Self {
119 213 : Self {
120 213 : tenant_shard_id,
121 213 : timeline_id,
122 213 : key_range,
123 213 : lsn_range: Self::image_layer_lsn_range(lsn),
124 213 : is_delta: false,
125 213 : file_size,
126 213 : }
127 213 : }
128 :
129 813 : pub fn new_delta(
130 813 : tenant_shard_id: TenantShardId,
131 813 : timeline_id: TimelineId,
132 813 : key_range: Range<Key>,
133 813 : lsn_range: Range<Lsn>,
134 813 : file_size: u64,
135 813 : ) -> Self {
136 813 : Self {
137 813 : tenant_shard_id,
138 813 : timeline_id,
139 813 : key_range,
140 813 : lsn_range,
141 813 : is_delta: true,
142 813 : file_size,
143 813 : }
144 813 : }
145 :
146 61 : pub fn from_filename(
147 61 : tenant_shard_id: TenantShardId,
148 61 : timeline_id: TimelineId,
149 61 : filename: LayerName,
150 61 : file_size: u64,
151 61 : ) -> Self {
152 61 : match filename {
153 2 : LayerName::Image(i) => {
154 2 : Self::new_img(tenant_shard_id, timeline_id, i.key_range, i.lsn, file_size)
155 : }
156 59 : LayerName::Delta(d) => Self::new_delta(
157 59 : tenant_shard_id,
158 59 : timeline_id,
159 59 : d.key_range,
160 59 : d.lsn_range,
161 59 : file_size,
162 : ),
163 : }
164 61 : }
165 :
166 : /// Get the LSN that the image layer covers.
167 1270361 : pub fn image_layer_lsn(&self) -> Lsn {
168 1270361 : assert!(!self.is_delta);
169 1270361 : assert!(self.lsn_range.start + 1 == self.lsn_range.end);
170 1270361 : self.lsn_range.start
171 1270361 : }
172 :
173 : /// Get the LSN range corresponding to a single image layer LSN.
174 1224 : pub fn image_layer_lsn_range(lsn: Lsn) -> Range<Lsn> {
175 1224 : lsn..(lsn + 1)
176 1224 : }
177 :
178 : /// Get a delta layer name for this layer.
179 : ///
180 : /// Panic: if this is not a delta layer.
181 895769 : pub fn delta_layer_name(&self) -> DeltaLayerName {
182 895769 : assert!(self.is_delta);
183 895769 : DeltaLayerName {
184 895769 : key_range: self.key_range.clone(),
185 895769 : lsn_range: self.lsn_range.clone(),
186 895769 : }
187 895769 : }
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 1808 : pub fn image_layer_name(&self) -> ImageLayerName {
193 1808 : assert!(!self.is_delta);
194 1808 : assert!(self.lsn_range.start + 1 == self.lsn_range.end);
195 1808 : ImageLayerName {
196 1808 : key_range: self.key_range.clone(),
197 1808 : lsn: self.lsn_range.start,
198 1808 : }
199 1808 : }
200 :
201 897577 : pub fn layer_name(&self) -> LayerName {
202 897577 : if self.is_delta {
203 895769 : self.delta_layer_name().into()
204 : } else {
205 1808 : self.image_layer_name().into()
206 : }
207 897577 : }
208 :
209 : // TODO: remove this in the future once we refactor timeline APIs.
210 :
211 3266816 : pub fn get_lsn_range(&self) -> Range<Lsn> {
212 3266816 : self.lsn_range.clone()
213 3266816 : }
214 :
215 53347 : pub fn get_key_range(&self) -> Range<Key> {
216 53347 : self.key_range.clone()
217 53347 : }
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 2766 : pub fn is_incremental(&self) -> bool {
228 2766 : self.is_delta
229 2766 : }
230 :
231 3825666 : pub fn is_delta(&self) -> bool {
232 3825666 : self.is_delta
233 3825666 : }
234 :
235 8 : pub fn dump(&self) {
236 8 : if self.is_delta {
237 7 : println!(
238 7 : "----- delta layer for ten {} tli {} keys {}-{} lsn {}-{} is_incremental {} size {} ----",
239 7 : self.tenant_shard_id,
240 7 : self.timeline_id,
241 7 : self.key_range.start,
242 7 : self.key_range.end,
243 7 : self.lsn_range.start,
244 7 : self.lsn_range.end,
245 7 : self.is_incremental(),
246 7 : self.file_size,
247 7 : );
248 7 : } else {
249 1 : println!(
250 1 : "----- image layer for ten {} tli {} key {}-{} at {} is_incremental {} size {} ----",
251 1 : self.tenant_shard_id,
252 1 : self.timeline_id,
253 1 : self.key_range.start,
254 1 : self.key_range.end,
255 1 : self.image_layer_lsn(),
256 1 : self.is_incremental(),
257 1 : self.file_size
258 1 : );
259 1 : }
260 8 : }
261 :
262 117 : pub fn file_size(&self) -> u64 {
263 117 : self.file_size
264 117 : }
265 : }
|