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 216615 : pub fn new(host: String, port: String) -> Self {
45 216615 : // port number is the same as NodeId
46 216615 : let port_num = port.parse::<u32>().unwrap();
47 216615 : Self {
48 216615 : host,
49 216615 : port,
50 216615 : node_id: port_num,
51 216615 : socket: None,
52 216615 : is_connecting: false,
53 216615 : is_start_wal_push: false,
54 216615 : raw_ptr: std::ptr::null_mut(),
55 216615 : }
56 216615 : }
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 72205 : pub fn new(os: NodeOs) -> Self {
73 72205 : let node_events = os.node_events();
74 72205 : Self {
75 72205 : os,
76 72205 : chans: vec![Box::new(node_events)],
77 72205 : sk_ptrs: vec![std::ptr::null_mut()],
78 72205 : masks: vec![WL_SOCKET_READABLE],
79 72205 : }
80 72205 : }
81 :
82 : /// Leaves all readable channels at the beginning of the array.
83 220490 : fn sort_readable(&mut self) -> usize {
84 220490 : let mut cnt = 1;
85 523923 : for i in 1..self.chans.len() {
86 523923 : if self.masks[i] & WL_SOCKET_READABLE != 0 {
87 523923 : self.chans.swap(i, cnt);
88 523923 : self.sk_ptrs.swap(i, cnt);
89 523923 : self.masks.swap(i, cnt);
90 523923 : cnt += 1;
91 523923 : }
92 : }
93 220490 : cnt
94 220490 : }
95 :
96 531385 : fn update_event_set(&mut self, conn: &SafekeeperConn, event_mask: u32) {
97 531385 : let index = self
98 531385 : .sk_ptrs
99 531385 : .iter()
100 2004358 : .position(|&ptr| ptr == conn.raw_ptr)
101 531385 : .expect("safekeeper should exist in event set");
102 531385 : self.masks[index] = event_mask;
103 531385 : }
104 :
105 479560 : fn add_safekeeper(&mut self, sk: &SafekeeperConn, event_mask: u32) {
106 1160108 : for ptr in self.sk_ptrs.iter() {
107 1160108 : assert!(*ptr != sk.raw_ptr);
108 : }
109 :
110 479560 : self.chans.push(Box::new(
111 479560 : sk.socket
112 479560 : .as_ref()
113 479560 : .expect("socket should not be closed")
114 479560 : .recv_chan(),
115 479560 : ));
116 479560 : self.sk_ptrs.push(sk.raw_ptr);
117 479560 : self.masks.push(event_mask);
118 479560 : }
119 :
120 302053 : fn remove_safekeeper(&mut self, sk: &SafekeeperConn) {
121 642699 : let index = self.sk_ptrs.iter().position(|&ptr| ptr == sk.raw_ptr);
122 302053 : if index.is_none() {
123 41 : debug!("remove_safekeeper: sk={:?} not found", sk.raw_ptr);
124 41 : return;
125 302012 : }
126 302012 : let index = index.unwrap();
127 302012 :
128 302012 : self.chans.remove(index);
129 302012 : self.sk_ptrs.remove(index);
130 302012 : self.masks.remove(index);
131 302012 :
132 302012 : // to simulate the actual behaviour
133 302012 : self.refresh_event_set();
134 302053 : }
135 :
136 : /// Updates all masks to match the result of a SafekeeperStateDesiredEvents.
137 342426 : fn refresh_event_set(&mut self) {
138 966993 : for (i, mask) in self.masks.iter_mut().enumerate() {
139 966993 : if i == 0 {
140 342426 : continue;
141 624567 : }
142 624567 :
143 624567 : let mut mask_sk: u32 = 0;
144 624567 : let mut mask_nwr: u32 = 0;
145 624567 : unsafe { SafekeeperStateDesiredEvents(self.sk_ptrs[i], &mut mask_sk, &mut mask_nwr) };
146 624567 :
147 624567 : 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 624567 : }
154 : }
155 342426 : }
156 :
157 : /// Wait for events on all channels.
158 220490 : fn wait(&mut self, timeout_millis: i64) -> walproposer::walproposer::WaitResult {
159 : // all channels are always writeable
160 744413 : for (i, mask) in self.masks.iter().enumerate() {
161 744413 : 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 744413 : }
167 : }
168 :
169 220490 : let cnt = self.sort_readable();
170 220490 :
171 220490 : let slice = &self.chans[0..cnt];
172 220490 : match executor::epoll_chans(slice, timeout_millis) {
173 89947 : None => walproposer::walproposer::WaitResult::Timeout,
174 : Some(0) => {
175 3131 : let msg = self.os.node_events().must_recv();
176 3131 : match msg {
177 3131 : NodeEvent::Internal(AnyMessage::Just32(0)) => {
178 3131 : // got a notification about new WAL available
179 3131 : }
180 0 : NodeEvent::Internal(_) => unreachable!(),
181 0 : NodeEvent::Accept(_) => unreachable!(),
182 : }
183 3131 : walproposer::walproposer::WaitResult::Latch
184 : }
185 127412 : Some(index) => walproposer::walproposer::WaitResult::Network(
186 127412 : self.sk_ptrs[index],
187 127412 : WL_SOCKET_READABLE,
188 127412 : ),
189 : }
190 220490 : }
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 : shmem: UnsafeCell<walproposer::bindings::WalproposerShmemState>,
200 : config: Config,
201 : event_set: RefCell<Option<EventSet>>,
202 : }
203 :
204 : pub struct Args {
205 : pub os: NodeOs,
206 : pub config: Config,
207 : pub disk: Arc<DiskWalProposer>,
208 : pub redo_start_lsn: Option<Lsn>,
209 : }
210 :
211 : impl SimulationApi {
212 72205 : pub fn new(args: Args) -> Self {
213 72205 : // initialize connection state for each safekeeper
214 72205 : let sk_conns = args
215 72205 : .config
216 72205 : .safekeepers_list
217 72205 : .iter()
218 216615 : .map(|s| {
219 216615 : SafekeeperConn::new(
220 216615 : s.split(':').next().unwrap().to_string(),
221 216615 : s.split(':').nth(1).unwrap().to_string(),
222 216615 : )
223 216615 : })
224 72205 : .collect::<Vec<_>>();
225 72205 :
226 72205 : Self {
227 72205 : os: args.os,
228 72205 : safekeepers: RefCell::new(sk_conns),
229 72205 : disk: args.disk,
230 72205 : redo_start_lsn: args.redo_start_lsn,
231 72205 : shmem: UnsafeCell::new(walproposer::bindings::WalproposerShmemState {
232 72205 : mutex: 0,
233 72205 : feedback: PageserverFeedback {
234 72205 : currentClusterSize: 0,
235 72205 : last_received_lsn: 0,
236 72205 : disk_consistent_lsn: 0,
237 72205 : remote_consistent_lsn: 0,
238 72205 : replytime: 0,
239 72205 : },
240 72205 : mineLastElectedTerm: 0,
241 72205 : backpressureThrottlingTime: pg_atomic_uint64 { value: 0 },
242 72205 : }),
243 72205 : config: args.config,
244 72205 : event_set: RefCell::new(None),
245 72205 : }
246 72205 : }
247 :
248 : /// Get SafekeeperConn for the given Safekeeper.
249 2355030 : fn get_conn(&self, sk: &mut walproposer::bindings::Safekeeper) -> RefMut<'_, SafekeeperConn> {
250 2355030 : let sk_port = unsafe { CStr::from_ptr(sk.port).to_str().unwrap() };
251 2355030 : let state = self.safekeepers.borrow_mut();
252 2355030 : RefMut::map(state, |v| {
253 2355030 : v.iter_mut()
254 4706190 : .find(|conn| conn.port == sk_port)
255 2355030 : .expect("safekeeper conn not found by port")
256 2355030 : })
257 2355030 : }
258 : }
259 :
260 : impl ApiImpl for SimulationApi {
261 2513334 : fn get_current_timestamp(&self) -> i64 {
262 2513334 : debug!("get_current_timestamp");
263 : // PG TimestampTZ is microseconds, but simulation unit is assumed to be
264 : // milliseconds, so add 10^3
265 2513334 : self.os.now() as i64 * 1000
266 2513334 : }
267 :
268 266482 : fn conn_status(
269 266482 : &self,
270 266482 : _: &mut walproposer::bindings::Safekeeper,
271 266482 : ) -> walproposer::bindings::WalProposerConnStatusType {
272 266482 : debug!("conn_status");
273 : // break the connection with a 10% chance
274 266482 : if self.os.random(100) < 10 {
275 26702 : walproposer::bindings::WalProposerConnStatusType_WP_CONNECTION_BAD
276 : } else {
277 239780 : walproposer::bindings::WalProposerConnStatusType_WP_CONNECTION_OK
278 : }
279 266482 : }
280 :
281 266482 : fn conn_connect_start(&self, sk: &mut walproposer::bindings::Safekeeper) {
282 266482 : debug!("conn_connect_start");
283 266482 : let mut conn = self.get_conn(sk);
284 266482 :
285 266482 : assert!(conn.socket.is_none());
286 266482 : let socket = self.os.open_tcp(conn.node_id);
287 266482 : conn.socket = Some(socket);
288 266482 : conn.raw_ptr = sk;
289 266482 : conn.is_connecting = true;
290 266482 : }
291 :
292 239780 : fn conn_connect_poll(
293 239780 : &self,
294 239780 : _: &mut walproposer::bindings::Safekeeper,
295 239780 : ) -> walproposer::bindings::WalProposerConnectPollStatusType {
296 239780 : debug!("conn_connect_poll");
297 : // TODO: break the connection here
298 239780 : walproposer::bindings::WalProposerConnectPollStatusType_WP_CONN_POLLING_OK
299 239780 : }
300 :
301 239780 : fn conn_send_query(&self, sk: &mut walproposer::bindings::Safekeeper, query: &str) -> bool {
302 239780 : debug!("conn_send_query: {}", query);
303 239780 : self.get_conn(sk).is_start_wal_push = true;
304 239780 : true
305 239780 : }
306 :
307 239780 : fn conn_get_query_result(
308 239780 : &self,
309 239780 : _: &mut walproposer::bindings::Safekeeper,
310 239780 : ) -> walproposer::bindings::WalProposerExecStatusType {
311 239780 : debug!("conn_get_query_result");
312 : // TODO: break the connection here
313 239780 : walproposer::bindings::WalProposerExecStatusType_WP_EXEC_SUCCESS_COPYBOTH
314 239780 : }
315 :
316 139410 : fn conn_async_read(
317 139410 : &self,
318 139410 : sk: &mut walproposer::bindings::Safekeeper,
319 139410 : vec: &mut Vec<u8>,
320 139410 : ) -> walproposer::bindings::PGAsyncReadResult {
321 139410 : debug!("conn_async_read");
322 139410 : let mut conn = self.get_conn(sk);
323 :
324 139410 : let socket = if let Some(socket) = conn.socket.as_mut() {
325 139410 : socket
326 : } else {
327 : // socket is already closed
328 0 : return walproposer::bindings::PGAsyncReadResult_PG_ASYNC_READ_FAIL;
329 : };
330 :
331 139410 : let msg = socket.recv_chan().try_recv();
332 :
333 125758 : match msg {
334 : None => {
335 : // no message is ready
336 13652 : walproposer::bindings::PGAsyncReadResult_PG_ASYNC_READ_TRY_AGAIN
337 : }
338 : Some(NetEvent::Closed) => {
339 : // connection is closed
340 60065 : debug!("conn_async_read: connection is closed");
341 60065 : conn.socket = None;
342 60065 : walproposer::bindings::PGAsyncReadResult_PG_ASYNC_READ_FAIL
343 : }
344 65693 : Some(NetEvent::Message(msg)) => {
345 : // got a message
346 65693 : let b = match msg {
347 65693 : desim::proto::AnyMessage::Bytes(b) => b,
348 0 : _ => unreachable!(),
349 : };
350 65693 : vec.extend_from_slice(&b);
351 65693 : walproposer::bindings::PGAsyncReadResult_PG_ASYNC_READ_SUCCESS
352 : }
353 : }
354 139410 : }
355 :
356 269798 : fn conn_blocking_write(&self, sk: &mut walproposer::bindings::Safekeeper, buf: &[u8]) -> bool {
357 269798 : let mut conn = self.get_conn(sk);
358 269798 : debug!("conn_blocking_write to {}: {:?}", conn.node_id, buf);
359 269798 : let socket = conn.socket.as_mut().unwrap();
360 269798 : socket.send(desim::proto::AnyMessage::Bytes(Bytes::copy_from_slice(buf)));
361 269798 : true
362 269798 : }
363 :
364 35254 : fn conn_async_write(
365 35254 : &self,
366 35254 : sk: &mut walproposer::bindings::Safekeeper,
367 35254 : buf: &[u8],
368 35254 : ) -> walproposer::bindings::PGAsyncWriteResult {
369 35254 : let mut conn = self.get_conn(sk);
370 35254 : debug!("conn_async_write to {}: {:?}", conn.node_id, buf);
371 35254 : if let Some(socket) = conn.socket.as_mut() {
372 35254 : socket.send(desim::proto::AnyMessage::Bytes(Bytes::copy_from_slice(buf)));
373 35254 : } else {
374 : // connection is already closed
375 0 : debug!("conn_async_write: writing to a closed socket!");
376 : // TODO: maybe we should return error here?
377 : }
378 35254 : walproposer::bindings::PGAsyncWriteResult_PG_ASYNC_WRITE_SUCCESS
379 35254 : }
380 :
381 7960 : fn wal_reader_allocate(&self, _: &mut walproposer::bindings::Safekeeper) -> NeonWALReadResult {
382 7960 : debug!("wal_reader_allocate");
383 7960 : walproposer::bindings::NeonWALReadResult_NEON_WALREAD_SUCCESS
384 7960 : }
385 :
386 27294 : fn wal_read(
387 27294 : &self,
388 27294 : _sk: &mut walproposer::bindings::Safekeeper,
389 27294 : buf: &mut [u8],
390 27294 : startpos: u64,
391 27294 : ) -> NeonWALReadResult {
392 27294 : self.disk.lock().read(startpos, buf);
393 27294 : walproposer::bindings::NeonWALReadResult_NEON_WALREAD_SUCCESS
394 27294 : }
395 :
396 72205 : fn init_event_set(&self, _: &mut walproposer::bindings::WalProposer) {
397 72205 : debug!("init_event_set");
398 72205 : let new_event_set = EventSet::new(self.os.clone());
399 72205 : let old_event_set = self.event_set.replace(Some(new_event_set));
400 72205 : assert!(old_event_set.is_none());
401 72205 : }
402 :
403 531385 : fn update_event_set(&self, sk: &mut walproposer::bindings::Safekeeper, event_mask: u32) {
404 531385 : debug!(
405 1166 : "update_event_set, sk={:?}, events_mask={:#b}",
406 1166 : sk as *mut walproposer::bindings::Safekeeper, event_mask
407 1166 : );
408 531385 : let conn = self.get_conn(sk);
409 531385 :
410 531385 : self.event_set
411 531385 : .borrow_mut()
412 531385 : .as_mut()
413 531385 : .unwrap()
414 531385 : .update_event_set(&conn, event_mask);
415 531385 : }
416 :
417 479560 : fn add_safekeeper_event_set(
418 479560 : &self,
419 479560 : sk: &mut walproposer::bindings::Safekeeper,
420 479560 : event_mask: u32,
421 479560 : ) {
422 479560 : debug!(
423 728 : "add_safekeeper_event_set, sk={:?}, events_mask={:#b}",
424 728 : sk as *mut walproposer::bindings::Safekeeper, event_mask
425 728 : );
426 :
427 479560 : self.event_set
428 479560 : .borrow_mut()
429 479560 : .as_mut()
430 479560 : .unwrap()
431 479560 : .add_safekeeper(&self.get_conn(sk), event_mask);
432 479560 : }
433 :
434 302053 : fn rm_safekeeper_event_set(&self, sk: &mut walproposer::bindings::Safekeeper) {
435 302053 : debug!(
436 400 : "rm_safekeeper_event_set, sk={:?}",
437 400 : sk as *mut walproposer::bindings::Safekeeper,
438 400 : );
439 :
440 302053 : self.event_set
441 302053 : .borrow_mut()
442 302053 : .as_mut()
443 302053 : .unwrap()
444 302053 : .remove_safekeeper(&self.get_conn(sk));
445 302053 : }
446 :
447 40414 : fn active_state_update_event_set(&self, sk: &mut walproposer::bindings::Safekeeper) {
448 40414 : debug!("active_state_update_event_set");
449 :
450 40414 : assert!(sk.state == walproposer::bindings::SafekeeperState_SS_ACTIVE);
451 40414 : self.event_set
452 40414 : .borrow_mut()
453 40414 : .as_mut()
454 40414 : .unwrap()
455 40414 : .refresh_event_set();
456 40414 : }
457 :
458 115200 : fn wal_reader_events(&self, _sk: &mut walproposer::bindings::Safekeeper) -> u32 {
459 115200 : 0
460 115200 : }
461 :
462 700050 : fn wait_event_set(
463 700050 : &self,
464 700050 : _: &mut walproposer::bindings::WalProposer,
465 700050 : timeout_millis: i64,
466 700050 : ) -> walproposer::walproposer::WaitResult {
467 700050 : // TODO: handle multiple stages as part of the simulation (e.g. connect, start_wal_push, etc)
468 700050 : let mut conns = self.safekeepers.borrow_mut();
469 1620458 : for conn in conns.iter_mut() {
470 1620458 : if conn.socket.is_some() && conn.is_connecting {
471 239780 : conn.is_connecting = false;
472 239780 : debug!("wait_event_set, connecting to {}:{}", conn.host, conn.port);
473 239780 : return walproposer::walproposer::WaitResult::Network(
474 239780 : conn.raw_ptr,
475 239780 : WL_SOCKET_READABLE | WL_SOCKET_WRITEABLE,
476 239780 : );
477 1380678 : }
478 1380678 : if conn.socket.is_some() && conn.is_start_wal_push {
479 239780 : conn.is_start_wal_push = false;
480 239780 : debug!(
481 364 : "wait_event_set, start wal push to {}:{}",
482 364 : conn.host, conn.port
483 364 : );
484 239780 : return walproposer::walproposer::WaitResult::Network(
485 239780 : conn.raw_ptr,
486 239780 : WL_SOCKET_READABLE,
487 239780 : );
488 1140898 : }
489 : }
490 220490 : drop(conns);
491 220490 :
492 220490 : let res = self
493 220490 : .event_set
494 220490 : .borrow_mut()
495 220490 : .as_mut()
496 220490 : .unwrap()
497 220490 : .wait(timeout_millis);
498 220490 :
499 220490 : debug!(
500 690 : "wait_event_set, timeout_millis={}, res={:?}",
501 690 : timeout_millis, res,
502 690 : );
503 152352 : res
504 631912 : }
505 :
506 72205 : fn strong_random(&self, buf: &mut [u8]) -> bool {
507 72205 : debug!("strong_random");
508 72205 : buf.fill(0);
509 72205 : true
510 72205 : }
511 :
512 2938 : fn finish_sync_safekeepers(&self, lsn: u64) {
513 2938 : debug!("finish_sync_safekeepers, lsn={}", lsn);
514 2938 : executor::exit(0, Lsn(lsn).to_string());
515 2938 : }
516 :
517 790091 : fn log_internal(&self, _wp: &mut walproposer::bindings::WalProposer, level: Level, msg: &str) {
518 790091 : debug!("wp_log[{}] {}", level, msg);
519 790091 : if level == Level::Fatal || level == Level::Panic {
520 565 : if msg.contains("rejects our connection request with term") {
521 313 : // collected quorum with lower term, then got rejected by next connected safekeeper
522 313 : executor::exit(1, msg.to_owned());
523 313 : }
524 565 : if msg.contains("collected propEpochStartLsn") && msg.contains(", but basebackup LSN ")
525 21 : {
526 21 : // sync-safekeepers collected wrong quorum, walproposer collected another quorum
527 21 : executor::exit(1, msg.to_owned());
528 544 : }
529 565 : if msg.contains("failed to download WAL for logical replicaiton") {
530 158 : // Recovery connection broken and recovery was failed
531 158 : executor::exit(1, msg.to_owned());
532 407 : }
533 565 : if msg.contains("missing majority of votes, collected") {
534 73 : // Voting bug when safekeeper disconnects after voting
535 73 : executor::exit(1, msg.to_owned());
536 492 : }
537 565 : panic!("unknown FATAL error from walproposer: {}", msg);
538 789526 : }
539 789526 : }
540 :
541 5955 : fn after_election(&self, wp: &mut walproposer::bindings::WalProposer) {
542 5955 : let prop_lsn = wp.propEpochStartLsn;
543 5955 : let prop_term = wp.propTerm;
544 5955 :
545 5955 : let mut prev_lsn: u64 = 0;
546 5955 : let mut prev_term: u64 = 0;
547 5955 :
548 5955 : unsafe {
549 5955 : let history = wp.propTermHistory.entries;
550 5955 : let len = wp.propTermHistory.n_entries as usize;
551 5955 : if len > 1 {
552 3943 : let entry = *history.wrapping_add(len - 2);
553 3943 : prev_lsn = entry.lsn;
554 3943 : prev_term = entry.term;
555 3943 : }
556 : }
557 :
558 5955 : let msg = format!(
559 5955 : "prop_elected;{};{};{};{}",
560 5955 : prop_lsn, prop_term, prev_lsn, prev_term
561 5955 : );
562 5955 :
563 5955 : debug!(msg);
564 5955 : self.os.log_event(msg);
565 5955 : }
566 :
567 2224 : fn get_redo_start_lsn(&self) -> u64 {
568 2224 : debug!("get_redo_start_lsn -> {:?}", self.redo_start_lsn);
569 2224 : self.redo_start_lsn.expect("redo_start_lsn is not set").0
570 2224 : }
571 :
572 1328 : fn get_shmem_state(&self) -> *mut walproposer::bindings::WalproposerShmemState {
573 1328 : self.shmem.get()
574 1328 : }
575 :
576 1278 : fn start_streaming(
577 1278 : &self,
578 1278 : startpos: u64,
579 1278 : callback: &walproposer::walproposer::StreamingCallback,
580 1278 : ) {
581 1278 : let disk = &self.disk;
582 1278 : let disk_lsn = disk.lock().flush_rec_ptr().0;
583 1278 : debug!("start_streaming at {} (disk_lsn={})", startpos, disk_lsn);
584 1278 : if startpos < disk_lsn {
585 404 : debug!("startpos < disk_lsn, it means we wrote some transaction even before streaming started");
586 874 : }
587 1278 : assert!(startpos <= disk_lsn);
588 1278 : let mut broadcasted = Lsn(startpos);
589 :
590 : loop {
591 4228 : let available = disk.lock().flush_rec_ptr();
592 4228 : assert!(available >= broadcasted);
593 2950 : callback.broadcast(broadcasted, available);
594 2950 : broadcasted = available;
595 2950 : callback.poll();
596 : }
597 : }
598 :
599 13652 : fn process_safekeeper_feedback(
600 13652 : &self,
601 13652 : wp: &mut walproposer::bindings::WalProposer,
602 13652 : commit_lsn: u64,
603 13652 : ) {
604 13652 : debug!("process_safekeeper_feedback, commit_lsn={}", commit_lsn);
605 13652 : if commit_lsn > wp.lastSentCommitLsn {
606 2974 : self.os.log_event(format!("commit_lsn;{}", commit_lsn));
607 10678 : }
608 13652 : }
609 :
610 859 : fn get_flush_rec_ptr(&self) -> u64 {
611 859 : let lsn = self.disk.lock().flush_rec_ptr();
612 859 : debug!("get_flush_rec_ptr: {}", lsn);
613 859 : lsn.0
614 859 : }
615 :
616 5955 : fn recovery_download(
617 5955 : &self,
618 5955 : wp: &mut walproposer::bindings::WalProposer,
619 5955 : sk: &mut walproposer::bindings::Safekeeper,
620 5955 : ) -> bool {
621 5955 : let mut startpos = wp.truncateLsn;
622 5955 : let endpos = wp.propEpochStartLsn;
623 5955 :
624 5955 : if startpos == endpos {
625 3622 : debug!("recovery_download: nothing to download");
626 3622 : return true;
627 2333 : }
628 2333 :
629 2333 : debug!("recovery_download from {} to {}", startpos, endpos,);
630 :
631 2333 : let replication_prompt = format!(
632 2333 : "START_REPLICATION {} {} {} {}",
633 2333 : self.config.ttid.tenant_id, self.config.ttid.timeline_id, startpos, endpos,
634 2333 : );
635 2333 : let async_conn = self.get_conn(sk);
636 2333 :
637 2333 : let conn = self.os.open_tcp(async_conn.node_id);
638 2333 : conn.send(desim::proto::AnyMessage::Bytes(replication_prompt.into()));
639 2333 :
640 2333 : let chan = conn.recv_chan();
641 3944 : while startpos < endpos {
642 2333 : let event = chan.recv();
643 2175 : match event {
644 : NetEvent::Closed => {
645 158 : debug!("connection closed in recovery");
646 158 : break;
647 : }
648 2175 : NetEvent::Message(AnyMessage::Bytes(b)) => {
649 2175 : debug!("got recovery bytes from safekeeper");
650 1611 : self.disk.lock().write(startpos, &b);
651 1611 : startpos += b.len() as u64;
652 : }
653 0 : NetEvent::Message(_) => unreachable!(),
654 : }
655 : }
656 :
657 1769 : debug!("recovery finished at {}", startpos);
658 :
659 1769 : startpos == endpos
660 5391 : }
661 :
662 88975 : fn conn_finish(&self, sk: &mut walproposer::bindings::Safekeeper) {
663 88975 : let mut conn = self.get_conn(sk);
664 88975 : debug!("conn_finish to {}", conn.node_id);
665 88975 : if let Some(socket) = conn.socket.as_mut() {
666 28869 : socket.close();
667 60106 : } else {
668 60106 : // connection is already closed
669 60106 : }
670 88975 : conn.socket = None;
671 88975 : }
672 :
673 86767 : fn conn_error_message(&self, _sk: &mut walproposer::bindings::Safekeeper) -> String {
674 86767 : "connection is closed, probably".into()
675 86767 : }
676 : }
|