kernel/hil/log.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
// Licensed under the Apache License, Version 2.0 or the MIT License.
// SPDX-License-Identifier: Apache-2.0 OR MIT
// Copyright Tock Contributors 2022.
//! Interface for a persistent log that stores distinct log entries.
//!
//! Log entries are appended to the end of a log and read back sequentially. Log data persists
//! across device reboots.
use crate::ErrorCode;
/// An interface for reading from log storage.
pub trait LogRead<'a> {
/// Unique identifier for log entries.
type EntryID;
/// Set the client for reading from a log. The client will be called when reading operations complete.
fn set_read_client(&'a self, read_client: &'a dyn LogReadClient);
/// Read the next entry from the log. The log advances to the next entry after a successful
/// read. State does not change in the event of a failure.
fn read(
&self,
buffer: &'static mut [u8],
length: usize,
) -> Result<(), (ErrorCode, &'static mut [u8])>;
/// Returns the entry ID at the start of the log. This is the ID of the oldest remaining entry.
fn log_start(&self) -> Self::EntryID;
/// Returns the entry ID at the end of the log. This is the ID of the next entry to be
/// appended.
fn log_end(&self) -> Self::EntryID;
/// Returns the ID of the next entry to be read.
fn next_read_entry_id(&self) -> Self::EntryID;
/// Seek to the entry with the given entry ID and begin reading from there. Fails without
/// modifying the read position if the given entry ID is invalid or no longer in the log.
fn seek(&self, entry: Self::EntryID) -> Result<(), ErrorCode>;
/// Get approximate log capacity in bytes.
fn get_size(&self) -> usize;
}
/// Receive callbacks from `LogRead`.
pub trait LogReadClient {
/// Returns a buffer containing data read and the length of the number of bytes read or an error
/// code if the read failed.
fn read_done(&self, buffer: &'static mut [u8], length: usize, error: Result<(), ErrorCode>);
/// Returns whether the seek succeeded or failed.
fn seek_done(&self, error: Result<(), ErrorCode>);
}
/// An interface for writing to log storage.
pub trait LogWrite<'a> {
/// Set the client for appending from a log. The client will be called when writing operations complete.
fn set_append_client(&'a self, append_client: &'a dyn LogWriteClient);
/// Append an entry to the end of the log. May fail if the entry is too large.
fn append(
&self,
buffer: &'static mut [u8],
length: usize,
) -> Result<(), (ErrorCode, &'static mut [u8])>;
/// Sync log to storage, making all entries persistent (not including any entries that were
/// previously overwritten). There is no guarantee that any changes to the log are persistent
/// until it is synced. In the event of an error, not all pages may be synced, but the log will
/// remain in a valid state.
fn sync(&self) -> Result<(), ErrorCode>;
/// Erase the entire log. In the event of a failure, only some pages may be erased, but the log
/// will remain in a valid state.
fn erase(&self) -> Result<(), ErrorCode>;
}
/// Receive callbacks from `LogWrite`.
pub trait LogWriteClient {
/// Returns the original buffer that contained the data to write, the number of bytes written,
/// and whether any old entries in the log were lost (due to a circular log being filled up).
fn append_done(
&self,
buffer: &'static mut [u8],
length: usize,
records_lost: bool,
error: Result<(), ErrorCode>,
);
/// Returns whether or not all pages were correctly synced, making all changes persistent.
fn sync_done(&self, error: Result<(), ErrorCode>);
/// Returns whether or not all pages of the log were erased.
fn erase_done(&self, error: Result<(), ErrorCode>);
}