Line data Source code
1 : use std::collections::HashMap;
2 : use std::sync::Arc;
3 :
4 : use parking_lot::Mutex;
5 : use safekeeper::state::TimelinePersistentState;
6 : use utils::id::TenantTimelineId;
7 :
8 : use super::block_storage::BlockStorage;
9 :
10 : use std::{ops::Deref, time::Instant};
11 :
12 : use anyhow::Result;
13 : use bytes::{Buf, BytesMut};
14 : use futures::future::BoxFuture;
15 : use postgres_ffi::{waldecoder::WalStreamDecoder, XLogSegNo};
16 : use safekeeper::{control_file, metrics::WalStorageMetrics, wal_storage};
17 : use tracing::{debug, info};
18 : use utils::lsn::Lsn;
19 :
20 : /// All safekeeper state that is usually saved to disk.
21 : pub struct SafekeeperDisk {
22 : pub timelines: Mutex<HashMap<TenantTimelineId, Arc<TimelineDisk>>>,
23 : }
24 :
25 : impl Default for SafekeeperDisk {
26 0 : fn default() -> Self {
27 0 : Self::new()
28 0 : }
29 : }
30 :
31 : impl SafekeeperDisk {
32 12048 : pub fn new() -> Self {
33 12048 : SafekeeperDisk {
34 12048 : timelines: Mutex::new(HashMap::new()),
35 12048 : }
36 12048 : }
37 :
38 11396 : pub fn put_state(
39 11396 : &self,
40 11396 : ttid: &TenantTimelineId,
41 11396 : state: TimelinePersistentState,
42 11396 : ) -> Arc<TimelineDisk> {
43 11396 : self.timelines
44 11396 : .lock()
45 11396 : .entry(*ttid)
46 11396 : .and_modify(|e| {
47 0 : let mut mu = e.state.lock();
48 0 : *mu = state.clone();
49 11396 : })
50 11396 : .or_insert_with(|| {
51 11396 : Arc::new(TimelineDisk {
52 11396 : state: Mutex::new(state),
53 11396 : wal: Mutex::new(BlockStorage::new()),
54 11396 : })
55 11396 : })
56 11396 : .clone()
57 11396 : }
58 : }
59 :
60 : /// Control file state and WAL storage.
61 : pub struct TimelineDisk {
62 : pub state: Mutex<TimelinePersistentState>,
63 : pub wal: Mutex<BlockStorage>,
64 : }
65 :
66 : /// Implementation of `control_file::Storage` trait.
67 : pub struct DiskStateStorage {
68 : persisted_state: TimelinePersistentState,
69 : disk: Arc<TimelineDisk>,
70 : last_persist_at: Instant,
71 : }
72 :
73 : impl DiskStateStorage {
74 68984 : pub fn new(disk: Arc<TimelineDisk>) -> Self {
75 68984 : let guard = disk.state.lock();
76 68984 : let state = guard.clone();
77 68984 : drop(guard);
78 68984 : DiskStateStorage {
79 68984 : persisted_state: state,
80 68984 : disk,
81 68984 : last_persist_at: Instant::now(),
82 68984 : }
83 68984 : }
84 : }
85 :
86 : #[async_trait::async_trait]
87 : impl control_file::Storage for DiskStateStorage {
88 : /// Persist safekeeper state on disk and update internal state.
89 32042 : async fn persist(&mut self, s: &TimelinePersistentState) -> Result<()> {
90 32042 : self.persisted_state = s.clone();
91 32042 : *self.disk.state.lock() = s.clone();
92 32042 : Ok(())
93 64084 : }
94 :
95 : /// Timestamp of last persist.
96 0 : fn last_persist_at(&self) -> Instant {
97 0 : // TODO: don't rely on it in tests
98 0 : self.last_persist_at
99 0 : }
100 : }
101 :
102 : impl Deref for DiskStateStorage {
103 : type Target = TimelinePersistentState;
104 :
105 1961074 : fn deref(&self) -> &Self::Target {
106 1961074 : &self.persisted_state
107 1961074 : }
108 : }
109 :
110 : /// Implementation of `wal_storage::Storage` trait.
111 : pub struct DiskWALStorage {
112 : /// Written to disk, but possibly still in the cache and not fully persisted.
113 : /// Also can be ahead of record_lsn, if happen to be in the middle of a WAL record.
114 : write_lsn: Lsn,
115 :
116 : /// The LSN of the last WAL record written to disk. Still can be not fully flushed.
117 : write_record_lsn: Lsn,
118 :
119 : /// The LSN of the last WAL record flushed to disk.
120 : flush_record_lsn: Lsn,
121 :
122 : /// Decoder is required for detecting boundaries of WAL records.
123 : decoder: WalStreamDecoder,
124 :
125 : /// Bytes of WAL records that are not yet written to disk.
126 : unflushed_bytes: BytesMut,
127 :
128 : /// Contains BlockStorage for WAL.
129 : disk: Arc<TimelineDisk>,
130 : }
131 :
132 : impl DiskWALStorage {
133 68984 : pub fn new(disk: Arc<TimelineDisk>, state: &TimelinePersistentState) -> Result<Self> {
134 68984 : let write_lsn = if state.commit_lsn == Lsn(0) {
135 64124 : Lsn(0)
136 : } else {
137 4860 : Self::find_end_of_wal(disk.clone(), state.commit_lsn)?
138 : };
139 :
140 68984 : let flush_lsn = write_lsn;
141 68984 : Ok(DiskWALStorage {
142 68984 : write_lsn,
143 68984 : write_record_lsn: flush_lsn,
144 68984 : flush_record_lsn: flush_lsn,
145 68984 : decoder: WalStreamDecoder::new(flush_lsn, 16),
146 68984 : unflushed_bytes: BytesMut::new(),
147 68984 : disk,
148 68984 : })
149 68984 : }
150 :
151 4860 : fn find_end_of_wal(disk: Arc<TimelineDisk>, start_lsn: Lsn) -> Result<Lsn> {
152 4860 : let mut buf = [0; 8192];
153 4860 : let mut pos = start_lsn.0;
154 4860 : let mut decoder = WalStreamDecoder::new(start_lsn, 16);
155 4860 : let mut result = start_lsn;
156 4860 : loop {
157 4860 : disk.wal.lock().read(pos, &mut buf);
158 4860 : pos += buf.len() as u64;
159 4860 : decoder.feed_bytes(&buf);
160 :
161 : loop {
162 25430 : match decoder.poll_decode() {
163 20570 : Ok(Some(record)) => result = record.0,
164 4860 : Err(e) => {
165 4860 : debug!(
166 70 : "find_end_of_wal reached end at {:?}, decode error: {:?}",
167 70 : result, e
168 70 : );
169 4860 : return Ok(result);
170 : }
171 0 : Ok(None) => break, // need more data
172 : }
173 : }
174 : }
175 4860 : }
176 : }
177 :
178 : #[async_trait::async_trait]
179 : impl wal_storage::Storage for DiskWALStorage {
180 : /// LSN of last durably stored WAL record.
181 147533 : fn flush_lsn(&self) -> Lsn {
182 147533 : self.flush_record_lsn
183 147533 : }
184 :
185 : /// Write piece of WAL from buf to disk, but not necessarily sync it.
186 4384 : async fn write_wal(&mut self, startpos: Lsn, buf: &[u8]) -> Result<()> {
187 4384 : if self.write_lsn != startpos {
188 0 : panic!("write_wal called with wrong startpos");
189 4384 : }
190 4384 :
191 4384 : self.unflushed_bytes.extend_from_slice(buf);
192 4384 : self.write_lsn += buf.len() as u64;
193 4384 :
194 4384 : if self.decoder.available() != startpos {
195 0 : info!(
196 0 : "restart decoder from {} to {}",
197 0 : self.decoder.available(),
198 0 : startpos,
199 0 : );
200 0 : self.decoder = WalStreamDecoder::new(startpos, 16);
201 4384 : }
202 4384 : self.decoder.feed_bytes(buf);
203 : loop {
204 65726 : match self.decoder.poll_decode()? {
205 4384 : None => break, // no full record yet
206 61342 : Some((lsn, _rec)) => {
207 61342 : self.write_record_lsn = lsn;
208 61342 : }
209 : }
210 : }
211 :
212 4384 : Ok(())
213 13152 : }
214 :
215 : /// Truncate WAL at specified LSN, which must be the end of WAL record.
216 7192 : async fn truncate_wal(&mut self, end_pos: Lsn) -> Result<()> {
217 7192 : if self.write_lsn != Lsn(0) && end_pos > self.write_lsn {
218 0 : panic!(
219 0 : "truncate_wal called on non-written WAL, write_lsn={}, end_pos={}",
220 0 : self.write_lsn, end_pos
221 0 : );
222 7192 : }
223 7192 :
224 7192 : self.flush_wal().await?;
225 :
226 : // write zeroes to disk from end_pos until self.write_lsn
227 7192 : let buf = [0; 8192];
228 7192 : let mut pos = end_pos.0;
229 7214 : while pos < self.write_lsn.0 {
230 22 : self.disk.wal.lock().write(pos, &buf);
231 22 : pos += buf.len() as u64;
232 22 : }
233 :
234 7192 : self.write_lsn = end_pos;
235 7192 : self.write_record_lsn = end_pos;
236 7192 : self.flush_record_lsn = end_pos;
237 7192 : self.unflushed_bytes.clear();
238 7192 : self.decoder = WalStreamDecoder::new(end_pos, 16);
239 7192 :
240 7192 : Ok(())
241 21576 : }
242 :
243 : /// Durably store WAL on disk, up to the last written WAL record.
244 52222 : async fn flush_wal(&mut self) -> Result<()> {
245 52222 : if self.flush_record_lsn == self.write_record_lsn {
246 : // no need to do extra flush
247 47859 : return Ok(());
248 4363 : }
249 4363 :
250 4363 : let num_bytes = self.write_record_lsn.0 - self.flush_record_lsn.0;
251 4363 :
252 4363 : self.disk.wal.lock().write(
253 4363 : self.flush_record_lsn.0,
254 4363 : &self.unflushed_bytes[..num_bytes as usize],
255 4363 : );
256 4363 : self.unflushed_bytes.advance(num_bytes as usize);
257 4363 : self.flush_record_lsn = self.write_record_lsn;
258 4363 :
259 4363 : Ok(())
260 156666 : }
261 :
262 : /// Remove all segments <= given segno. Returns function doing that as we
263 : /// want to perform it without timeline lock.
264 0 : fn remove_up_to(&self, _segno_up_to: XLogSegNo) -> BoxFuture<'static, anyhow::Result<()>> {
265 0 : Box::pin(async move { Ok(()) })
266 0 : }
267 :
268 : /// Release resources associated with the storage -- technically, close FDs.
269 : /// Currently we don't remove timelines until restart (#3146), so need to
270 : /// spare descriptors. This would be useful for temporary tli detach as
271 : /// well.
272 0 : fn close(&mut self) {}
273 :
274 : /// Get metrics for this timeline.
275 0 : fn get_metrics(&self) -> WalStorageMetrics {
276 0 : WalStorageMetrics::default()
277 0 : }
278 : }
|