1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
|
use crate::step::Step;
use serde::{Deserialize, Serialize};
use std::collections::HashSet;
use std::fs::File;
use std::path::{Path, PathBuf};
#[derive(Debug, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct Specification {
benchmarks: Vec<Benchmark>,
}
#[derive(Debug, thiserror::Error)]
pub enum SpecificationError {
#[error("Duplicate benchmark name {0}")]
DuplicateBenchmark(String),
#[error("Couldn't open {0}: {1}")]
Open(PathBuf, std::io::Error),
#[error("Couldn't read YAML specification from {0}:\n {1}")]
Yaml(PathBuf, serde_yaml::Error),
}
#[derive(Debug, Serialize, Deserialize)]
pub struct Benchmark {
benchmark: String,
backups: Vec<Backup>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct Backup {
pub changes: Vec<Change>,
}
#[derive(Debug, Serialize, Deserialize)]
pub enum Change {
#[serde(rename = "create")]
Create(Create),
#[serde(rename = "delete")]
Delete(FileCount),
#[serde(rename = "rename")]
Rename(FileCount),
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Create {
files: u64,
file_size: u64,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FileCount {
files: u64,
}
impl Specification {
pub fn from_file(filename: &Path) -> Result<Self, SpecificationError> {
let f = File::open(filename)
.map_err(|err| SpecificationError::Open(filename.to_path_buf(), err))?;
let spec: Specification = serde_yaml::from_reader(f)
.map_err(|err| SpecificationError::Yaml(filename.to_path_buf(), err))?;
spec.check()?;
Ok(spec)
}
fn check(&self) -> Result<(), SpecificationError> {
let mut names = HashSet::new();
for name in self.benchmarks().map(|b| b.name()) {
let name = name.to_string();
if names.contains(&name) {
return Err(SpecificationError::DuplicateBenchmark(name));
}
names.insert(name);
}
Ok(())
}
pub fn benchmarks(&self) -> impl Iterator<Item = &Benchmark> {
self.benchmarks.iter()
}
pub fn steps(&self) -> Vec<Step> {
let mut steps = vec![];
for b in self.benchmarks() {
steps.push(Step::Start(b.name().to_string()));
for (i, backup) in b.backups().enumerate() {
for change in backup.changes() {
steps.push(Step::from(change));
}
steps.push(Step::Backup(i));
}
for (i, _) in b.backups().enumerate() {
steps.push(Step::Restore(i));
}
steps.push(Step::Stop(b.name().to_string()));
}
steps
}
}
impl Benchmark {
pub fn name(&self) -> &str {
&self.benchmark
}
pub fn backups(&self) -> impl Iterator<Item = &Backup> {
self.backups.iter()
}
}
impl Backup {
pub fn changes(&self) -> impl Iterator<Item = &Change> {
self.changes.iter()
}
}
impl Change {
pub fn execute(&self) -> Result<(), SpecificationError> {
match self {
Change::Create(x) => println!("create {} {}", x.files, x.file_size),
Change::Rename(x) => println!("rename {}", x.files),
Change::Delete(x) => println!("delete {}", x.files),
}
Ok(())
}
}
|