Append a record to the in-memory buffer. Returns the assigned LSN. The record is NOT durable until `submit_and_sync()` is called. `database_id` is stored in header bytes 34-41. Pass `0` for the default database (backward-compatible with pre-existing records).
(
&mut self,
record_type: u32,
tenant_id: u64,
vshard_id: u32,
database_id: u64,
payload: &[u8],
)
| 146 | /// `database_id` is stored in header bytes 34-41. Pass `0` for the |
| 147 | /// default database (backward-compatible with pre-existing records). |
| 148 | pub fn append( |
| 149 | &mut self, |
| 150 | record_type: u32, |
| 151 | tenant_id: u64, |
| 152 | vshard_id: u32, |
| 153 | database_id: u64, |
| 154 | payload: &[u8], |
| 155 | ) -> Result<u64> { |
| 156 | if self.sealed { |
| 157 | return Err(WalError::Sealed); |
| 158 | } |
| 159 | |
| 160 | let lsn = self.next_lsn.fetch_add(1, Ordering::Relaxed); |
| 161 | let preamble_bytes = self.segment_preamble.as_ref().map(|p| p.to_bytes()); |
| 162 | let record = WalRecord::new( |
| 163 | record_type, |
| 164 | lsn, |
| 165 | tenant_id, |
| 166 | vshard_id, |
| 167 | database_id, |
| 168 | payload.to_vec(), |
| 169 | self.encryption_key.as_ref(), |
| 170 | preamble_bytes.as_ref(), |
| 171 | )?; |
| 172 | |
| 173 | let header_bytes = record.header.to_bytes(); |
| 174 | let total_size = HEADER_SIZE + record.payload.len(); |
| 175 | |
| 176 | if self.buffer.remaining() < total_size { |
| 177 | self.submit_and_wait_write()?; |
| 178 | } |
| 179 | |
| 180 | if total_size > self.buffer.capacity() { |
| 181 | return Err(WalError::PayloadTooLarge { |
| 182 | size: record.payload.len(), |
| 183 | max: self.buffer.capacity() - HEADER_SIZE, |
| 184 | }); |
| 185 | } |
| 186 | |
| 187 | self.buffer.write(&header_bytes); |
| 188 | self.buffer.write(&record.payload); |
| 189 | |
| 190 | Ok(lsn) |
| 191 | } |
| 192 | |
| 193 | /// Submit the buffered data via io_uring write + fsync, and wait for completion. |
| 194 | /// |