use logfile_id::LogfileID;
use logfile_partition::LogfilePartition;
use serde_json as json;
use std::fs;
use std::io::{Read, Write};
use std::path::Path;
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct LogfileTransaction {
pub id: String,
pub partitions: Vec<LogfileTransactionPartition>,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct LogfileTransactionPartition {
pub time_head: u64,
pub time_tail: u64,
pub offset: u64,
}
impl LogfileTransaction {
pub fn new(id: &LogfileID, partitions: &[LogfilePartition]) -> LogfileTransaction {
let partitions = partitions
.iter()
.map(|partition| LogfileTransactionPartition {
time_head: partition.get_time_head(),
time_tail: partition.get_time_tail(),
offset: partition.get_file_offset(),
});
LogfileTransaction {
id: id.get_string(),
partitions: partitions.collect(),
}
}
pub fn read_file(path: &Path) -> Result<LogfileTransaction, ::Error> {
let mut file = fs::File::open(path)?;
let mut data = String::new();
file.read_to_string(&mut data)?;
let transaction = match json::from_str(&data) {
Ok(v) => v,
Err(e) => return Err(err_server!("error while decoding transaction file: {}", e)),
};
Ok(transaction)
}
pub fn write_file(&self, path: &Path) -> Result<(), ::Error> {
let encoded = match json::to_vec(&self) {
Ok(v) => v,
Err(e) => return Err(err_server!("error while encoding transaction file: {}", e)),
};
let path_swap = format!(
"{}.swap",
match path.to_str() {
Some(v) => v,
None => return Err(err_server!("invalid transaction path")),
}
);
{
let mut file = fs::File::create(&path_swap)?;
file.write_all(&encoded)?;
file.sync_data()?;
}
fs::rename(&path_swap, &path)?;
Ok(())
}
}