Line data Source code
1 : use anyhow::Result;
2 : use core::fmt::Display;
3 : use std::ops::Range;
4 : use utils::{
5 : id::{TenantId, TimelineId},
6 : lsn::Lsn,
7 : };
8 :
9 : use crate::{context::RequestContext, repository::Key};
10 :
11 : use super::{DeltaFileName, ImageFileName, LayerFileName};
12 :
13 : use serde::{Deserialize, Serialize};
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 37504 : #[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
19 : pub struct PersistentLayerDesc {
20 : pub tenant_id: TenantId,
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 46065740 : #[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 PersistentLayerDesc {
45 45837672 : pub fn key(&self) -> PersistentLayerKey {
46 45837672 : PersistentLayerKey {
47 45837672 : key_range: self.key_range.clone(),
48 45837672 : lsn_range: self.lsn_range.clone(),
49 45837672 : is_delta: self.is_delta,
50 45837672 : }
51 45837672 : }
52 :
53 8263 : pub fn short_id(&self) -> impl Display {
54 8263 : self.filename()
55 8263 : }
56 :
57 : #[cfg(test)]
58 0 : pub fn new_test(key_range: Range<Key>) -> Self {
59 0 : Self {
60 0 : tenant_id: TenantId::generate(),
61 0 : timeline_id: TimelineId::generate(),
62 0 : key_range,
63 0 : lsn_range: Lsn(0)..Lsn(1),
64 0 : is_delta: false,
65 0 : file_size: 0,
66 0 : }
67 0 : }
68 :
69 2810 : pub fn new_img(
70 2810 : tenant_id: TenantId,
71 2810 : timeline_id: TimelineId,
72 2810 : key_range: Range<Key>,
73 2810 : lsn: Lsn,
74 2810 : file_size: u64,
75 2810 : ) -> Self {
76 2810 : Self {
77 2810 : tenant_id,
78 2810 : timeline_id,
79 2810 : key_range,
80 2810 : lsn_range: Self::image_layer_lsn_range(lsn),
81 2810 : is_delta: false,
82 2810 : file_size,
83 2810 : }
84 2810 : }
85 :
86 21371 : pub fn new_delta(
87 21371 : tenant_id: TenantId,
88 21371 : timeline_id: TimelineId,
89 21371 : key_range: Range<Key>,
90 21371 : lsn_range: Range<Lsn>,
91 21371 : file_size: u64,
92 21371 : ) -> Self {
93 21371 : Self {
94 21371 : tenant_id,
95 21371 : timeline_id,
96 21371 : key_range,
97 21371 : lsn_range,
98 21371 : is_delta: true,
99 21371 : file_size,
100 21371 : }
101 21371 : }
102 :
103 : /// Get the LSN that the image layer covers.
104 1570 : pub fn image_layer_lsn(&self) -> Lsn {
105 1570 : assert!(!self.is_delta);
106 1570 : assert!(self.lsn_range.start + 1 == self.lsn_range.end);
107 1570 : self.lsn_range.start
108 1570 : }
109 :
110 : /// Get the LSN range corresponding to a single image layer LSN.
111 2810 : pub fn image_layer_lsn_range(lsn: Lsn) -> Range<Lsn> {
112 2810 : lsn..(lsn + 1)
113 2810 : }
114 :
115 : /// Get a delta file name for this layer.
116 : ///
117 : /// Panic: if this is not a delta layer.
118 70323 : pub fn delta_file_name(&self) -> DeltaFileName {
119 70323 : assert!(self.is_delta);
120 70323 : DeltaFileName {
121 70323 : key_range: self.key_range.clone(),
122 70323 : lsn_range: self.lsn_range.clone(),
123 70323 : }
124 70323 : }
125 :
126 : /// Get a delta file name for this layer.
127 : ///
128 : /// Panic: if this is not an image layer, or the lsn range is invalid
129 7603 : pub fn image_file_name(&self) -> ImageFileName {
130 7603 : assert!(!self.is_delta);
131 7603 : assert!(self.lsn_range.start + 1 == self.lsn_range.end);
132 7603 : ImageFileName {
133 7603 : key_range: self.key_range.clone(),
134 7603 : lsn: self.lsn_range.start,
135 7603 : }
136 7603 : }
137 :
138 31853 : pub fn filename(&self) -> LayerFileName {
139 31853 : if self.is_delta {
140 27736 : self.delta_file_name().into()
141 : } else {
142 4117 : self.image_file_name().into()
143 : }
144 31853 : }
145 :
146 : // TODO: remove this in the future once we refactor timeline APIs.
147 :
148 84594080 : pub fn get_lsn_range(&self) -> Range<Lsn> {
149 84594080 : self.lsn_range.clone()
150 84594080 : }
151 :
152 11769714 : pub fn get_key_range(&self) -> Range<Key> {
153 11769714 : self.key_range.clone()
154 11769714 : }
155 :
156 0 : pub fn get_timeline_id(&self) -> TimelineId {
157 0 : self.timeline_id
158 0 : }
159 :
160 0 : pub fn get_tenant_id(&self) -> TenantId {
161 0 : self.tenant_id
162 0 : }
163 :
164 : /// Does this layer only contain some data for the key-range (incremental),
165 : /// or does it contain a version of every page? This is important to know
166 : /// for garbage collecting old layers: an incremental layer depends on
167 : /// the previous non-incremental layer.
168 27265 : pub fn is_incremental(&self) -> bool {
169 27265 : self.is_delta
170 27265 : }
171 :
172 0 : pub fn is_delta(&self) -> bool {
173 0 : self.is_delta
174 0 : }
175 :
176 0 : pub fn dump(&self, _verbose: bool, _ctx: &RequestContext) -> Result<()> {
177 0 : println!(
178 0 : "----- layer for ten {} tli {} keys {}-{} lsn {}-{} is_delta {} is_incremental {} size {} ----",
179 0 : self.tenant_id,
180 0 : self.timeline_id,
181 0 : self.key_range.start,
182 0 : self.key_range.end,
183 0 : self.lsn_range.start,
184 0 : self.lsn_range.end,
185 0 : self.is_delta,
186 0 : self.is_incremental(),
187 0 : self.file_size,
188 0 : );
189 0 :
190 0 : Ok(())
191 0 : }
192 :
193 64825 : pub fn file_size(&self) -> u64 {
194 64825 : self.file_size
195 64825 : }
196 : }
|