added untested code for disk persistence
This commit is contained in:
parent
e13fb05dbb
commit
3c2137f224
@ -1,3 +1,4 @@
|
|||||||
|
mod persistence;
|
||||||
mod datastore;
|
mod datastore;
|
||||||
use crate::grpc::challenge::NodeUpdate;
|
use crate::grpc::challenge::NodeUpdate;
|
||||||
use tokio::sync::broadcast::Sender;
|
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