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