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

Method next_record

nodedb-wal/src/reader.rs:83–147  ·  view source on GitHub ↗

Read the next record from the WAL. Returns `None` at EOF (clean end) or at the first corruption point. Returns `Err` only for I/O errors or unknown required record types.

(&mut self)

Source from the content-addressed store, hash-verified

81 /// Returns `None` at EOF (clean end) or at the first corruption point.
82 /// Returns `Err` only for I/O errors or unknown required record types.
83 pub fn next_record(&mut self) -> Result<Option<WalRecord>> {
84 loop {
85 // Read header.
86 let mut header_buf = [0u8; HEADER_SIZE];
87 match self.read_exact(&mut header_buf) {
88 Ok(()) => {}
89 Err(WalError::Io(e)) if e.kind() == std::io::ErrorKind::UnexpectedEof => {
90 return Ok(None); // Clean EOF.
91 }
92 Err(e) => return Err(e),
93 }
94
95 let header = RecordHeader::from_bytes(&header_buf);
96
97 // Validate magic and version.
98 if header.validate(self.offset - HEADER_SIZE as u64).is_err() {
99 // Corruption or end of valid data — treat as end of committed prefix.
100 return Ok(None);
101 }
102
103 // Read payload.
104 let mut payload = vec![0u8; header.payload_len as usize];
105 if !payload.is_empty() {
106 match self.read_exact(&mut payload) {
107 Ok(()) => {}
108 Err(WalError::Io(e)) if e.kind() == std::io::ErrorKind::UnexpectedEof => {
109 return Ok(None);
110 }
111 Err(e) => return Err(e),
112 }
113 }
114
115 let record = WalRecord { header, payload };
116
117 // Verify checksum.
118 if record.verify_checksum().is_err() {
119 if let Some(dwb) = &mut self.double_write
120 && let Ok(Some(recovered)) = dwb.recover_record(header.lsn)
121 {
122 tracing::info!(
123 lsn = header.lsn,
124 "recovered torn write from double-write buffer"
125 );
126 self.offset += recovered.payload.len() as u64;
127 return Ok(Some(recovered));
128 }
129 return Ok(None);
130 }
131
132 // Check if the record type is known (strip encrypted flag for lookup).
133 let logical_type = record.logical_record_type();
134 if RecordType::from_raw(logical_type).is_none() {
135 if RecordType::is_required(logical_type) {
136 return Err(WalError::UnknownRequiredRecordType {
137 record_type: header.record_type,
138 lsn: header.lsn,
139 });
140 }

Callers 2

recoverFunction · 0.45
nextMethod · 0.45

Calls 8

kindMethod · 0.80
verify_checksumMethod · 0.80
recover_recordMethod · 0.80
read_exactMethod · 0.45
validateMethod · 0.45
is_emptyMethod · 0.45
lenMethod · 0.45
logical_record_typeMethod · 0.45

Tested by

no test coverage detected