Read all entries from a specific WAL file
(&self, file_number: u64)
| 652 | |
| 653 | /// Read all entries from a specific WAL file |
| 654 | pub fn read_wal_file(&self, file_number: u64) -> Result<Vec<WALEntry>, WALError> { |
| 655 | let filename = format!("wal_{:06}.log", file_number); |
| 656 | let file_path = self.wal_dir.join(&filename); |
| 657 | |
| 658 | if !file_path.exists() { |
| 659 | return Err(WALError::IOError(format!( |
| 660 | "WAL file not found: {}", |
| 661 | file_path.display() |
| 662 | ))); |
| 663 | } |
| 664 | |
| 665 | let mut file = File::open(&file_path) |
| 666 | .map_err(|e| WALError::IOError(format!("Failed to open WAL file: {}", e)))?; |
| 667 | |
| 668 | // Skip file header (64 bytes) |
| 669 | file.seek(SeekFrom::Start(64)) |
| 670 | .map_err(|e| WALError::IOError(format!("Failed to seek in WAL file: {}", e)))?; |
| 671 | |
| 672 | let mut reader = BufReader::new(file); |
| 673 | let mut entries = Vec::new(); |
| 674 | let mut buffer = Vec::new(); |
| 675 | |
| 676 | // Read entire file |
| 677 | reader |
| 678 | .read_to_end(&mut buffer) |
| 679 | .map_err(|e| WALError::IOError(format!("Failed to read WAL file: {}", e)))?; |
| 680 | |
| 681 | let mut offset = 0; |
| 682 | while offset < buffer.len() { |
| 683 | // Try to find next entry by looking for magic number |
| 684 | if offset + 4 <= buffer.len() { |
| 685 | let magic = u32::from_le_bytes([ |
| 686 | buffer[offset], |
| 687 | buffer[offset + 1], |
| 688 | buffer[offset + 2], |
| 689 | buffer[offset + 3], |
| 690 | ]); |
| 691 | |
| 692 | if magic == WAL_MAGIC { |
| 693 | // Read the minimum size to determine actual entry size |
| 694 | if offset + 50 <= buffer.len() { |
| 695 | // Try to deserialize starting from this offset |
| 696 | // The deserializer should handle determining the actual size |
| 697 | match WALEntry::deserialize(&buffer[offset..]) { |
| 698 | Ok(entry) => { |
| 699 | // Calculate the actual size of this entry |
| 700 | let entry_bytes = entry.serialize(); |
| 701 | let entry_size = entry_bytes.len(); |
| 702 | |
| 703 | entries.push(entry); |
| 704 | // Move offset past this entry |
| 705 | offset += entry_size; |
| 706 | continue; |
| 707 | } |
| 708 | Err(_) => { |
| 709 | // Skip this corrupted entry |
| 710 | offset += 1; |
| 711 | } |
no test coverage detected