X-Git-Url: http://git.code-monkey.de/?a=blobdiff_plain;f=src%2Fcommon%2Flogger.rs;h=8ca0ed4da62c36a9130cedb90a3a377b44e74907;hb=4e82712727981c944f56d4ada62dc54ad8542d94;hp=d958193c281d97205b694bd333a5adee51998ec5;hpb=8f0161e8492d090b09782c13b43ef71201787186;p=gps-watch.git diff --git a/src/common/logger.rs b/src/common/logger.rs index d958193..8ca0ed4 100644 --- a/src/common/logger.rs +++ b/src/common/logger.rs @@ -25,12 +25,20 @@ use gps::TimeAndPos; use storage::Storage; use varint; use systick::elapsed_ms; +use buffer::Buffer; +use yencode::Yencode; +use fmt::*; pub const MEMORY_SIZE: usize = 2 << 20; const SECTOR_SIZE: usize = 4 << 10; const NUM_SECTORS: usize = MEMORY_SIZE / SECTOR_SIZE; +#[derive(Clone, Copy, PartialEq, Debug)] +pub enum Error { + NoSuchRecording, +} + enum SectorFlag { InUse = 1 << 0, DataRecord = 1 << 1, @@ -72,6 +80,10 @@ impl SectorHeader { (self.flags & mask) == value } + + fn belongs_to(&self, recording_id: u16) -> bool { + self.is_in_use() && self.recording_id == recording_id + } } #[derive(Clone, Copy)] @@ -92,7 +104,7 @@ impl InFlight { } pub struct Logger<'a> { - storage: &'a mut dyn Storage, + pub storage: &'a mut dyn Storage, recording_id: u16, // Zero is considered invalid. @@ -329,7 +341,7 @@ impl<'a> Logger<'a> { fn read_sector_header(&mut self, sector_index: usize) { let address = sector_index * SECTOR_SIZE; - let mut chunk = [0u8; 4]; + let mut chunk = [0u8; 8]; self.storage.read(address, &mut chunk); @@ -418,10 +430,18 @@ impl<'a> Logger<'a> { let this_sector = self.first_sector + self.sectors_written; - self.storage.write(this_sector as usize * SECTOR_SIZE, - &self.write_buffer); + if self.storage.write(this_sector as usize * SECTOR_SIZE, + &self.write_buffer).is_err() { + // XXX + } + + self.sectors_written += 1; + + for i in 0..self.sectors_written { + self.read_sector_header((self.first_sector + i) as usize); + } - self.sectors_written + 1 + self.sectors_written } fn sector_header_iter(&self) -> SectorHeaderIter { @@ -535,8 +555,10 @@ impl<'a> Logger<'a> { // our buffer with 0xff, so we don't need to do anything here. let this_sector = self.first_sector + self.sectors_written; - self.storage.write(this_sector as usize * SECTOR_SIZE, - &self.write_buffer); + if self.storage.write(this_sector as usize * SECTOR_SIZE, + &self.write_buffer).is_err() { + // XXX + } self.sectors_written += 1; @@ -551,4 +573,76 @@ impl<'a> Logger<'a> { self.write_buffer_offset += num_bytes_written; } + + /// + /// Check whether or not recording @p recording_id exists. + pub fn has_recording(&mut self, recording_id: u16) -> bool { + if recording_id == 0 { + return false; + } + + self.sector_header_iter().find(|&index| { + let sector_header = &self.sector_header[index as usize]; + + sector_header.recording_id == recording_id && + sector_header.starts_recording() + }).is_some() + } + + /// + /// Retrieve recording @p recording_id and + /// write it to @p tx_buf in yencoded form. + pub fn get_recording(&mut self, recording_id: u16, + tx_buf: &mut Buffer) -> Result<(), Error> { + if recording_id == 0 { + return Err(Error::NoSuchRecording); + } + + if let Some(found_index) = self.sector_header_iter().find(|&index| { + let sector_header = &self.sector_header[index as usize]; + + sector_header.recording_id == recording_id && + sector_header.starts_recording() + }) { + let mut filename = [b' '; 29]; + + filename[0..].copy_from_slice(b"gps-watch-recording-XXXXX.bin"); + + fmt_u32_pad(&mut filename[20..], recording_id as u32, 5, b'0'); + + let mut yenc = Yencode::new(tx_buf); + + yenc.start(&filename); + + let format_version = 1u8; + yenc.data(&[format_version]); + + let mut next_sector = found_index as usize; + + for _ in 0..NUM_SECTORS { + let address = next_sector * SECTOR_SIZE; + let mut buf = [0u8; SECTOR_SIZE]; + + self.storage.read(address, &mut buf); + + // Skip flags and recording ID. + yenc.data(&buf[4..]); + + next_sector += 1; + next_sector &= NUM_SECTORS - 1; + + if !self.sector_header[next_sector].belongs_to(recording_id) { + break; + } + } + + yenc.finish(); + + tx_buf.flush(); + + Ok(()) + } else { + Err(Error::NoSuchRecording) + } + } }