Line data Source code
1 : use std::{
2 : cell::{RefCell, RefMut, UnsafeCell},
3 : ffi::CStr,
4 : sync::Arc,
5 : };
6 :
7 : use bytes::Bytes;
8 : use desim::{
9 : executor::{self, PollSome},
10 : network::TCP,
11 : node_os::NodeOs,
12 : proto::{AnyMessage, NetEvent, NodeEvent},
13 : world::NodeId,
14 : };
15 : use tracing::debug;
16 : use utils::lsn::Lsn;
17 : use walproposer::{
18 : api_bindings::Level,
19 : bindings::{
20 : pg_atomic_uint64, NeonWALReadResult, PageserverFeedback, SafekeeperStateDesiredEvents,
21 : WL_SOCKET_READABLE, WL_SOCKET_WRITEABLE,
22 : },
23 : walproposer::{ApiImpl, Config},
24 : };
25 :
26 : use super::walproposer_disk::DiskWalProposer;
27 :
28 : /// Special state for each wp->sk connection.
29 : struct SafekeeperConn {
30 : host: String,
31 : port: String,
32 : node_id: NodeId,
33 : // socket is Some(..) equals to connection is established
34 : socket: Option<TCP>,
35 : // connection is in progress
36 : is_connecting: bool,
37 : // START_WAL_PUSH is in progress
38 : is_start_wal_push: bool,
39 : // pointer to Safekeeper in walproposer for callbacks
40 : raw_ptr: *mut walproposer::bindings::Safekeeper,
41 : }
42 :
43 : impl SafekeeperConn {
44 217620 : pub fn new(host: String, port: String) -> Self {
45 217620 : // port number is the same as NodeId
46 217620 : let port_num = port.parse::<u32>().unwrap();
47 217620 : Self {
48 217620 : host,
49 217620 : port,
50 217620 : node_id: port_num,
51 217620 : socket: None,
52 217620 : is_connecting: false,
53 217620 : is_start_wal_push: false,
54 217620 : raw_ptr: std::ptr::null_mut(),
55 217620 : }
56 217620 : }
57 : }
58 :
59 : /// Simulation version of a postgres WaitEventSet. At pos 0 there is always
60 : /// a special NodeEvents channel, which is used as a latch.
61 : struct EventSet {
62 : os: NodeOs,
63 : // all pollable channels, 0 is always NodeEvent channel
64 : chans: Vec<Box<dyn PollSome>>,
65 : // 0 is always nullptr
66 : sk_ptrs: Vec<*mut walproposer::bindings::Safekeeper>,
67 : // event mask for each channel
68 : masks: Vec<u32>,
69 : }
70 :
71 : impl EventSet {
72 72540 : pub fn new(os: NodeOs) -> Self {
73 72540 : let node_events = os.node_events();
74 72540 : Self {
75 72540 : os,
76 72540 : chans: vec![Box::new(node_events)],
77 72540 : sk_ptrs: vec![std::ptr::null_mut()],
78 72540 : masks: vec![WL_SOCKET_READABLE],
79 72540 : }
80 72540 : }
81 :
82 : /// Leaves all readable channels at the beginning of the array.
83 223063 : fn sort_readable(&mut self) -> usize {
84 223063 : let mut cnt = 1;
85 530931 : for i in 1..self.chans.len() {
86 530931 : if self.masks[i] & WL_SOCKET_READABLE != 0 {
87 530931 : self.chans.swap(i, cnt);
88 530931 : self.sk_ptrs.swap(i, cnt);
89 530931 : self.masks.swap(i, cnt);
90 530931 : cnt += 1;
91 530931 : }
92 : }
93 223063 : cnt
94 223063 : }
95 :
96 534289 : fn update_event_set(&mut self, conn: &SafekeeperConn, event_mask: u32) {
97 534289 : let index = self
98 534289 : .sk_ptrs
99 534289 : .iter()
100 2014945 : .position(|&ptr| ptr == conn.raw_ptr)
101 534289 : .expect("safekeeper should exist in event set");
102 534289 : self.masks[index] = event_mask;
103 534289 : }
104 :
105 481946 : fn add_safekeeper(&mut self, sk: &SafekeeperConn, event_mask: u32) {
106 1165718 : for ptr in self.sk_ptrs.iter() {
107 1165718 : assert!(*ptr != sk.raw_ptr);
108 : }
109 :
110 481946 : self.chans.push(Box::new(
111 481946 : sk.socket
112 481946 : .as_ref()
113 481946 : .expect("socket should not be closed")
114 481946 : .recv_chan(),
115 481946 : ));
116 481946 : self.sk_ptrs.push(sk.raw_ptr);
117 481946 : self.masks.push(event_mask);
118 481946 : }
119 :
120 303494 : fn remove_safekeeper(&mut self, sk: &SafekeeperConn) {
121 645964 : let index = self.sk_ptrs.iter().position(|&ptr| ptr == sk.raw_ptr);
122 303494 : if index.is_none() {
123 42 : debug!("remove_safekeeper: sk={:?} not found", sk.raw_ptr);
124 42 : return;
125 303452 : }
126 303452 : let index = index.unwrap();
127 303452 :
128 303452 : self.chans.remove(index);
129 303452 : self.sk_ptrs.remove(index);
130 303452 : self.masks.remove(index);
131 303452 :
132 303452 : // to simulate the actual behaviour
133 303452 : self.refresh_event_set();
134 303494 : }
135 :
136 : /// Updates all masks to match the result of a SafekeeperStateDesiredEvents.
137 347038 : fn refresh_event_set(&mut self) {
138 983428 : for (i, mask) in self.masks.iter_mut().enumerate() {
139 983428 : if i == 0 {
140 347038 : continue;
141 636390 : }
142 636390 :
143 636390 : let mut mask_sk: u32 = 0;
144 636390 : let mut mask_nwr: u32 = 0;
145 636390 : unsafe { SafekeeperStateDesiredEvents(self.sk_ptrs[i], &mut mask_sk, &mut mask_nwr) };
146 636390 :
147 636390 : if mask_sk != *mask {
148 0 : debug!(
149 0 : "refresh_event_set: sk={:?}, old_mask={:#b}, new_mask={:#b}",
150 0 : self.sk_ptrs[i], *mask, mask_sk
151 0 : );
152 0 : *mask = mask_sk;
153 636390 : }
154 : }
155 347038 : }
156 :
157 : /// Wait for events on all channels.
158 223063 : fn wait(&mut self, timeout_millis: i64) -> walproposer::walproposer::WaitResult {
159 : // all channels are always writeable
160 753994 : for (i, mask) in self.masks.iter().enumerate() {
161 753994 : if *mask & WL_SOCKET_WRITEABLE != 0 {
162 0 : return walproposer::walproposer::WaitResult::Network(
163 0 : self.sk_ptrs[i],
164 0 : WL_SOCKET_WRITEABLE,
165 0 : );
166 753994 : }
167 : }
168 :
169 223063 : let cnt = self.sort_readable();
170 223063 :
171 223063 : let slice = &self.chans[0..cnt];
172 223063 : match executor::epoll_chans(slice, timeout_millis) {
173 90100 : None => walproposer::walproposer::WaitResult::Timeout,
174 : Some(0) => {
175 3187 : let msg = self.os.node_events().must_recv();
176 3187 : match msg {
177 3187 : NodeEvent::Internal(AnyMessage::Just32(0)) => {
178 3187 : // got a notification about new WAL available
179 3187 : }
180 0 : NodeEvent::Internal(_) => unreachable!(),
181 0 : NodeEvent::Accept(_) => unreachable!(),
182 : }
183 3187 : walproposer::walproposer::WaitResult::Latch
184 : }
185 129776 : Some(index) => walproposer::walproposer::WaitResult::Network(
186 129776 : self.sk_ptrs[index],
187 129776 : WL_SOCKET_READABLE,
188 129776 : ),
189 : }
190 223063 : }
191 : }
192 :
193 : /// This struct handles all calls from walproposer into walproposer_api.
194 : pub struct SimulationApi {
195 : os: NodeOs,
196 : safekeepers: RefCell<Vec<SafekeeperConn>>,
197 : disk: Arc<DiskWalProposer>,
198 : redo_start_lsn: Option<Lsn>,
199 : last_logged_commit_lsn: u64,
200 : shmem: UnsafeCell<walproposer::bindings::WalproposerShmemState>,
201 : config: Config,
202 : event_set: RefCell<Option<EventSet>>,
203 : }
204 :
205 : pub struct Args {
206 : pub os: NodeOs,
207 : pub config: Config,
208 : pub disk: Arc<DiskWalProposer>,
209 : pub redo_start_lsn: Option<Lsn>,
210 : }
211 :
212 : impl SimulationApi {
213 72540 : pub fn new(args: Args) -> Self {
214 72540 : // initialize connection state for each safekeeper
215 72540 : let sk_conns = args
216 72540 : .config
217 72540 : .safekeepers_list
218 72540 : .iter()
219 217620 : .map(|s| {
220 217620 : SafekeeperConn::new(
221 217620 : s.split(':').next().unwrap().to_string(),
222 217620 : s.split(':').nth(1).unwrap().to_string(),
223 217620 : )
224 217620 : })
225 72540 : .collect::<Vec<_>>();
226 72540 :
227 72540 : let empty_feedback = PageserverFeedback {
228 72540 : present: false,
229 72540 : currentClusterSize: 0,
230 72540 : last_received_lsn: 0,
231 72540 : disk_consistent_lsn: 0,
232 72540 : remote_consistent_lsn: 0,
233 72540 : replytime: 0,
234 72540 : shard_number: 0,
235 72540 : };
236 72540 :
237 72540 : Self {
238 72540 : os: args.os,
239 72540 : safekeepers: RefCell::new(sk_conns),
240 72540 : disk: args.disk,
241 72540 : redo_start_lsn: args.redo_start_lsn,
242 72540 : last_logged_commit_lsn: 0,
243 72540 : shmem: UnsafeCell::new(walproposer::bindings::WalproposerShmemState {
244 72540 : mutex: 0,
245 72540 : mineLastElectedTerm: 0,
246 72540 : backpressureThrottlingTime: pg_atomic_uint64 { value: 0 },
247 72540 : currentClusterSize: pg_atomic_uint64 { value: 0 },
248 72540 : shard_ps_feedback: [empty_feedback; 128],
249 72540 : num_shards: 0,
250 72540 : min_ps_feedback: empty_feedback,
251 72540 : }),
252 72540 : config: args.config,
253 72540 : event_set: RefCell::new(None),
254 72540 : }
255 72540 : }
256 :
257 : /// Get SafekeeperConn for the given Safekeeper.
258 2372566 : fn get_conn(&self, sk: &mut walproposer::bindings::Safekeeper) -> RefMut<'_, SafekeeperConn> {
259 2372566 : let sk_port = unsafe { CStr::from_ptr(sk.port).to_str().unwrap() };
260 2372566 : let state = self.safekeepers.borrow_mut();
261 2372566 : RefMut::map(state, |v| {
262 2372566 : v.iter_mut()
263 4742584 : .find(|conn| conn.port == sk_port)
264 2372566 : .expect("safekeeper conn not found by port")
265 2372566 : })
266 2372566 : }
267 : }
268 :
269 : impl ApiImpl for SimulationApi {
270 2531619 : fn get_current_timestamp(&self) -> i64 {
271 2531619 : debug!("get_current_timestamp");
272 : // PG TimestampTZ is microseconds, but simulation unit is assumed to be
273 : // milliseconds, so add 10^3
274 2531619 : self.os.now() as i64 * 1000
275 2531619 : }
276 :
277 268147 : fn conn_status(
278 268147 : &self,
279 268147 : _: &mut walproposer::bindings::Safekeeper,
280 268147 : ) -> walproposer::bindings::WalProposerConnStatusType {
281 268147 : debug!("conn_status");
282 : // break the connection with a 10% chance
283 268147 : if self.os.random(100) < 10 {
284 27174 : walproposer::bindings::WalProposerConnStatusType_WP_CONNECTION_BAD
285 : } else {
286 240973 : walproposer::bindings::WalProposerConnStatusType_WP_CONNECTION_OK
287 : }
288 268147 : }
289 :
290 268147 : fn conn_connect_start(&self, sk: &mut walproposer::bindings::Safekeeper) {
291 268147 : debug!("conn_connect_start");
292 268147 : let mut conn = self.get_conn(sk);
293 268147 :
294 268147 : assert!(conn.socket.is_none());
295 268147 : let socket = self.os.open_tcp(conn.node_id);
296 268147 : conn.socket = Some(socket);
297 268147 : conn.raw_ptr = sk;
298 268147 : conn.is_connecting = true;
299 268147 : }
300 :
301 240973 : fn conn_connect_poll(
302 240973 : &self,
303 240973 : _: &mut walproposer::bindings::Safekeeper,
304 240973 : ) -> walproposer::bindings::WalProposerConnectPollStatusType {
305 240973 : debug!("conn_connect_poll");
306 : // TODO: break the connection here
307 240973 : walproposer::bindings::WalProposerConnectPollStatusType_WP_CONN_POLLING_OK
308 240973 : }
309 :
310 240973 : fn conn_send_query(&self, sk: &mut walproposer::bindings::Safekeeper, query: &str) -> bool {
311 240973 : debug!("conn_send_query: {}", query);
312 240973 : self.get_conn(sk).is_start_wal_push = true;
313 240973 : true
314 240973 : }
315 :
316 240973 : fn conn_get_query_result(
317 240973 : &self,
318 240973 : _: &mut walproposer::bindings::Safekeeper,
319 240973 : ) -> walproposer::bindings::WalProposerExecStatusType {
320 240973 : debug!("conn_get_query_result");
321 : // TODO: break the connection here
322 240973 : walproposer::bindings::WalProposerExecStatusType_WP_EXEC_SUCCESS_COPYBOTH
323 240973 : }
324 :
325 142592 : fn conn_async_read(
326 142592 : &self,
327 142592 : sk: &mut walproposer::bindings::Safekeeper,
328 142592 : vec: &mut Vec<u8>,
329 142592 : ) -> walproposer::bindings::PGAsyncReadResult {
330 142592 : debug!("conn_async_read");
331 142592 : let mut conn = self.get_conn(sk);
332 :
333 142592 : let socket = if let Some(socket) = conn.socket.as_mut() {
334 142592 : socket
335 : } else {
336 : // socket is already closed
337 0 : return walproposer::bindings::PGAsyncReadResult_PG_ASYNC_READ_FAIL;
338 : };
339 :
340 142592 : let msg = socket.recv_chan().try_recv();
341 :
342 128189 : match msg {
343 : None => {
344 : // no message is ready
345 14403 : walproposer::bindings::PGAsyncReadResult_PG_ASYNC_READ_TRY_AGAIN
346 : }
347 : Some(NetEvent::Closed) => {
348 : // connection is closed
349 60389 : debug!("conn_async_read: connection is closed");
350 60389 : conn.socket = None;
351 60389 : walproposer::bindings::PGAsyncReadResult_PG_ASYNC_READ_FAIL
352 : }
353 67800 : Some(NetEvent::Message(msg)) => {
354 : // got a message
355 67800 : let b = match msg {
356 67800 : desim::proto::AnyMessage::Bytes(b) => b,
357 0 : _ => unreachable!(),
358 : };
359 67800 : vec.extend_from_slice(&b);
360 67800 : walproposer::bindings::PGAsyncReadResult_PG_ASYNC_READ_SUCCESS
361 : }
362 : }
363 142592 : }
364 :
365 271356 : fn conn_blocking_write(&self, sk: &mut walproposer::bindings::Safekeeper, buf: &[u8]) -> bool {
366 271356 : let mut conn = self.get_conn(sk);
367 271356 : debug!("conn_blocking_write to {}: {:?}", conn.node_id, buf);
368 271356 : let socket = conn.socket.as_mut().unwrap();
369 271356 : socket.send(desim::proto::AnyMessage::Bytes(Bytes::copy_from_slice(buf)));
370 271356 : true
371 271356 : }
372 :
373 37645 : fn conn_async_write(
374 37645 : &self,
375 37645 : sk: &mut walproposer::bindings::Safekeeper,
376 37645 : buf: &[u8],
377 37645 : ) -> walproposer::bindings::PGAsyncWriteResult {
378 37645 : let mut conn = self.get_conn(sk);
379 37645 : debug!("conn_async_write to {}: {:?}", conn.node_id, buf);
380 37645 : if let Some(socket) = conn.socket.as_mut() {
381 37645 : socket.send(desim::proto::AnyMessage::Bytes(Bytes::copy_from_slice(buf)));
382 37645 : } else {
383 : // connection is already closed
384 0 : debug!("conn_async_write: writing to a closed socket!");
385 : // TODO: maybe we should return error here?
386 : }
387 37645 : walproposer::bindings::PGAsyncWriteResult_PG_ASYNC_WRITE_SUCCESS
388 37645 : }
389 :
390 8462 : fn wal_reader_allocate(&self, _: &mut walproposer::bindings::Safekeeper) -> NeonWALReadResult {
391 8462 : debug!("wal_reader_allocate");
392 8462 : walproposer::bindings::NeonWALReadResult_NEON_WALREAD_SUCCESS
393 8462 : }
394 :
395 29183 : fn wal_read(
396 29183 : &self,
397 29183 : _sk: &mut walproposer::bindings::Safekeeper,
398 29183 : buf: &mut [u8],
399 29183 : startpos: u64,
400 29183 : ) -> NeonWALReadResult {
401 29183 : self.disk.lock().read(startpos, buf);
402 29183 : walproposer::bindings::NeonWALReadResult_NEON_WALREAD_SUCCESS
403 29183 : }
404 :
405 72540 : fn init_event_set(&self, _: &mut walproposer::bindings::WalProposer) {
406 72540 : debug!("init_event_set");
407 72540 : let new_event_set = EventSet::new(self.os.clone());
408 72540 : let old_event_set = self.event_set.replace(Some(new_event_set));
409 72540 : assert!(old_event_set.is_none());
410 72540 : }
411 :
412 534289 : fn update_event_set(&self, sk: &mut walproposer::bindings::Safekeeper, event_mask: u32) {
413 534289 : debug!(
414 1166 : "update_event_set, sk={:?}, events_mask={:#b}",
415 1166 : sk as *mut walproposer::bindings::Safekeeper, event_mask
416 1166 : );
417 534289 : let conn = self.get_conn(sk);
418 534289 :
419 534289 : self.event_set
420 534289 : .borrow_mut()
421 534289 : .as_mut()
422 534289 : .unwrap()
423 534289 : .update_event_set(&conn, event_mask);
424 534289 : }
425 :
426 481946 : fn add_safekeeper_event_set(
427 481946 : &self,
428 481946 : sk: &mut walproposer::bindings::Safekeeper,
429 481946 : event_mask: u32,
430 481946 : ) {
431 481946 : debug!(
432 728 : "add_safekeeper_event_set, sk={:?}, events_mask={:#b}",
433 728 : sk as *mut walproposer::bindings::Safekeeper, event_mask
434 728 : );
435 :
436 481946 : self.event_set
437 481946 : .borrow_mut()
438 481946 : .as_mut()
439 481946 : .unwrap()
440 481946 : .add_safekeeper(&self.get_conn(sk), event_mask);
441 481946 : }
442 :
443 303494 : fn rm_safekeeper_event_set(&self, sk: &mut walproposer::bindings::Safekeeper) {
444 303494 : debug!(
445 400 : "rm_safekeeper_event_set, sk={:?}",
446 400 : sk as *mut walproposer::bindings::Safekeeper,
447 400 : );
448 :
449 303494 : self.event_set
450 303494 : .borrow_mut()
451 303494 : .as_mut()
452 303494 : .unwrap()
453 303494 : .remove_safekeeper(&self.get_conn(sk));
454 303494 : }
455 :
456 43586 : fn active_state_update_event_set(&self, sk: &mut walproposer::bindings::Safekeeper) {
457 43586 : debug!("active_state_update_event_set");
458 :
459 43586 : assert!(sk.state == walproposer::bindings::SafekeeperState_SS_ACTIVE);
460 43586 : self.event_set
461 43586 : .borrow_mut()
462 43586 : .as_mut()
463 43586 : .unwrap()
464 43586 : .refresh_event_set();
465 43586 : }
466 :
467 125011 : fn wal_reader_events(&self, _sk: &mut walproposer::bindings::Safekeeper) -> u32 {
468 125011 : 0
469 125011 : }
470 :
471 705009 : fn wait_event_set(
472 705009 : &self,
473 705009 : _: &mut walproposer::bindings::WalProposer,
474 705009 : timeout_millis: i64,
475 705009 : ) -> walproposer::walproposer::WaitResult {
476 705009 : // TODO: handle multiple stages as part of the simulation (e.g. connect, start_wal_push, etc)
477 705009 : let mut conns = self.safekeepers.borrow_mut();
478 1633105 : for conn in conns.iter_mut() {
479 1633105 : if conn.socket.is_some() && conn.is_connecting {
480 240973 : conn.is_connecting = false;
481 240973 : debug!("wait_event_set, connecting to {}:{}", conn.host, conn.port);
482 240973 : return walproposer::walproposer::WaitResult::Network(
483 240973 : conn.raw_ptr,
484 240973 : WL_SOCKET_READABLE | WL_SOCKET_WRITEABLE,
485 240973 : );
486 1392132 : }
487 1392132 : if conn.socket.is_some() && conn.is_start_wal_push {
488 240973 : conn.is_start_wal_push = false;
489 240973 : debug!(
490 364 : "wait_event_set, start wal push to {}:{}",
491 364 : conn.host, conn.port
492 364 : );
493 240973 : return walproposer::walproposer::WaitResult::Network(
494 240973 : conn.raw_ptr,
495 240973 : WL_SOCKET_READABLE,
496 240973 : );
497 1151159 : }
498 : }
499 223063 : drop(conns);
500 223063 :
501 223063 : let res = self
502 223063 : .event_set
503 223063 : .borrow_mut()
504 223063 : .as_mut()
505 223063 : .unwrap()
506 223063 : .wait(timeout_millis);
507 223063 :
508 223063 : debug!(
509 690 : "wait_event_set, timeout_millis={}, res={:?}",
510 690 : timeout_millis, res,
511 690 : );
512 154657 : res
513 636603 : }
514 :
515 72540 : fn strong_random(&self, buf: &mut [u8]) -> bool {
516 72540 : debug!("strong_random");
517 72540 : buf.fill(0);
518 72540 : true
519 72540 : }
520 :
521 2907 : fn finish_sync_safekeepers(&self, lsn: u64) {
522 2907 : debug!("finish_sync_safekeepers, lsn={}", lsn);
523 2907 : executor::exit(0, Lsn(lsn).to_string());
524 2907 : }
525 :
526 727613 : fn log_internal(&self, _wp: &mut walproposer::bindings::WalProposer, level: Level, msg: &str) {
527 727613 : debug!("wp_log[{}] {}", level, msg);
528 727613 : if level == Level::Fatal || level == Level::Panic {
529 652 : if msg.contains("rejects our connection request with term") {
530 345 : // collected quorum with lower term, then got rejected by next connected safekeeper
531 345 : executor::exit(1, msg.to_owned());
532 345 : }
533 652 : if msg.contains("collected propEpochStartLsn") && msg.contains(", but basebackup LSN ")
534 30 : {
535 30 : // sync-safekeepers collected wrong quorum, walproposer collected another quorum
536 30 : executor::exit(1, msg.to_owned());
537 622 : }
538 652 : if msg.contains("failed to download WAL for logical replicaiton") {
539 185 : // Recovery connection broken and recovery was failed
540 185 : executor::exit(1, msg.to_owned());
541 467 : }
542 652 : if msg.contains("missing majority of votes, collected") {
543 92 : // Voting bug when safekeeper disconnects after voting
544 92 : executor::exit(1, msg.to_owned());
545 560 : }
546 652 : panic!("unknown FATAL error from walproposer: {}", msg);
547 726961 : }
548 726961 : }
549 :
550 6113 : fn after_election(&self, wp: &mut walproposer::bindings::WalProposer) {
551 6113 : let prop_lsn = wp.propEpochStartLsn;
552 6113 : let prop_term = wp.propTerm;
553 6113 :
554 6113 : let mut prev_lsn: u64 = 0;
555 6113 : let mut prev_term: u64 = 0;
556 6113 :
557 6113 : unsafe {
558 6113 : let history = wp.propTermHistory.entries;
559 6113 : let len = wp.propTermHistory.n_entries as usize;
560 6113 : if len > 1 {
561 4194 : let entry = *history.wrapping_add(len - 2);
562 4194 : prev_lsn = entry.lsn;
563 4194 : prev_term = entry.term;
564 4194 : }
565 : }
566 :
567 6113 : let msg = format!(
568 6113 : "prop_elected;{};{};{};{}",
569 6113 : prop_lsn, prop_term, prev_lsn, prev_term
570 6113 : );
571 6113 :
572 6113 : debug!(msg);
573 6113 : self.os.log_event(msg);
574 6113 : }
575 :
576 2401 : fn get_redo_start_lsn(&self) -> u64 {
577 2401 : debug!("get_redo_start_lsn -> {:?}", self.redo_start_lsn);
578 2401 : self.redo_start_lsn.expect("redo_start_lsn is not set").0
579 2401 : }
580 :
581 1465 : fn get_shmem_state(&self) -> *mut walproposer::bindings::WalproposerShmemState {
582 1465 : self.shmem.get()
583 1465 : }
584 :
585 1405 : fn start_streaming(
586 1405 : &self,
587 1405 : startpos: u64,
588 1405 : callback: &walproposer::walproposer::StreamingCallback,
589 1405 : ) {
590 1405 : let disk = &self.disk;
591 1405 : let disk_lsn = disk.lock().flush_rec_ptr().0;
592 1405 : debug!("start_streaming at {} (disk_lsn={})", startpos, disk_lsn);
593 1405 : if startpos < disk_lsn {
594 421 : debug!("startpos < disk_lsn, it means we wrote some transaction even before streaming started");
595 984 : }
596 1405 : assert!(startpos <= disk_lsn);
597 1405 : let mut broadcasted = Lsn(startpos);
598 :
599 : loop {
600 4586 : let available = disk.lock().flush_rec_ptr();
601 4586 : assert!(available >= broadcasted);
602 3181 : callback.broadcast(broadcasted, available);
603 3181 : broadcasted = available;
604 3181 : callback.poll();
605 : }
606 : }
607 :
608 15465 : fn process_safekeeper_feedback(
609 15465 : &mut self,
610 15465 : wp: &mut walproposer::bindings::WalProposer,
611 15465 : _sk: &mut walproposer::bindings::Safekeeper,
612 15465 : ) {
613 15465 : debug!("process_safekeeper_feedback, commit_lsn={}", wp.commitLsn);
614 15465 : if wp.commitLsn > self.last_logged_commit_lsn {
615 3221 : self.os.log_event(format!("commit_lsn;{}", wp.commitLsn));
616 3221 : self.last_logged_commit_lsn = wp.commitLsn;
617 12244 : }
618 15465 : }
619 :
620 854 : fn get_flush_rec_ptr(&self) -> u64 {
621 854 : let lsn = self.disk.lock().flush_rec_ptr();
622 854 : debug!("get_flush_rec_ptr: {}", lsn);
623 854 : lsn.0
624 854 : }
625 :
626 6113 : fn recovery_download(
627 6113 : &self,
628 6113 : wp: &mut walproposer::bindings::WalProposer,
629 6113 : sk: &mut walproposer::bindings::Safekeeper,
630 6113 : ) -> bool {
631 6113 : let mut startpos = wp.truncateLsn;
632 6113 : let endpos = wp.propEpochStartLsn;
633 6113 :
634 6113 : if startpos == endpos {
635 3684 : debug!("recovery_download: nothing to download");
636 3684 : return true;
637 2429 : }
638 2429 :
639 2429 : debug!("recovery_download from {} to {}", startpos, endpos,);
640 :
641 2429 : let replication_prompt = format!(
642 2429 : "START_REPLICATION {} {} {} {}",
643 2429 : self.config.ttid.tenant_id, self.config.ttid.timeline_id, startpos, endpos,
644 2429 : );
645 2429 : let async_conn = self.get_conn(sk);
646 2429 :
647 2429 : let conn = self.os.open_tcp(async_conn.node_id);
648 2429 : conn.send(desim::proto::AnyMessage::Bytes(replication_prompt.into()));
649 2429 :
650 2429 : let chan = conn.recv_chan();
651 4098 : while startpos < endpos {
652 2429 : let event = chan.recv();
653 2244 : match event {
654 : NetEvent::Closed => {
655 185 : debug!("connection closed in recovery");
656 185 : break;
657 : }
658 2244 : NetEvent::Message(AnyMessage::Bytes(b)) => {
659 2244 : debug!("got recovery bytes from safekeeper");
660 1669 : self.disk.lock().write(startpos, &b);
661 1669 : startpos += b.len() as u64;
662 : }
663 0 : NetEvent::Message(_) => unreachable!(),
664 : }
665 : }
666 :
667 1854 : debug!("recovery finished at {}", startpos);
668 :
669 1854 : startpos == endpos
670 5538 : }
671 :
672 89695 : fn conn_finish(&self, sk: &mut walproposer::bindings::Safekeeper) {
673 89695 : let mut conn = self.get_conn(sk);
674 89695 : debug!("conn_finish to {}", conn.node_id);
675 89695 : if let Some(socket) = conn.socket.as_mut() {
676 29264 : socket.close();
677 60431 : } else {
678 60431 : // connection is already closed
679 60431 : }
680 89695 : conn.socket = None;
681 89695 : }
682 :
683 87563 : fn conn_error_message(&self, _sk: &mut walproposer::bindings::Safekeeper) -> String {
684 87563 : "connection is closed, probably".into()
685 87563 : }
686 : }
|