Skip to content
This repository was archived by the owner on Nov 15, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
34577eb
service: storage monitor added
michalkucharczyk Jan 5, 2023
b5f970b
Merge remote-tracking branch 'origin/master' into mku-storage-monitor
michalkucharczyk Jan 6, 2023
37bbba4
Cargo.lock updated
michalkucharczyk Jan 6, 2023
ba0f28f
misspell
michalkucharczyk Jan 9, 2023
e360685
fs events throttling added
michalkucharczyk Jan 9, 2023
fd5679f
minor updates
michalkucharczyk Jan 9, 2023
217234f
filter out non mutating events
michalkucharczyk Jan 9, 2023
8b3310b
misspell
michalkucharczyk Jan 9, 2023
931339c
".git/.scripts/commands/fmt/fmt.sh"
Jan 10, 2023
c200159
Update client/service/src/storage_monitor.rs
michalkucharczyk Jan 12, 2023
f5501f2
storage-monitor crate added
michalkucharczyk Jan 13, 2023
45171dc
cleanup: configuration + service builder
michalkucharczyk Jan 13, 2023
f346394
storage_monitor in custom service (wip)
michalkucharczyk Jan 13, 2023
eb49400
copy-paste bad desc fixed
michalkucharczyk Jan 13, 2023
8619766
notify removed
michalkucharczyk Jan 16, 2023
a0cd44d
storage_monitor added to node
michalkucharczyk Jan 16, 2023
d3f143c
Merge remote-tracking branch 'origin/master' into mku-storage-monitor
Jan 16, 2023
a79af9a
fix for clippy
michalkucharczyk Jan 16, 2023
00e7264
publish = false
michalkucharczyk Jan 16, 2023
6c3eb1c
Update bin/node/cli/src/command.rs
michalkucharczyk Jan 17, 2023
58dcf55
Apply suggestions from code review
michalkucharczyk Jan 23, 2023
95b576b
crate name: storage-monitor -> sc-storage-monitor
michalkucharczyk Jan 23, 2023
0b8697e
error handling improved
michalkucharczyk Jan 23, 2023
c0fc2ca
Merge remote-tracking branch 'origin/master' into mku-storage-monitor
michalkucharczyk Jan 23, 2023
de35dda
Apply suggestions from code review
michalkucharczyk Jan 23, 2023
4e32f3d
publish=false removed
michalkucharczyk Jan 24, 2023
0578588
Merge remote-tracking branch 'origin/master' into mku-storage-monitor
Jan 24, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
storage-monitor crate added
  • Loading branch information
michalkucharczyk committed Jan 13, 2023
commit f5501f22b2e1bce41eb14f15c76f74cc15873bf1
19 changes: 19 additions & 0 deletions client/storage-monitor/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
[package]
name = "storage-monitor"
version = "0.1.0"
authors = ["Parity Technologies <admin@parity.io>"]
edition = "2021"
license = "GPL-3.0-or-later WITH Classpath-exception-2.0"
repository = "https://github.com/paritytech/substrate"
description = "BEEFY Client gadget for substrate"
homepage = "https://substrate.io"

[dependencies]
clap = { version = "4.0.9", features = ["derive", "string"] }
futures = "0.3.21"
log = "0.4.17"
nix = { version = "0.26.1", features = ["fs"] }
notify = "5.0.0"
sc-client-db = { version = "0.10.0-dev", default-features = false, path = "../db" }
sc-utils = { version = "4.0.0-dev", path = "../utils" }
sp-core = { version = "7.0.0", path = "../../primitives/core" }
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,13 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.

use crate::{config::Configuration, error::Error};
use clap::Args;
use futures::StreamExt;
use nix::{errno::Errno, sys::statvfs::statvfs};
use notify::{Config, Event, RecommendedWatcher, RecursiveMode, Watcher};
use sc_client_db::DatabaseSource;
use sc_utils::mpsc::{tracing_unbounded, TracingUnboundedReceiver};
use sp_core::traits::SpawnEssentialNamed;
use std::{
path::{Path, PathBuf},
time::{Duration, Instant},
Expand All @@ -29,6 +31,22 @@ use std::{
const LOG_TARGET: &str = "storage-monitor";
const THROTTLE_PERIOD: std::time::Duration = Duration::from_secs(2);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also wondering how did you end up choosing 2 sec? why not 5 or 10s? or even 60s? do you know the avg disk space growth rate in polkadot?

Copy link
Contributor Author

@michalkucharczyk michalkucharczyk Jan 23, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a guess. The syscall is cheap, should not affect the system. I did not measure the usage by node, but there also can be other consumers of storage running on the machine.

I also added a param, so anyone can adjust if required.


type Error = String;

/// Parameters used to create the storage monitor.
#[derive(Default, Debug, Clone, Args)]
pub struct StorageMonitorParams {
/// Required available space on database storage. If available space for DB storage drops below
/// the given threshold, node will be gracefully terminated. If `0` is given monitoring will be
/// disabled.
#[arg(long = "db-storage-threshold", value_name = "MB", default_value_t = 1000)]
pub threshold: u64,

/// How often available space is polled.
#[arg(long = "db-storage-polling-period", value_name = "SECONDS", default_value_t = 5, value_parser = clap::value_parser!(u32).range(1..))]
pub polling_period: u32,
}

/// Storage monitor service: checks the available space for the filesystem for fiven path.
pub struct StorageMonitorService {
/// watched path
Expand All @@ -45,21 +63,19 @@ pub struct StorageMonitorService {

impl StorageMonitorService {
/// Creates new StorageMonitorService for given client config
pub fn new_for_config(config: &Configuration) -> Result<Option<Self>, Error> {
Ok(match (config.available_storage_threshold, config.database.path()) {
pub fn try_spawn(parameters: StorageMonitorParams, database: DatabaseSource, spawner: &impl SpawnEssentialNamed) -> Result<(), Error> {
Ok(match (parameters.threshold, database.path()) {
(0, _) => {
log::info!(
target: LOG_TARGET,
"StorageMonitorService: threshold 0 given, storage monitoring disabled",
);
None
},
(_, None) => {
log::warn!(
target: LOG_TARGET,
"StorageMonitorService: no database path to observe",
);
None
},
(threshold, Some(path)) => {
let (sink, stream) = tracing_unbounded("mpsc_storage_monitor", 1024);
Expand All @@ -70,11 +86,11 @@ impl StorageMonitorService {
},
Config::default(),
)
.map_err(|e| Error::Other(format!("Could not create fs watcher {e}")))?;
.map_err(|e| format!("Could not create fs watcher {e}"))?;

watcher
.watch(path.as_ref(), RecursiveMode::Recursive)
.map_err(|e| Error::Other(format!("Could not start fs watcher {e}")))?;
.map_err(|e| format!("Could not start fs watcher {e}"))?;

log::debug!(
target: LOG_TARGET,
Expand All @@ -84,20 +100,26 @@ impl StorageMonitorService {

Self::check_free_space(&path, threshold)?;

Some(StorageMonitorService {
let storage_monitor_service = StorageMonitorService {
path: path.to_path_buf(),
stream,
threshold,
recent_check: Instant::now(),
_watcher: watcher,
})
};

spawner.spawn_essential(
"storage-monitor",
None,
Box::pin(storage_monitor_service.run()),
);
},
})
}

/// Main monitoring loop, intended to be spawned as essential task. Quits if free space drop
/// below threshold.
pub async fn run(mut self) {
async fn run(mut self) {
while let Some(watch_event) = self.stream.next().await {
match watch_event {
Ok(Event { kind: notify::EventKind::Access(_), .. }) => {
Expand Down Expand Up @@ -144,7 +166,7 @@ impl StorageMonitorService {
threshold,
);
log::error!(target: LOG_TARGET, "{}", msg);
Err(Error::Other(msg))
Err(msg)
} else {
Ok(())
}
Expand Down