Skip to content

Commit 6c52b10

Browse files
committed
feat(store): store load, create and save logic
1 parent e895731 commit 6c52b10

File tree

4 files changed

+131
-9
lines changed

4 files changed

+131
-9
lines changed

src/errors.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,20 @@
1+
use thiserror::Error;
2+
13
/// Could not convert from [CheckFlag](crate::records::CheckFlag) to [CheckType](crate::records::CheckType).
24
pub struct CheckFlagTypeConversionError;
5+
6+
#[derive(Error, Debug)]
7+
pub enum StoreError {
8+
#[error("The store does not exist")]
9+
DoesNotExist,
10+
#[error("IO Error")]
11+
Io {
12+
#[from]
13+
source: std::io::Error,
14+
},
15+
#[error("Could not Serialize or Deserialize")]
16+
DeSerialize {
17+
#[from]
18+
source: bincode::Error,
19+
},
20+
}

src/lib.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
1-
/// The filename of the database, in [DB_PATH]
2-
pub const DB_NAME: &str = "netpulse.store";
3-
/// Path to the database of netpulse (combine with [DB_NAME])
4-
pub const DB_PATH: &str = "/var/lib/netpulse/";
51
/// How long to wait until considering a connection as timed out, in milliseconds
62
pub const TIMEOUT_MS: u16 = 30_000;
73

84
pub mod errors;
95
pub mod records;
6+
pub mod store;

src/records.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,6 @@ use serde::{Deserialize, Serialize};
55

66
use crate::errors::CheckFlagTypeConversionError;
77

8-
#[derive(Debug, PartialEq, Eq, Hash, Deserialize, Serialize, Default)]
9-
pub struct Store {
10-
checks: Vec<Check>,
11-
}
12-
138
flags! {
149
#[derive(Hash, Deserialize, Serialize)]
1510
pub enum CheckFlag: u16 {
@@ -21,6 +16,11 @@ flags! {
2116
/// Failure because the destination is unreachable
2217
Unreachable = 0b0000_0000_0000_0100,
2318

19+
/// The Check used IPv4
20+
IPv4 = 0b0000_0001_0000_0000,
21+
/// The Check used IPv6
22+
IPv6 = 0b0000_0010_0000_0000,
23+
2424
/// The Check used HTTP/HTTPS
2525
TypeHTTP = 0b0010_0000_0000_0000,
2626
/// The Check used Ping/ICMP

src/store.rs

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
use std::fs;
2+
use std::io::{BufReader, ErrorKind, Write};
3+
use std::path::PathBuf;
4+
5+
use serde::{Deserialize, Serialize};
6+
7+
use crate::errors::StoreError;
8+
use crate::records::Check;
9+
10+
/// The filename of the database, in [DB_PATH]
11+
pub const DB_NAME: &str = "netpulse.store";
12+
/// Path to the database of netpulse (combine with [DB_NAME])
13+
pub const DB_PATH: &str = "/var/lib/netpulse";
14+
15+
#[derive(Debug, PartialEq, Eq, Hash, Deserialize, Serialize)]
16+
pub struct Store {
17+
checks: Vec<Check>,
18+
}
19+
20+
impl Store {
21+
pub fn path() -> PathBuf {
22+
PathBuf::from(format!("{DB_PATH}/{DB_NAME}"))
23+
}
24+
25+
fn new() -> Self {
26+
Self { checks: Vec::new() }
27+
}
28+
29+
fn create() -> Result<Self, StoreError> {
30+
fs::create_dir_all(
31+
Self::path()
32+
.parent()
33+
.expect("the store path has no parent directory"),
34+
)?;
35+
36+
let mut file = match fs::File::options()
37+
.read(false)
38+
.write(true)
39+
.append(false)
40+
.create_new(true)
41+
.open(Self::path())
42+
{
43+
Ok(file) => file,
44+
Err(err) => return Err(err.into()),
45+
};
46+
47+
let store = Store::new();
48+
49+
file.write_all(&bincode::serialize(&store)?)?;
50+
file.flush()?;
51+
Ok(store)
52+
}
53+
54+
pub fn load_or_create() -> Result<Self, StoreError> {
55+
match Self::load() {
56+
Ok(store) => Ok(store),
57+
Err(err) => {
58+
if matches!(err, StoreError::DoesNotExist) {
59+
Self::create()
60+
} else {
61+
eprintln!("Error while trying to load the store: {err:#}");
62+
Err(err)
63+
}
64+
}
65+
}
66+
}
67+
68+
pub fn load() -> Result<Self, StoreError> {
69+
let file = match fs::File::options()
70+
.read(true)
71+
.write(false)
72+
.open(Self::path())
73+
{
74+
Ok(file) => file,
75+
Err(err) => match err.kind() {
76+
ErrorKind::NotFound => return Err(StoreError::DoesNotExist),
77+
_ => return Err(err.into()),
78+
},
79+
};
80+
81+
let reader = BufReader::new(file);
82+
83+
Ok(bincode::deserialize_from(reader)?)
84+
}
85+
86+
pub fn save(&self) -> Result<(), StoreError> {
87+
let mut file = match fs::File::options()
88+
.read(false)
89+
.write(true)
90+
.append(false)
91+
.create_new(false)
92+
.truncate(true)
93+
.create(false)
94+
.open(Self::path())
95+
{
96+
Ok(file) => file,
97+
Err(err) => match err.kind() {
98+
ErrorKind::NotFound => return Err(StoreError::DoesNotExist),
99+
_ => return Err(err.into()),
100+
},
101+
};
102+
103+
file.write_all(&bincode::serialize(&self)?)?;
104+
file.flush()?;
105+
Ok(())
106+
}
107+
}

0 commit comments

Comments
 (0)