Open or create the double-write buffer file in the requested I/O mode. Returns `None`-wrapped errors for unsupported modes via `Err(WalError::…)`; callers that want "off" should not call this at all.
(path: &Path, mode: DwbMode)
| 163 | /// Returns `None`-wrapped errors for unsupported modes via |
| 164 | /// `Err(WalError::…)`; callers that want "off" should not call this at all. |
| 165 | pub fn open(path: &Path, mode: DwbMode) -> Result<Self> { |
| 166 | if mode == DwbMode::Off { |
| 167 | return Err(WalError::DwbOffNotOpenable); |
| 168 | } |
| 169 | |
| 170 | let mut opts = OpenOptions::new(); |
| 171 | opts.read(true).write(true).create(true).truncate(false); |
| 172 | #[cfg(not(target_arch = "wasm32"))] |
| 173 | if mode == DwbMode::Direct { |
| 174 | opts.custom_flags(libc::O_DIRECT); |
| 175 | } |
| 176 | |
| 177 | let file = opts.open(path).map_err(|e| { |
| 178 | tracing::warn!(path = %path.display(), error = %e, mode = ?mode, "failed to open double-write buffer"); |
| 179 | WalError::Io(e) |
| 180 | })?; |
| 181 | |
| 182 | let (slot_buf, header_buf) = if mode == DwbMode::Direct { |
| 183 | ( |
| 184 | Some(AlignedBuf::new(DWB_SLOT_STRIDE, DEFAULT_ALIGNMENT)?), |
| 185 | Some(AlignedBuf::new(DWB_HEADER_STRIDE, DEFAULT_ALIGNMENT)?), |
| 186 | ) |
| 187 | } else { |
| 188 | (None, None) |
| 189 | }; |
| 190 | |
| 191 | let mut dwb = Self { |
| 192 | file, |
| 193 | path: path.to_path_buf(), |
| 194 | mode, |
| 195 | write_pos: 0, |
| 196 | count: 0, |
| 197 | dirty: false, |
| 198 | slot_buf, |
| 199 | header_buf, |
| 200 | }; |
| 201 | |
| 202 | // Try to read existing header (first DWB_HEADER_FIELDS bytes of block 0). |
| 203 | let file_len = dwb.file.metadata().map(|m| m.len()).unwrap_or(0); |
| 204 | if file_len >= DWB_HEADER_STRIDE as u64 { |
| 205 | let mut block = vec![0u8; DWB_HEADER_STRIDE]; |
| 206 | dwb.file.seek(SeekFrom::Start(0)).map_err(WalError::Io)?; |
| 207 | if dwb.file.read_exact(&mut block).is_ok() { |
| 208 | let mut arr4 = [0u8; 4]; |
| 209 | arr4.copy_from_slice(&block[0..4]); |
| 210 | let magic = u32::from_le_bytes(arr4); |
| 211 | if magic == DWB_MAGIC { |
| 212 | arr4.copy_from_slice(&block[4..8]); |
| 213 | dwb.count = u32::from_le_bytes(arr4); |
| 214 | arr4.copy_from_slice(&block[8..12]); |
| 215 | dwb.write_pos = u32::from_le_bytes(arr4); |
| 216 | } |
| 217 | } |
| 218 | } |
| 219 | |
| 220 | Ok(dwb) |
| 221 | } |
| 222 |