Added more logging and temp files for file linked
This commit is contained in:
parent
ec54efe8be
commit
7b11578f7a
6 changed files with 142 additions and 38 deletions
|
@ -19,3 +19,4 @@ serde = { version = "1.0", features = ["derive"] }
|
||||||
thiserror = "1.0"
|
thiserror = "1.0"
|
||||||
anyhow = "1.0"
|
anyhow = "1.0"
|
||||||
bincode = "1.3.3"
|
bincode = "1.3.3"
|
||||||
|
log = "0.4.14"
|
17
file_linked/src/error.rs
Normal file
17
file_linked/src/error.rs
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
use thiserror::Error;
|
||||||
|
|
||||||
|
#[derive(Error, Debug)]
|
||||||
|
pub enum Error {
|
||||||
|
#[error(transparent)]
|
||||||
|
Serialization(bincode::Error),
|
||||||
|
#[error(transparent)]
|
||||||
|
IO(std::io::Error),
|
||||||
|
#[error(transparent)]
|
||||||
|
Other(#[from] anyhow::Error),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<std::io::Error> for Error {
|
||||||
|
fn from(error: std::io::Error) -> Error {
|
||||||
|
Error::IO(error)
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,23 +1,15 @@
|
||||||
//! A wrapper around an object that ties it to a physical file
|
//! A wrapper around an object that ties it to a physical file
|
||||||
|
|
||||||
extern crate serde;
|
pub mod error;
|
||||||
|
|
||||||
use anyhow::Context;
|
use anyhow::{anyhow, Context};
|
||||||
|
use error::Error;
|
||||||
|
use log::info;
|
||||||
use serde::de::DeserializeOwned;
|
use serde::de::DeserializeOwned;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use std::fs::File;
|
use std::fs::{copy, remove_file, File};
|
||||||
|
use std::io::ErrorKind;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use thiserror::Error;
|
|
||||||
|
|
||||||
#[derive(Error, Debug)]
|
|
||||||
pub enum Error {
|
|
||||||
#[error(transparent)]
|
|
||||||
Serialization(bincode::Error),
|
|
||||||
#[error(transparent)]
|
|
||||||
IO(std::io::Error),
|
|
||||||
#[error(transparent)]
|
|
||||||
Other(#[from] anyhow::Error),
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A wrapper around an object `T` that ties the object to a physical file
|
/// A wrapper around an object `T` that ties the object to a physical file
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -27,6 +19,7 @@ where
|
||||||
{
|
{
|
||||||
val: T,
|
val: T,
|
||||||
path: PathBuf,
|
path: PathBuf,
|
||||||
|
temp_file_path: PathBuf,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> FileLinked<T>
|
impl<T> FileLinked<T>
|
||||||
|
@ -106,21 +99,57 @@ where
|
||||||
/// # }
|
/// # }
|
||||||
/// ```
|
/// ```
|
||||||
pub fn new(val: T, path: &Path) -> Result<FileLinked<T>, Error> {
|
pub fn new(val: T, path: &Path) -> Result<FileLinked<T>, Error> {
|
||||||
|
let mut temp_file_path = path.to_path_buf();
|
||||||
|
temp_file_path.set_file_name(format!(
|
||||||
|
".temp{}",
|
||||||
|
path.file_name()
|
||||||
|
.ok_or_else(|| anyhow!("Unable to get filename for tempfile {}", path.display()))?
|
||||||
|
.to_str()
|
||||||
|
.ok_or_else(|| anyhow!("Unable to get filename for tempfile {}", path.display()))?
|
||||||
|
));
|
||||||
|
|
||||||
let result = FileLinked {
|
let result = FileLinked {
|
||||||
val,
|
val,
|
||||||
path: path.to_path_buf(),
|
path: path.to_path_buf(),
|
||||||
|
temp_file_path,
|
||||||
};
|
};
|
||||||
|
|
||||||
result.write_data()?;
|
result.write_data()?;
|
||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_data(&self) -> Result<(), Error> {
|
fn write_data(&self) -> Result<(), Error> {
|
||||||
let file = File::create(&self.path)
|
match File::open(&self.path) {
|
||||||
.with_context(|| format!("Unable to open path {}", self.path.display()))?;
|
Ok(_) => {
|
||||||
|
copy(&self.path, &self.temp_file_path).with_context(|| {
|
||||||
|
format!(
|
||||||
|
"Unable to copy temp file from {} to {}",
|
||||||
|
self.path.display(),
|
||||||
|
self.temp_file_path.display()
|
||||||
|
)
|
||||||
|
})?;
|
||||||
|
|
||||||
|
let file = File::create(&self.path)?;
|
||||||
|
|
||||||
bincode::serialize_into(file, &self.val)
|
bincode::serialize_into(file, &self.val)
|
||||||
.with_context(|| format!("Unable to write to file {}", self.path.display()))?;
|
.with_context(|| format!("Unable to write to file {}", self.path.display()))?;
|
||||||
|
|
||||||
|
remove_file(&self.temp_file_path).with_context(|| {
|
||||||
|
format!(
|
||||||
|
"Unable to remove temp file {}",
|
||||||
|
self.temp_file_path.display()
|
||||||
|
)
|
||||||
|
})?;
|
||||||
|
}
|
||||||
|
Err(error) if error.kind() == ErrorKind::NotFound => {
|
||||||
|
let file = File::create(&self.path)?;
|
||||||
|
|
||||||
|
bincode::serialize_into(file, &self.val)
|
||||||
|
.with_context(|| format!("Unable to write to file {}", self.path.display()))?;
|
||||||
|
}
|
||||||
|
Err(error) => return Err(Error::IO(error)),
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -130,6 +159,7 @@ where
|
||||||
/// # Examples
|
/// # Examples
|
||||||
/// ```
|
/// ```
|
||||||
/// # use file_linked::*;
|
/// # use file_linked::*;
|
||||||
|
/// # use file_linked::error::Error;
|
||||||
/// # use serde::{Deserialize, Serialize};
|
/// # use serde::{Deserialize, Serialize};
|
||||||
/// # use std::fmt;
|
/// # use std::fmt;
|
||||||
/// # use std::string::ToString;
|
/// # use std::string::ToString;
|
||||||
|
@ -176,6 +206,7 @@ where
|
||||||
/// # Examples
|
/// # Examples
|
||||||
/// ```
|
/// ```
|
||||||
/// # use file_linked::*;
|
/// # use file_linked::*;
|
||||||
|
/// # use file_linked::error::Error;
|
||||||
/// # use serde::{Deserialize, Serialize};
|
/// # use serde::{Deserialize, Serialize};
|
||||||
/// # use std::fmt;
|
/// # use std::fmt;
|
||||||
/// # use std::string::ToString;
|
/// # use std::string::ToString;
|
||||||
|
@ -229,6 +260,7 @@ where
|
||||||
/// # Examples
|
/// # Examples
|
||||||
/// ```
|
/// ```
|
||||||
/// # use file_linked::*;
|
/// # use file_linked::*;
|
||||||
|
/// # use file_linked::error::Error;
|
||||||
/// # use serde::{Deserialize, Serialize};
|
/// # use serde::{Deserialize, Serialize};
|
||||||
/// # use std::fmt;
|
/// # use std::fmt;
|
||||||
/// # use std::string::ToString;
|
/// # use std::string::ToString;
|
||||||
|
@ -274,18 +306,66 @@ where
|
||||||
/// # }
|
/// # }
|
||||||
/// ```
|
/// ```
|
||||||
pub fn from_file(path: &Path) -> Result<FileLinked<T>, Error> {
|
pub fn from_file(path: &Path) -> Result<FileLinked<T>, Error> {
|
||||||
let file =
|
let mut temp_file_path = path.to_path_buf();
|
||||||
File::open(path).with_context(|| format!("Unable to open file {}", path.display()))?;
|
temp_file_path.set_file_name(format!(
|
||||||
|
".temp{}",
|
||||||
|
path.file_name()
|
||||||
|
.ok_or_else(|| anyhow!("Unable to get filename for tempfile {}", path.display()))?
|
||||||
|
.to_str()
|
||||||
|
.ok_or_else(|| anyhow!("Unable to get filename for tempfile {}", path.display()))?
|
||||||
|
));
|
||||||
|
|
||||||
let val = bincode::deserialize_from(file)
|
match File::open(path).map_err(Error::from).and_then(|file| {
|
||||||
.with_context(|| String::from("Unable to parse value from file."))?;
|
bincode::deserialize_from::<std::fs::File, T>(file)
|
||||||
|
.with_context(|| format!("Unable to deserialize file {}", path.display()))
|
||||||
|
.map_err(Error::from)
|
||||||
|
}) {
|
||||||
|
Ok(val) => Ok(FileLinked {
|
||||||
|
val,
|
||||||
|
path: path.to_path_buf(),
|
||||||
|
temp_file_path,
|
||||||
|
}),
|
||||||
|
Err(err) => {
|
||||||
|
info!(
|
||||||
|
"Unable to read/deserialize file {} attempting to open temp file {}",
|
||||||
|
path.display(),
|
||||||
|
temp_file_path.display()
|
||||||
|
);
|
||||||
|
|
||||||
|
// Try to use temp file instead and see if that file exists and is serializable
|
||||||
|
let val = FileLinked::from_temp_file(&temp_file_path, path)
|
||||||
|
.map_err(|_| err)
|
||||||
|
.with_context(|| format!("Failed to read/deserialize the object from the file {} and temp file {}", path.display(), temp_file_path.display()))?;
|
||||||
|
|
||||||
Ok(FileLinked {
|
Ok(FileLinked {
|
||||||
val,
|
val,
|
||||||
path: path.to_path_buf(),
|
path: path.to_path_buf(),
|
||||||
|
temp_file_path,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn from_temp_file(temp_file_path: &Path, path: &Path) -> Result<T, Error> {
|
||||||
|
let file = File::open(temp_file_path)
|
||||||
|
.with_context(|| format!("Unable to open file {}", temp_file_path.display()))?;
|
||||||
|
|
||||||
|
let val = bincode::deserialize_from(file).with_context(|| {
|
||||||
|
format!(
|
||||||
|
"Could not deserialize from temp file {}",
|
||||||
|
temp_file_path.display()
|
||||||
|
)
|
||||||
|
})?;
|
||||||
|
|
||||||
|
info!("Successfully deserialized value from temp file");
|
||||||
|
|
||||||
|
copy(temp_file_path, path)?;
|
||||||
|
remove_file(temp_file_path)
|
||||||
|
.with_context(|| format!("Unable to remove temp file {}", temp_file_path.display()))?;
|
||||||
|
|
||||||
|
Ok(val)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
|
|
@ -10,8 +10,8 @@ use clap::App;
|
||||||
use gemla::core::{Gemla, GemlaConfig};
|
use gemla::core::{Gemla, GemlaConfig};
|
||||||
use gemla::error::log_error;
|
use gemla::error::log_error;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use test_state::TestState;
|
|
||||||
use std::time::Instant;
|
use std::time::Instant;
|
||||||
|
use test_state::TestState;
|
||||||
// use std::io::Write;
|
// use std::io::Write;
|
||||||
|
|
||||||
/// Runs a simluation of a genetic algorithm against a dataset.
|
/// Runs a simluation of a genetic algorithm against a dataset.
|
||||||
|
|
|
@ -8,9 +8,9 @@ use crate::tree::Tree;
|
||||||
use anyhow::anyhow;
|
use anyhow::anyhow;
|
||||||
use file_linked::FileLinked;
|
use file_linked::FileLinked;
|
||||||
use genetic_node::{GeneticNode, GeneticNodeWrapper, GeneticState};
|
use genetic_node::{GeneticNode, GeneticNodeWrapper, GeneticState};
|
||||||
|
use log::{info, trace};
|
||||||
use serde::de::DeserializeOwned;
|
use serde::de::DeserializeOwned;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use log::{info, trace};
|
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::ErrorKind;
|
use std::io::ErrorKind;
|
||||||
|
@ -67,7 +67,10 @@ where
|
||||||
self.data
|
self.data
|
||||||
.mutate(|(d, c)| Gemla::increase_height(d, c, steps))??;
|
.mutate(|(d, c)| Gemla::increase_height(d, c, steps))??;
|
||||||
|
|
||||||
info!("Height of simulation tree increased to {}", self.data.readonly().0.as_ref().unwrap().height());
|
info!(
|
||||||
|
"Height of simulation tree increased to {}",
|
||||||
|
self.data.readonly().0.as_ref().unwrap().height()
|
||||||
|
);
|
||||||
|
|
||||||
self.data
|
self.data
|
||||||
.mutate(|(d, _c)| Gemla::process_tree(d.as_mut().unwrap()))??;
|
.mutate(|(d, _c)| Gemla::process_tree(d.as_mut().unwrap()))??;
|
||||||
|
@ -146,7 +149,11 @@ where
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
trace!("{:?} completed in {:?}", node_state, node_state_time.elapsed());
|
trace!(
|
||||||
|
"{:?} completed in {:?}",
|
||||||
|
node_state,
|
||||||
|
node_state_time.elapsed()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
info!("Processed node in {:?}", node_time.elapsed());
|
info!("Processed node in {:?}", node_time.elapsed());
|
||||||
|
|
|
@ -1,20 +1,20 @@
|
||||||
use thiserror::Error;
|
|
||||||
use log::error;
|
use log::error;
|
||||||
|
use thiserror::Error;
|
||||||
|
|
||||||
#[derive(Error, Debug)]
|
#[derive(Error, Debug)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
FileLinked(file_linked::Error),
|
FileLinked(file_linked::error::Error),
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
IO(std::io::Error),
|
IO(std::io::Error),
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
Other(#[from] anyhow::Error),
|
Other(#[from] anyhow::Error),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<file_linked::Error> for Error {
|
impl From<file_linked::error::Error> for Error {
|
||||||
fn from(error: file_linked::Error) -> Error {
|
fn from(error: file_linked::error::Error) -> Error {
|
||||||
match error {
|
match error {
|
||||||
file_linked::Error::Other(e) => Error::Other(e),
|
file_linked::error::Error::Other(e) => Error::Other(e),
|
||||||
_ => Error::FileLinked(error),
|
_ => Error::FileLinked(error),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -32,4 +32,3 @@ pub fn log_error<T>(result: Result<T, Error>) -> Result<T, Error> {
|
||||||
e
|
e
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue