Skip to content

Commit

Permalink
chore: use tokio::fs
Browse files Browse the repository at this point in the history
  • Loading branch information
joshuef authored and oetyng committed Jul 5, 2021
1 parent 4dc3aa3 commit 11c353a
Show file tree
Hide file tree
Showing 12 changed files with 134 additions and 119 deletions.
15 changes: 8 additions & 7 deletions examples/config_handling.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@

use anyhow::Result;
use safe_network::node::Config;
use std::{fs::remove_file, io};
use structopt::StructOpt;
use tokio::{fs::remove_file, io};

// This example is to demonstrate how the node configuration is constructed
// The node will attempt to read a cached config file from disk
Expand All @@ -18,7 +18,8 @@ use structopt::StructOpt;
// Note: This is essentially a test, but, when using test filtering, StructOpt
// tries to parse the filter as an argument passed resulting in a `UnmatchedArgument` error.

fn main() -> Result<()> {
#[tokio::main]
async fn main() -> Result<()> {
// Create some config and write it to disk
let file_config = Config::default();

Expand All @@ -30,12 +31,12 @@ fn main() -> Result<()> {
// );
// file_config.network_config.local_port = Some(0);
// file_config.network_config.external_port = Some(12345);
file_config.write_to_disk()?;
file_config.write_to_disk().await?;

// This should load the config from disk and
// use the command line arguments to overwrite the config
// with any provided arguments
let config = Config::new()?;
let config = Config::new().await?;

let command_line_args = Config::from_args();

Expand Down Expand Up @@ -194,18 +195,18 @@ fn main() -> Result<()> {
)
}

clear_disk_config()?;
clear_disk_config().await?;

Ok(())
}

fn clear_disk_config() -> io::Result<()> {
async fn clear_disk_config() -> io::Result<()> {
let mut path = dirs_next::home_dir()
.ok_or_else(|| io::Error::new(io::ErrorKind::NotFound, "Home directory not found"))?;

path.push(".safe");
path.push("node");
path.push("node.config");

remove_file(path)
remove_file(path).await
}
2 changes: 1 addition & 1 deletion src/client/client_api/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ impl Client {
}
};

let mut qp2p_config = Config::new(config_file_path, bootstrap_config).qp2p;
let mut qp2p_config = Config::new(config_file_path, bootstrap_config).await.qp2p;
// We use feature `no-igd` so this will use the echo service only
qp2p_config.forward_port = true;

Expand Down
65 changes: 26 additions & 39 deletions src/client/config_handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,9 @@
use crate::client::Error;
use qp2p::Config as QuicP2pConfig;
use serde::{Deserialize, Serialize};
use std::{
collections::HashSet,
fs::File,
io::{self, BufReader},
net::SocketAddr,
path::Path,
};
use std::{collections::HashSet, net::SocketAddr, path::Path};
use tokio::fs::{self};
use tokio::io::{self};
use tracing::{debug, warn};

/// Configuration for sn_client.
Expand All @@ -27,15 +23,15 @@ pub struct Config {

impl Config {
/// Returns a new `Config` instance. Tries to read quic-p2p config from file.
pub fn new(
pub async fn new(
config_file_path: Option<&Path>,
bootstrap_config: Option<HashSet<SocketAddr>>,
) -> Self {
// If a config file path was provided we try to read it,
// otherwise we use default qp2p config.
let mut qp2p = match &config_file_path {
None => QuicP2pConfig::default(),
Some(path) => match read_config_file(path) {
Some(path) => match read_config_file(path).await {
Err(Error::IoError(ref err)) if err.kind() == io::ErrorKind::NotFound => {
QuicP2pConfig {
bootstrap_cache_dir: path.parent().map(|p| p.display().to_string()),
Expand All @@ -55,29 +51,18 @@ impl Config {
}
}

fn read_config_file(filepath: &Path) -> Result<QuicP2pConfig, Error> {
match File::open(filepath) {
Ok(file) => {
debug!("Reading config file '{}' ...", filepath.display());
let reader = BufReader::new(file);
serde_json::from_reader(reader).map_err(|err| {
warn!(
"Could not parse content of config file '{}': {}",
filepath.display(),
err
);
err.into()
})
}
Err(err) => {
warn!(
"Failed to open config file from '{}': {}",
filepath.display(),
err
);
Err(err.into())
}
}
async fn read_config_file(filepath: &Path) -> Result<QuicP2pConfig, Error> {
debug!("Reading config file '{}' ...", filepath.display());
let contents = fs::read(filepath).await?;

serde_json::from_slice(&contents).map_err(|err| {
warn!(
"Could not parse content of config file '{}': {}",
filepath.display(),
err
);
err.into()
})
}

#[cfg(test)]
Expand All @@ -86,17 +71,19 @@ mod tests {
use crate::client::utils::test_utils::init_logger;
use anyhow::Result;
use rand::{distributions::Alphanumeric, thread_rng, Rng};
use std::{env::temp_dir, fs::create_dir_all};
use std::env::temp_dir;
use std::fs::File;
use tokio::fs::create_dir_all;

// 1. Verify that `Config::new()` generates the correct default config
// when the file is not found. The default config shall have the provided
// config path in the `boostrap_cache_dir` field.
// 2. Write the default config file to temp directory.
// 3. Assert that `Config::new()` reads the default config written to disk.
// 4. Verify that `Config::new()` returns the correct default config when no path is provided.
#[test]
#[tokio::test]
#[ignore]
fn custom_config_path() -> Result<()> {
async fn custom_config_path() -> Result<()> {
init_logger();

let path = temp_dir();
Expand All @@ -105,7 +92,7 @@ mod tests {

// In the absence of a config file, the config handler
// should initialize bootstrap_cache_dir only
let config = Config::new(Some(&config_filepath), None);
let config = Config::new(Some(&config_filepath), None).await;
// convert to string for assert
let mut str_path = path
.to_str()
Expand All @@ -124,17 +111,17 @@ mod tests {
};
assert_eq!(config, expected_config);

create_dir_all(path)?;
create_dir_all(path).await?;
let mut file = File::create(&config_filepath)?;

let config_on_disk = Config::default();
serde_json::to_writer_pretty(&mut file, &config_on_disk)?;
file.sync_all()?;

let read_cfg = Config::new(Some(&config_filepath), None);
let read_cfg = Config::new(Some(&config_filepath), None).await;
assert_eq!(config_on_disk, read_cfg);

let default_cfg = Config::new(None, None);
let default_cfg = Config::new(None, None).await;
assert_eq!(Config::default(), default_cfg);

Ok(())
Expand Down
18 changes: 11 additions & 7 deletions src/dbs/event_store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,13 @@
use super::{new_auto_dump_db, Error, Result, ToDbKey};
use pickledb::PickleDb;
use serde::{de::DeserializeOwned, Serialize};

use std::{
fmt::Debug,
marker::PhantomData,
path::{Path, PathBuf},
};
use tokio::fs;
use xor_name::XorName;

const DB_EXTENSION: &str = ".db";
Expand All @@ -30,20 +32,22 @@ pub struct DeletableStore {
}

impl DeletableStore {
pub fn delete(&self) -> Result<()> {
std::fs::remove_file(self.db_path.as_path()).map_err(Error::Io)
pub async fn delete(&self) -> Result<()> {
fs::remove_file(self.db_path.as_path())
.await
.map_err(Error::Io)
}
}

impl<'a, TEvent: Debug + Serialize + DeserializeOwned> EventStore<TEvent>
where
TEvent: 'a,
{
pub fn new(id: XorName, db_dir: &Path) -> Result<Self> {
pub async fn new(id: XorName, db_dir: &Path) -> Result<Self> {
let db_name = format!("{}{}", id.to_db_key()?, DB_EXTENSION);
let db_path = db_dir.join(db_name.clone());
Ok(Self {
db: new_auto_dump_db(db_dir, db_name)?,
db: new_auto_dump_db(db_dir, db_name).await?,
db_path,
_phantom: PhantomData::default(),
})
Expand Down Expand Up @@ -102,13 +106,13 @@ mod test {
use std::path::Path;
use tempdir::TempDir;

#[test]
fn history() -> Result<()> {
#[tokio::test]
async fn history() -> Result<()> {
let id = xor_name::XorName::random();
let tmp_dir = TempDir::new("root")?;
let db_dir = tmp_dir.into_path().join(Path::new(&"Token".to_string()));

let mut store = EventStore::new(id, db_dir.as_path())?;
let mut store = EventStore::new(id, db_dir.as_path()).await?;

store.append(Token::from_nano(10))?;

Expand Down
11 changes: 7 additions & 4 deletions src/dbs/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,18 @@ pub use data_store::*;
pub use errors::{Error, Result};
pub use event_store::EventStore;
use pickledb::{PickleDb, PickleDbDumpPolicy};
use std::{fs, path::Path};

use std::path::Path;
use tokio::fs;
///
pub fn new_auto_dump_db<D: AsRef<Path>, N: AsRef<Path>>(db_dir: D, db_name: N) -> Result<PickleDb> {
pub async fn new_auto_dump_db<D: AsRef<Path>, N: AsRef<Path>>(
db_dir: D,
db_name: N,
) -> Result<PickleDb> {
let db_path = db_dir.as_ref().join(db_name);
match PickleDb::load_bin(db_path.clone(), PickleDbDumpPolicy::AutoDump) {
Ok(db) => Ok(db),
Err(_) => {
fs::create_dir_all(db_dir)?;
fs::create_dir_all(db_dir).await?;
let mut db = PickleDb::new_bin(db_path.clone(), PickleDbDumpPolicy::AutoDump);

// dump is needed to actually write the db to disk.
Expand Down
11 changes: 7 additions & 4 deletions src/node/bin/launch_network.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,11 @@
use dirs_next::home_dir;
use sn_launch_tool::run_with;
use std::{
fs::{create_dir_all, remove_dir_all},
path::PathBuf,
process::{Command, Stdio},
};
use tokio::fs::{create_dir_all, remove_dir_all};

use tokio::time::{sleep, Duration};
use tracing::{debug, info};

Expand All @@ -51,8 +52,10 @@ const NODE_COUNT: &str = "60";
#[tokio::main]
async fn main() -> Result<(), String> {
let path = std::path::Path::new("nodes");
remove_dir_all(&path).unwrap_or(()); // Delete nodes directory if it exists;
create_dir_all(&path).expect("Cannot create nodes directory");
remove_dir_all(&path).await.unwrap_or(()); // Delete nodes directory if it exists;
create_dir_all(&path)
.await
.expect("Cannot create nodes directory");

let args: Vec<&str> = vec!["build", "--release"];
println!("Building current sn_node");
Expand Down Expand Up @@ -104,7 +107,7 @@ pub async fn run_network() -> Result<(), String> {
let node_log_dir = base_log_dir.join(NODES_DIR);
if !node_log_dir.exists() {
debug!("Creating '{}' folder", node_log_dir.display());
create_dir_all(node_log_dir.clone()).map_err(|err| {
create_dir_all(node_log_dir.clone()).await.map_err(|err| {
format!(
"Couldn't create target path to store nodes' generated data: {}",
err
Expand Down
20 changes: 12 additions & 8 deletions src/node/bin/sn_node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ use safe_network::routing;
fn main() {
let sn_node_thread = std::thread::Builder::new()
.name("sn_node".to_string())
.stack_size(8 * 1024 * 1024)
.stack_size(16 * 1024 * 1024)
.spawn(move || {
let rt = tokio::runtime::Runtime::new()?;
rt.block_on(run_node())?;
Expand All @@ -61,7 +61,7 @@ fn main() {
}

async fn run_node() -> Result<()> {
let config = match Config::new() {
let config = match Config::new().await {
Ok(cfg) => cfg,
Err(e) => {
println!("Failed to create Config: {:?}", e);
Expand Down Expand Up @@ -209,13 +209,17 @@ async fn run_node() -> Result<()> {
let our_conn_info = node.our_connection_info();

if config.is_first() {
set_connection_info(our_conn_info).unwrap_or_else(|err| {
error!("Unable to write our connection info to disk: {:?}", err);
});
set_connection_info(our_conn_info)
.await
.unwrap_or_else(|err| {
error!("Unable to write our connection info to disk: {:?}", err);
});
} else {
add_connection_info(our_conn_info).unwrap_or_else(|err| {
error!("Unable to add our connection info to disk: {:?}", err);
});
add_connection_info(our_conn_info)
.await
.unwrap_or_else(|err| {
error!("Unable to add our connection info to disk: {:?}", err);
});
}

match node.run(event_stream).await {
Expand Down
Loading

0 comments on commit 11c353a

Please sign in to comment.