X-Git-Url: http://git.code-monkey.de/?p=gps-watch.git;a=blobdiff_plain;f=src%2Fcommon%2Flogger.rs;h=824e26ca10b2025e6cd906804a8109897922354d;hp=be0632792af1177fab3c40993f1228486cd5ce61;hb=946cce9fdf4094ca5b3e2dd764a44e68cd3bf3a6;hpb=9bc6fc2996255514e0d49e3da0655e2f93f14d8c diff --git a/src/common/logger.rs b/src/common/logger.rs index be06327..824e26c 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. @@ -323,19 +335,23 @@ impl<'a> Logger<'a> { // Reading the directory entries one by one means // we won't need an as large buffer on the stack. for i in 0..NUM_SECTORS { - let address = i * SECTOR_SIZE; - let mut chunk = [0u8; 4]; + self.read_sector_header(i); + } + } - self.storage.read(address, &mut chunk); + fn read_sector_header(&mut self, sector_index: usize) { + let address = sector_index * SECTOR_SIZE; + let mut chunk = [0u8; 4]; - let sector_header_ptr: *mut SectorHeader = - &mut self.sector_header[i]; + self.storage.read(address, &mut chunk); - unsafe { - core::ptr::copy(chunk.as_ptr(), - sector_header_ptr as *mut u8, - chunk.len()); - } + let sector_header_ptr: *mut SectorHeader = + &mut self.sector_header[sector_index]; + + unsafe { + core::ptr::copy(chunk.as_ptr(), + sector_header_ptr as *mut u8, + chunk.len()); } } @@ -414,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 + self.sectors_written += 1; + + for i in 0..self.sectors_written { + self.read_sector_header((self.first_sector + i) as usize); + } + + self.sectors_written } fn sector_header_iter(&self) -> SectorHeaderIter { @@ -531,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; @@ -547,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) + } + } }