MCPcopy Create free account
hub / github.com/NodeDB-Lab/nodedb / write_record_deferred

Method write_record_deferred

nodedb-wal/src/double_write.rs:245–298  ·  view source on GitHub ↗

Write a WAL record to the DWB without fsyncing. The data is written to the OS page cache (Buffered mode) or directly to the block device (Direct mode) but not guaranteed durable until `flush()` is called. Use this in batch mode: write all records in a group commit batch, then call `flush()` once — reducing fsync calls from N-per-batch to 1-per-batch.

(&mut self, record: &WalRecord)

Source from the content-addressed store, hash-verified

243 /// group commit batch, then call `flush()` once — reducing fsync calls
244 /// from N-per-batch to 1-per-batch.
245 pub fn write_record_deferred(&mut self, record: &WalRecord) -> Result<()> {
246 let total_size = HEADER_SIZE + record.payload.len();
247
248 // Max 64 KiB per slot — larger records skip the double-write buffer
249 // (they're multi-page and need different protection).
250 if total_size > DWB_SLOT_PAYLOAD_MAX {
251 return Ok(()); // Skip oversized records.
252 }
253
254 let header_bytes = record.header.to_bytes();
255 let offset = slot_offset(self.write_pos);
256
257 match self.mode {
258 DwbMode::Off => unreachable!("Off never opens a DoubleWriteBuffer"),
259 DwbMode::Buffered => {
260 self.file
261 .seek(SeekFrom::Start(offset))
262 .map_err(WalError::Io)?;
263 self.file
264 .write_all(&(total_size as u32).to_le_bytes())
265 .map_err(WalError::Io)?;
266 self.file.write_all(&header_bytes).map_err(WalError::Io)?;
267 self.file.write_all(&record.payload).map_err(WalError::Io)?;
268 DWB_BYTES_WRITTEN_TOTAL.fetch_add(
269 (4 + header_bytes.len() + record.payload.len()) as u64,
270 Ordering::Relaxed,
271 );
272 }
273 DwbMode::Direct => {
274 let buf = self
275 .slot_buf
276 .as_mut()
277 .expect("slot_buf present in Direct mode");
278 buf.clear();
279 buf.write(&(total_size as u32).to_le_bytes());
280 buf.write(&header_bytes);
281 buf.write(&record.payload);
282 // Zero the tail so the full aligned slot can be written
283 // without leaking prior contents.
284 zero_tail(buf);
285 let slice = full_capacity_slice(buf);
286 debug_assert_eq!(slice.len(), DWB_SLOT_STRIDE);
287 debug_assert!(is_aligned(offset as usize, DEFAULT_ALIGNMENT));
288 pwrite_all(&self.file, slice, offset)?;
289 DWB_BYTES_WRITTEN_TOTAL.fetch_add(slice.len() as u64, Ordering::Relaxed);
290 }
291 }
292
293 self.write_pos = self.write_pos.wrapping_add(1);
294 self.count = self.count.saturating_add(1).min(DWB_CAPACITY as u32);
295 self.dirty = true;
296
297 Ok(())
298 }
299
300 /// Flush the DWB header and fsync the file.
301 ///

Callers 6

write_recordMethod · 0.80
flush_is_idempotentFunction · 0.80
recover_after_wraparoundFunction · 0.80
appendMethod · 0.80

Calls 9

slot_offsetFunction · 0.85
zero_tailFunction · 0.85
full_capacity_sliceFunction · 0.85
pwrite_allFunction · 0.85
lenMethod · 0.45
to_bytesMethod · 0.45
expectMethod · 0.45
clearMethod · 0.45
writeMethod · 0.45

Tested by 4

flush_is_idempotentFunction · 0.64
recover_after_wraparoundFunction · 0.64