Read the payload for a header that was just returned by `next_header()`. Must be called exactly once after `next_header()` returns `Some`, and before calling `next_header()` again (unless `skip_payload()` was called instead).
(&mut self, header: &RecordHeader)
| 101 | /// and before calling `next_header()` again (unless `skip_payload()` |
| 102 | /// was called instead). |
| 103 | pub fn read_payload(&mut self, header: &RecordHeader) -> Result<Vec<u8>> { |
| 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 Err(WalError::Io(std::io::Error::new( |
| 110 | std::io::ErrorKind::UnexpectedEof, |
| 111 | "torn write: incomplete payload", |
| 112 | ))); |
| 113 | } |
| 114 | Err(e) => return Err(e), |
| 115 | } |
| 116 | } |
| 117 | |
| 118 | // Verify checksum. |
| 119 | let record = WalRecord { |
| 120 | header: *header, |
| 121 | payload: payload.clone(), |
| 122 | }; |
| 123 | if record.verify_checksum().is_err() { |
| 124 | // Try double-write buffer recovery. |
| 125 | if let Some(dwb) = &mut self.double_write |
| 126 | && let Ok(Some(recovered)) = dwb.recover_record(header.lsn) |
| 127 | { |
| 128 | return Ok(recovered.payload); |
| 129 | } |
| 130 | return Err(WalError::Io(std::io::Error::new( |
| 131 | std::io::ErrorKind::InvalidData, |
| 132 | "checksum mismatch", |
| 133 | ))); |
| 134 | } |
| 135 | |
| 136 | Ok(payload) |
| 137 | } |
| 138 | |
| 139 | /// Read the payload and return a full WalRecord. |
| 140 | pub fn read_record(&mut self, header: &RecordHeader) -> Result<WalRecord> { |