Open a WAL segment file for mmap'd reading.
(path: &Path)
| 89 | impl MmapWalReader { |
| 90 | /// Open a WAL segment file for mmap'd reading. |
| 91 | pub fn open(path: &Path) -> Result<Self> { |
| 92 | observability::SEGMENTS_OPENED.fetch_add(1, Ordering::Relaxed); |
| 93 | let file = std::fs::File::open(path)?; |
| 94 | // SAFETY: The file is a sealed WAL segment (not being written to). |
| 95 | // The Data Plane writes to the ACTIVE segment via O_DIRECT; sealed |
| 96 | // segments are immutable after rollover. |
| 97 | let mmap = unsafe { Mmap::map(&file)? }; |
| 98 | |
| 99 | // Catchup iterates forward through a segment. MADV_SEQUENTIAL |
| 100 | // doubles readahead and drops already-consumed pages eagerly so |
| 101 | // replay doesn't grow buff/cache by the full WAL size. |
| 102 | let mut madvise_state = None; |
| 103 | if !mmap.is_empty() { |
| 104 | let rc = unsafe { |
| 105 | libc::madvise( |
| 106 | mmap.as_ptr() as *mut libc::c_void, |
| 107 | mmap.len(), |
| 108 | libc::MADV_SEQUENTIAL, |
| 109 | ) |
| 110 | }; |
| 111 | if rc == 0 { |
| 112 | madvise_state = Some(libc::MADV_SEQUENTIAL); |
| 113 | observability::MADV_SEQUENTIAL_COUNT.fetch_add(1, Ordering::Relaxed); |
| 114 | } else { |
| 115 | tracing::warn!( |
| 116 | path = %path.display(), |
| 117 | errno = std::io::Error::last_os_error().raw_os_error().unwrap_or(0), |
| 118 | "madvise(MADV_SEQUENTIAL) failed on WAL segment; continuing", |
| 119 | ); |
| 120 | } |
| 121 | } |
| 122 | |
| 123 | Ok(Self { |
| 124 | mmap, |
| 125 | offset: 0, |
| 126 | file, |
| 127 | path: path.to_path_buf(), |
| 128 | madvise_state, |
| 129 | }) |
| 130 | } |
| 131 | |
| 132 | /// The madvise hint applied to the mapped segment (if any). |
| 133 | pub fn madvise_state(&self) -> Option<libc::c_int> { |