Flush the DWB header and fsync the file. Must be called after one or more `write_record_deferred` calls to make the records durable. The single fsync covers all deferred writes since the last flush — amortizing the cost across the group commit batch.
(&mut self)
| 303 | /// the records durable. The single fsync covers all deferred writes since |
| 304 | /// the last flush — amortizing the cost across the group commit batch. |
| 305 | pub fn flush(&mut self) -> Result<()> { |
| 306 | if !self.dirty { |
| 307 | return Ok(()); |
| 308 | } |
| 309 | |
| 310 | let mut header = [0u8; DWB_HEADER_FIELDS]; |
| 311 | header[0..4].copy_from_slice(&DWB_MAGIC.to_le_bytes()); |
| 312 | header[4..8].copy_from_slice(&self.count.to_le_bytes()); |
| 313 | header[8..12].copy_from_slice(&self.write_pos.to_le_bytes()); |
| 314 | |
| 315 | match self.mode { |
| 316 | DwbMode::Off => unreachable!("invariant: flush() is gated on mode != Off by caller"), |
| 317 | DwbMode::Buffered => { |
| 318 | self.file.seek(SeekFrom::Start(0)).map_err(WalError::Io)?; |
| 319 | self.file.write_all(&header).map_err(WalError::Io)?; |
| 320 | DWB_BYTES_WRITTEN_TOTAL.fetch_add(header.len() as u64, Ordering::Relaxed); |
| 321 | } |
| 322 | DwbMode::Direct => { |
| 323 | let buf = self |
| 324 | .header_buf |
| 325 | .as_mut() |
| 326 | .expect("header_buf present in Direct mode"); |
| 327 | buf.clear(); |
| 328 | buf.write(&header); |
| 329 | zero_tail(buf); |
| 330 | let slice = full_capacity_slice(buf); |
| 331 | debug_assert_eq!(slice.len(), DWB_HEADER_STRIDE); |
| 332 | pwrite_all(&self.file, slice, 0)?; |
| 333 | DWB_BYTES_WRITTEN_TOTAL.fetch_add(slice.len() as u64, Ordering::Relaxed); |
| 334 | } |
| 335 | } |
| 336 | |
| 337 | self.file.sync_all().map_err(WalError::Io)?; |
| 338 | self.dirty = false; |
| 339 | |
| 340 | Ok(()) |
| 341 | } |
| 342 | |
| 343 | /// Path to the double-write buffer file. |
| 344 | pub fn path(&self) -> &Path { |