Skip to content

Commit

Permalink
Switch persister to a fixed set of keys
Browse files Browse the repository at this point in the history
  • Loading branch information
ivmarkov committed Oct 6, 2024
1 parent 2243c0f commit 34b408d
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 22 deletions.
77 changes: 56 additions & 21 deletions src/persist.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use core::fmt::{self, Display};

use embassy_futures::select::select;
use embassy_sync::blocking_mutex::raw::NoopRawMutex;

Expand All @@ -19,6 +21,8 @@ pub use file::DirKvBlobStore;
/// - `()` - which is used with the `Eth` network
/// - `&NetworkContext` - which is used with the `WirelessBle` network.
pub trait NetworkPersist: Sealed {
const KEY: Key;

/// Reset all networks, removing all stored data from the memory
async fn reset(&mut self) -> Result<(), Error>;

Expand Down Expand Up @@ -47,6 +51,8 @@ pub trait NetworkPersist: Sealed {
/// Used when the Matter stack is configured for Ethernet, as in that case
/// there is no network state that needs to be saved
impl NetworkPersist for () {
const KEY: Key = Key::EthNetworks; // Does not matter really as Ethernet networks do not have a persistence story

async fn reset(&mut self) -> Result<(), Error> {
Ok(())
}
Expand Down Expand Up @@ -150,8 +156,10 @@ where
pub async fn reset(&mut self) -> Result<(), Error> {
// TODO: Reset fabrics

self.store.remove("fabrics").await?;
self.store.remove("networks").await?;
self.store.remove(Key::Fabrics).await?;
self.store.remove(Key::EthNetworks).await?;
self.store.remove(Key::WifiNetworks).await?;
self.store.remove(Key::ThreadNetworks).await?;

self.networks.reset().await?;

Expand All @@ -163,11 +171,11 @@ where
let mut buf = self.buf.get().await.unwrap();
buf.resize_default(KV_BLOB_BUF_SIZE).unwrap();

if let Some(data) = self.store.load("fabrics", &mut buf).await? {
if let Some(data) = self.store.load(Key::Fabrics, &mut buf).await? {
self.matter.load_fabrics(data)?;
}

if let Some(data) = self.store.load("networks", &mut buf).await? {
if let Some(data) = self.store.load(C::KEY, &mut buf).await? {
self.networks.load(data).await?;
}

Expand All @@ -187,12 +195,12 @@ where

if self.matter.fabrics_changed() {
if let Some(data) = self.matter.store_fabrics(&mut buf)? {
self.store.store("fabrics", data).await?;
self.store.store(Key::Fabrics, data).await?;
}
}

if let Some(data) = self.networks.store(&mut buf).await? {
self.store.store("networks", data).await?;
self.store.store(C::KEY, data).await?;
}
}
}
Expand All @@ -216,26 +224,53 @@ where
}
}

/// The keys the `KvBlobStore` trait uses to store the BLOBs.
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
#[repr(u8)]
pub enum Key {
Fabrics = 0,
EthNetworks = 1,
WifiNetworks = 2,
ThreadNetworks = 3,
}

impl AsRef<str> for Key {
fn as_ref(&self) -> &str {
match self {
Key::Fabrics => "fabrics",
Key::EthNetworks => "eth-networks",
Key::WifiNetworks => "wifi-networks",
Key::ThreadNetworks => "thread-networks",
}
}
}

impl Display for Key {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(self.as_ref())
}
}

/// A trait representing a key-value BLOB storage.
pub trait KvBlobStore {
async fn load<'a>(&mut self, key: &str, buf: &'a mut [u8]) -> Result<Option<&'a [u8]>, Error>;
async fn store(&mut self, key: &str, value: &[u8]) -> Result<(), Error>;
async fn remove(&mut self, key: &str) -> Result<(), Error>;
async fn load<'a>(&mut self, key: Key, buf: &'a mut [u8]) -> Result<Option<&'a [u8]>, Error>;
async fn store(&mut self, key: Key, value: &[u8]) -> Result<(), Error>;
async fn remove(&mut self, key: Key) -> Result<(), Error>;
}

impl<T> KvBlobStore for &mut T
where
T: KvBlobStore,
{
async fn load<'a>(&mut self, key: &str, buf: &'a mut [u8]) -> Result<Option<&'a [u8]>, Error> {
async fn load<'a>(&mut self, key: Key, buf: &'a mut [u8]) -> Result<Option<&'a [u8]>, Error> {
T::load(self, key, buf).await
}

async fn store(&mut self, key: &str, value: &[u8]) -> Result<(), Error> {
async fn store(&mut self, key: Key, value: &[u8]) -> Result<(), Error> {
T::store(self, key, value).await
}

async fn remove(&mut self, key: &str) -> Result<(), Error> {
async fn remove(&mut self, key: Key) -> Result<(), Error> {
T::remove(self, key).await
}
}
Expand All @@ -262,7 +297,7 @@ where
mod file {
use rs_matter::error::Error;

use super::KvBlobStore;
use super::{Key, KvBlobStore};

extern crate std;

Expand All @@ -282,7 +317,7 @@ mod file {
}

/// Load a BLOB with the specified key from the directory.
pub fn load<'b>(&self, key: &str, buf: &'b mut [u8]) -> Result<Option<&'b [u8]>, Error> {
pub fn load<'b>(&self, key: Key, buf: &'b mut [u8]) -> Result<Option<&'b [u8]>, Error> {
use log::info;
use std::io::Read;

Expand Down Expand Up @@ -317,7 +352,7 @@ mod file {
}

/// Store a BLOB with the specified key in the directory.
fn store(&self, key: &str, data: &[u8]) -> Result<(), Error> {
fn store(&self, key: Key, data: &[u8]) -> Result<(), Error> {
use log::info;
use std::io::Write;

Expand All @@ -336,7 +371,7 @@ mod file {

/// Remove a BLOB with the specified key from the directory.
/// If the BLOB does not exist, this method does nothing.
fn remove(&self, key: &str) -> Result<(), Error> {
fn remove(&self, key: Key) -> Result<(), Error> {
use log::info;

let path = self.key_path(key);
Expand All @@ -348,8 +383,8 @@ mod file {
Ok(())
}

fn key_path(&self, key: &str) -> std::path::PathBuf {
self.0.join(key)
fn key_path(&self, key: Key) -> std::path::PathBuf {
self.0.join(key.as_ref())
}
}

Expand All @@ -362,17 +397,17 @@ mod file {
impl KvBlobStore for DirKvBlobStore {
async fn load<'a>(
&mut self,
key: &str,
key: Key,
buf: &'a mut [u8],
) -> Result<Option<&'a [u8]>, Error> {
DirKvBlobStore::load(self, key, buf)
}

async fn store(&mut self, key: &str, value: &[u8]) -> Result<(), Error> {
async fn store(&mut self, key: Key, value: &[u8]) -> Result<(), Error> {
DirKvBlobStore::store(self, key, value)
}

async fn remove(&mut self, key: &str) -> Result<(), Error> {
async fn remove(&mut self, key: Key) -> Result<(), Error> {
DirKvBlobStore::remove(self, key)
}
}
Expand Down
8 changes: 7 additions & 1 deletion src/wireless/store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use rs_matter::utils::storage::WriteBuf;
use rs_matter::utils::sync::blocking::Mutex;
use rs_matter::utils::sync::Notification;

use crate::persist::NetworkPersist;
use crate::persist::{Key, NetworkPersist};
use crate::private::Sealed;

use super::proxy::ControllerProxy;
Expand Down Expand Up @@ -290,6 +290,12 @@ where
T: WirelessData,
T::NetworkCredentials: Clone + for<'a> FromTLV<'a> + ToTLV,
{
const KEY: crate::persist::Key = if T::WIFI {
Key::WifiNetworks
} else {
Key::ThreadNetworks
};

async fn reset(&mut self) -> Result<(), Error> {
NetworkContext::reset(self);

Expand Down

0 comments on commit 34b408d

Please sign in to comment.