LCOV - code coverage report
Current view: top level - safekeeper/src - timeline_guard.rs (source / functions) Coverage Total Hit
Test: 52d9d4a58355424a48c56cb9ba9670a073f618b9.info Lines: 0.0 % 36 0
Test Date: 2024-11-21 08:31:22 Functions: 0.0 % 5 0

            Line data    Source code
       1              : //! Timeline residence guard
       2              : //!
       3              : //! It is needed to ensure that WAL segments are present on disk,
       4              : //! as long as the code is holding the guard. This file implements guard logic, to issue
       5              : //! and drop guards, and to notify the manager when the guard is dropped.
       6              : 
       7              : use std::collections::HashSet;
       8              : 
       9              : use tracing::debug;
      10              : use utils::sync::gate::GateGuard;
      11              : 
      12              : use crate::timeline_manager::ManagerCtlMessage;
      13              : 
      14              : #[derive(Debug, Clone, Copy)]
      15              : pub struct GuardId(u64);
      16              : 
      17              : pub struct ResidenceGuard {
      18              :     manager_tx: tokio::sync::mpsc::UnboundedSender<ManagerCtlMessage>,
      19              :     guard_id: GuardId,
      20              : 
      21              :     /// [`ResidenceGuard`] represents a guarantee that a timeline's data remains resident,
      22              :     /// which by extension also means the timeline is not shut down (since after shut down
      23              :     /// our data may be deleted). Therefore everyone holding a residence guard must also
      24              :     /// hold a guard on [`crate::timeline::Timeline::gate`]
      25              :     _gate_guard: GateGuard,
      26              : }
      27              : 
      28              : impl Drop for ResidenceGuard {
      29            0 :     fn drop(&mut self) {
      30            0 :         // notify the manager that the guard is dropped
      31            0 :         let res = self
      32            0 :             .manager_tx
      33            0 :             .send(ManagerCtlMessage::GuardDrop(self.guard_id));
      34            0 :         if let Err(e) = res {
      35            0 :             debug!("failed to send GuardDrop message: {:?}", e);
      36            0 :         }
      37            0 :     }
      38              : }
      39              : 
      40              : /// AccessService is responsible for issuing and dropping residence guards.
      41              : /// All guards are stored in the `guards` set.
      42              : /// TODO: it's possible to add `String` name to each guard, for better observability.
      43              : pub(crate) struct AccessService {
      44              :     next_guard_id: u64,
      45              :     guards: HashSet<u64>,
      46              :     manager_tx: tokio::sync::mpsc::UnboundedSender<ManagerCtlMessage>,
      47              : }
      48              : 
      49              : impl AccessService {
      50            0 :     pub(crate) fn new(manager_tx: tokio::sync::mpsc::UnboundedSender<ManagerCtlMessage>) -> Self {
      51            0 :         Self {
      52            0 :             next_guard_id: 0,
      53            0 :             guards: HashSet::new(),
      54            0 :             manager_tx,
      55            0 :         }
      56            0 :     }
      57              : 
      58            0 :     pub(crate) fn is_empty(&self) -> bool {
      59            0 :         self.guards.is_empty()
      60            0 :     }
      61              : 
      62              :     /// `timeline_gate_guard` is a guarantee that the timeline is not shut down
      63            0 :     pub(crate) fn create_guard(&mut self, timeline_gate_guard: GateGuard) -> ResidenceGuard {
      64            0 :         let guard_id = self.next_guard_id;
      65            0 :         self.next_guard_id += 1;
      66            0 :         self.guards.insert(guard_id);
      67            0 : 
      68            0 :         let guard_id = GuardId(guard_id);
      69            0 :         debug!("issued a new guard {:?}", guard_id);
      70              : 
      71            0 :         ResidenceGuard {
      72            0 :             manager_tx: self.manager_tx.clone(),
      73            0 :             guard_id,
      74            0 :             _gate_guard: timeline_gate_guard,
      75            0 :         }
      76            0 :     }
      77              : 
      78            0 :     pub(crate) fn drop_guard(&mut self, guard_id: GuardId) {
      79            0 :         debug!("dropping guard {:?}", guard_id);
      80            0 :         assert!(self.guards.remove(&guard_id.0));
      81            0 :     }
      82              : }
        

Generated by: LCOV version 2.1-beta