Skip to content

Commit 3eb9299

Browse files
authored
Merge pull request #72 from skel84/issue-70-jepsen-refactor
refactor(jepsen): split CLI into focused modules
2 parents 65a8953 + acbb408 commit 3eb9299

File tree

20 files changed

+7774
-6292
lines changed

20 files changed

+7774
-6292
lines changed

crates/allocdb-node/src/bin/allocdb-jepsen.rs

Lines changed: 292 additions & 6288 deletions
Large diffs are not rendered by default.

crates/allocdb-node/src/bin/allocdb-jepsen/args.rs

Lines changed: 461 additions & 0 deletions
Large diffs are not rendered by default.

crates/allocdb-node/src/bin/allocdb-jepsen/cluster.rs

Lines changed: 672 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
use std::fs::{self, File};
2+
use std::io::Write;
3+
use std::path::{Path, PathBuf};
4+
use std::sync::atomic::Ordering;
5+
use std::time::{SystemTime, UNIX_EPOCH};
6+
7+
use super::NEXT_PROBE_RESOURCE_ID;
8+
9+
pub(super) fn required_field<'a>(
10+
fields: &'a std::collections::BTreeMap<String, String>,
11+
field: &str,
12+
) -> Result<&'a str, String> {
13+
fields
14+
.get(field)
15+
.map(String::as_str)
16+
.ok_or_else(|| format!("missing run status field `{field}`"))
17+
}
18+
19+
pub(super) fn parse_required_u32(
20+
fields: &std::collections::BTreeMap<String, String>,
21+
field: &str,
22+
) -> Result<u32, String> {
23+
required_field(fields, field)?
24+
.parse::<u32>()
25+
.map_err(|error| format!("invalid `{field}`: {error}"))
26+
}
27+
28+
pub(super) fn parse_required_u64(
29+
fields: &std::collections::BTreeMap<String, String>,
30+
field: &str,
31+
) -> Result<u64, String> {
32+
required_field(fields, field)?
33+
.parse::<u64>()
34+
.map_err(|error| format!("invalid `{field}`: {error}"))
35+
}
36+
37+
pub(super) fn parse_required_u128(
38+
fields: &std::collections::BTreeMap<String, String>,
39+
field: &str,
40+
) -> Result<u128, String> {
41+
required_field(fields, field)?
42+
.parse::<u128>()
43+
.map_err(|error| format!("invalid `{field}`: {error}"))
44+
}
45+
46+
pub(super) fn parse_optional_u64(value: &str) -> Result<Option<u64>, String> {
47+
if value == "none" {
48+
Ok(None)
49+
} else {
50+
value
51+
.parse::<u64>()
52+
.map(Some)
53+
.map_err(|error| format!("invalid optional u64 `{value}`: {error}"))
54+
}
55+
}
56+
57+
pub(super) fn parse_optional_usize(value: &str) -> Result<Option<usize>, String> {
58+
if value == "none" {
59+
Ok(None)
60+
} else {
61+
value
62+
.parse::<usize>()
63+
.map(Some)
64+
.map_err(|error| format!("invalid optional usize `{value}`: {error}"))
65+
}
66+
}
67+
68+
pub(super) fn parse_optional_bool(value: &str) -> Result<Option<bool>, String> {
69+
match value {
70+
"none" => Ok(None),
71+
"true" => Ok(Some(true)),
72+
"false" => Ok(Some(false)),
73+
other => Err(format!("invalid optional bool `{other}`")),
74+
}
75+
}
76+
77+
pub(super) fn parse_optional_path(value: &str) -> Option<PathBuf> {
78+
if value == "none" {
79+
None
80+
} else {
81+
Some(PathBuf::from(value))
82+
}
83+
}
84+
85+
pub(super) fn parse_optional_string(value: &str) -> Option<String> {
86+
if value == "none" {
87+
None
88+
} else {
89+
Some(String::from(value))
90+
}
91+
}
92+
93+
pub(super) fn write_text_atomically(path: &Path, bytes: &str) -> Result<(), String> {
94+
if let Some(parent) = path.parent() {
95+
fs::create_dir_all(parent)
96+
.map_err(|error| format!("failed to create {}: {error}", parent.display()))?;
97+
}
98+
let temp_path = path.with_extension(format!("{}.tmp", std::process::id()));
99+
let mut file = File::create(&temp_path)
100+
.map_err(|error| format!("failed to create {}: {error}", temp_path.display()))?;
101+
file.write_all(bytes.as_bytes())
102+
.map_err(|error| format!("failed to write {}: {error}", temp_path.display()))?;
103+
file.sync_all()
104+
.map_err(|error| format!("failed to sync {}: {error}", temp_path.display()))?;
105+
drop(file);
106+
fs::rename(&temp_path, path).map_err(|error| {
107+
let _ = fs::remove_file(&temp_path);
108+
format!("failed to replace {}: {error}", path.display())
109+
})
110+
}
111+
112+
pub(super) fn append_text_line(path: &Path, line: &str) -> Result<(), String> {
113+
if let Some(parent) = path.parent() {
114+
fs::create_dir_all(parent)
115+
.map_err(|error| format!("failed to create {}: {error}", parent.display()))?;
116+
}
117+
let mut file = fs::OpenOptions::new()
118+
.create(true)
119+
.append(true)
120+
.open(path)
121+
.map_err(|error| format!("failed to open {}: {error}", path.display()))?;
122+
file.write_all(line.as_bytes())
123+
.map_err(|error| format!("failed to append {}: {error}", path.display()))?;
124+
file.sync_all()
125+
.map_err(|error| format!("failed to sync {}: {error}", path.display()))
126+
}
127+
128+
pub(super) fn current_time_millis() -> u128 {
129+
SystemTime::now()
130+
.duration_since(UNIX_EPOCH)
131+
.unwrap_or_default()
132+
.as_millis()
133+
}
134+
135+
pub(super) fn unique_probe_resource_id() -> u128 {
136+
let millis = current_time_millis();
137+
let nonce = u128::from(NEXT_PROBE_RESOURCE_ID.fetch_add(1, Ordering::Relaxed));
138+
(millis << 32) | nonce
139+
}

0 commit comments

Comments
 (0)