added untested code for disk persistence
This commit is contained in:
parent
e13fb05dbb
commit
3c2137f224
@ -1,3 +1,4 @@
|
||||
mod persistence;
|
||||
mod datastore;
|
||||
use crate::grpc::challenge::NodeUpdate;
|
||||
use tokio::sync::broadcast::Sender;
|
||||
|
108
src/persistence.rs
Normal file
108
src/persistence.rs
Normal file
@ -0,0 +1,108 @@
|
||||
#![allow(dead_code)]
|
||||
use ed25519_dalek::SigningKey;
|
||||
use ed25519_dalek::KEYPAIR_LENGTH;
|
||||
use std::net::AddrParseError;
|
||||
use std::net::Ipv4Addr;
|
||||
use std::time::{Duration, SystemTime, UNIX_EPOCH};
|
||||
use tokio::fs::File;
|
||||
use tokio::io::{AsyncReadExt, AsyncSeekExt, AsyncWriteExt, SeekFrom};
|
||||
use tokio::sync::Mutex;
|
||||
|
||||
const DATA_SIZE: usize = 78;
|
||||
|
||||
enum Error {
|
||||
CorruptedIP,
|
||||
}
|
||||
|
||||
impl From<AddrParseError> for Error {
|
||||
fn from(_: AddrParseError) -> Self {
|
||||
Error::CorruptedIP
|
||||
}
|
||||
}
|
||||
|
||||
struct Node {
|
||||
ip: Ipv4Addr,
|
||||
keypair: SigningKey,
|
||||
joined_at: SystemTime,
|
||||
}
|
||||
|
||||
impl TryFrom<(&str, SigningKey, SystemTime)> for Node {
|
||||
type Error = Error;
|
||||
fn try_from(value: (&str, SigningKey, SystemTime)) -> Result<Self, Self::Error> {
|
||||
Ok(Self {
|
||||
ip: value.0.parse()?,
|
||||
keypair: value.1,
|
||||
joined_at: value.2,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Node {
|
||||
fn ip_as_string(&self) -> String {
|
||||
self.ip.to_string()
|
||||
}
|
||||
|
||||
fn signing_key(&self) -> SigningKey {
|
||||
self.keypair.clone()
|
||||
}
|
||||
|
||||
fn to_bytes(self) -> [u8; DATA_SIZE] {
|
||||
let mut result = [0; DATA_SIZE];
|
||||
result[0..4].copy_from_slice(&self.ip.octets());
|
||||
result[4..68].copy_from_slice(&self.keypair.to_keypair_bytes());
|
||||
result[69..DATA_SIZE].copy_from_slice(
|
||||
&self
|
||||
.joined_at
|
||||
.duration_since(UNIX_EPOCH)
|
||||
.unwrap()
|
||||
.as_secs()
|
||||
.to_le_bytes(),
|
||||
);
|
||||
result
|
||||
}
|
||||
|
||||
fn from_bytes(bytes: [u8; DATA_SIZE]) -> Self {
|
||||
let ip: [u8; 4] = bytes[0..4].try_into().unwrap();
|
||||
let ip: Ipv4Addr = ip.into();
|
||||
let keypair: [u8; KEYPAIR_LENGTH] = bytes[4..68].try_into().unwrap();
|
||||
let keypair: SigningKey = SigningKey::from_keypair_bytes(&keypair).unwrap();
|
||||
let joined_at: [u8; 8] = bytes[69..DATA_SIZE].try_into().unwrap();
|
||||
let joined_at: u64 = u64::from_le_bytes(joined_at);
|
||||
let joined_at = SystemTime::UNIX_EPOCH + Duration::from_secs(joined_at);
|
||||
Self {
|
||||
ip,
|
||||
keypair,
|
||||
joined_at,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct FileManager {
|
||||
file: Mutex<File>,
|
||||
}
|
||||
|
||||
impl FileManager {
|
||||
async fn init(path: &str) -> std::io::Result<Self> {
|
||||
let file = File::open(path).await?;
|
||||
Ok(Self {
|
||||
file: Mutex::new(file),
|
||||
})
|
||||
}
|
||||
|
||||
async fn append_node(&self, node: Node) -> std::io::Result<()> {
|
||||
let mut file = self.file.lock().await;
|
||||
file.seek(SeekFrom::End(0)).await?;
|
||||
file.write_all(&node.to_bytes()).await?;
|
||||
file.flush().await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn get_node_by_id(&self, id: u64) -> std::io::Result<Node> {
|
||||
let mut file = self.file.lock().await;
|
||||
file.seek(SeekFrom::Start(id.wrapping_mul(DATA_SIZE.try_into().unwrap_or(0))))
|
||||
.await?;
|
||||
let mut node_bytes = [0; DATA_SIZE];
|
||||
file.read_exact(&mut node_bytes).await?;
|
||||
Ok(Node::from_bytes(node_bytes))
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user