-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #66 from glotzerlab/jobs
Add `show jobs`
- Loading branch information
Showing
10 changed files
with
290 additions
and
13 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
# show jobs | ||
|
||
Usage: | ||
```bash | ||
row show jobs [OPTIONS] [DIRECTORIES] | ||
``` | ||
|
||
`row show jobs` lists submitted jobs that execute a matching action on any of the | ||
provided directories. | ||
|
||
## `[DIRECTORIES]` | ||
|
||
List jobs that execute an action on one or more of the given directories. By default, | ||
**row** shows jobs executing an action on any directory. | ||
|
||
Pass a single `-` to read the directories from stdin (separated by newlines): | ||
```bash | ||
echo "dir1" | row show jobs [OPTIONS] - | ||
``` | ||
|
||
## `[OPTIONS]` | ||
|
||
### `--action` | ||
|
||
(also: `-a`) | ||
|
||
Set `--action <pattern>` to show only jobs that mach the given pattern by name. | ||
By default, **row** shows jobs executing any action. `<pattern>` is a wildcard pattern. | ||
|
||
### `--no-header` | ||
|
||
Hide the header in the output. | ||
|
||
### `--short` | ||
|
||
Show only the job IDs. | ||
|
||
## Examples | ||
|
||
* Show all jobs: | ||
```bash | ||
row show jobs | ||
``` | ||
* Show jobs that execute actions on any of the given directories: | ||
```bash | ||
row show jobs directory1 directory | ||
``` | ||
* Show jobs that execute the action 'one': | ||
```bash | ||
row show jobs --action one | ||
``` | ||
* Show jobs that execute an action starting with 'analyze': | ||
```bash | ||
row show jobs --action 'analyze*' | ||
``` | ||
* Cancel SLURM jobs executing action 'two': | ||
```bash | ||
row show jobs --action two --short | xargs scancel | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,147 @@ | ||
// Copyright (c) 2024 The Regents of the University of Michigan. | ||
// Part of row, released under the BSD 3-Clause License. | ||
|
||
use clap::Args; | ||
use clap_complete::ArgValueCandidates; | ||
use console::Style; | ||
use log::{debug, trace}; | ||
use std::collections::{BTreeMap, HashSet}; | ||
use std::error::Error; | ||
use std::io::Write; | ||
use std::path::PathBuf; | ||
use wildmatch::WildMatch; | ||
|
||
use crate::cli::{self, autocomplete, GlobalOptions}; | ||
use crate::ui::{Alignment, Item, Row, Table}; | ||
use row::project::Project; | ||
use row::MultiProgressContainer; | ||
|
||
#[derive(Args, Debug)] | ||
#[allow(clippy::struct_excessive_bools)] | ||
pub struct Arguments { | ||
/// Show jobs running on these directories (defaults to all). Use 'show jobs -' to read from stdin. | ||
#[arg(add=ArgValueCandidates::new(autocomplete::get_directory_candidates))] | ||
directories: Vec<PathBuf>, | ||
|
||
/// Show jobs running actions that match a wildcard pattern. | ||
#[arg(short, long, value_name = "pattern", default_value_t=String::from("*"), display_order=0, | ||
add=ArgValueCandidates::new(autocomplete::get_action_candidates))] | ||
action: String, | ||
|
||
/// Hide the table header. | ||
#[arg(long, display_order = 0)] | ||
no_header: bool, | ||
|
||
/// Show only job IDs. | ||
#[arg(long, default_value_t = false, display_order = 0)] | ||
short: bool, | ||
} | ||
|
||
struct JobDetails { | ||
action: String, | ||
n: u64, | ||
} | ||
|
||
/** Find jobs that match the given directories and the action wildcard on the selected cluster. | ||
*/ | ||
fn find( | ||
directories: Vec<PathBuf>, | ||
action: &str, | ||
project: &Project, | ||
) -> Result<BTreeMap<u32, JobDetails>, Box<dyn Error>> { | ||
debug!("Finding matching jobs."); | ||
let mut result: BTreeMap<u32, JobDetails> = BTreeMap::new(); | ||
|
||
let action_matcher = WildMatch::new(action); | ||
|
||
let query_directories: HashSet<PathBuf> = | ||
HashSet::from_iter(cli::parse_directories(directories, || { | ||
Ok(project.state().list_directories()) | ||
})?); | ||
|
||
for (action_name, jobs_by_directory) in project.state().submitted() { | ||
if !action_matcher.matches(action_name) { | ||
trace!( | ||
"Skipping action '{}'. It does not match the pattern '{}'.", | ||
action_name, | ||
action | ||
); | ||
continue; | ||
} | ||
|
||
for (directory_name, (cluster_name, job_id)) in jobs_by_directory { | ||
if cluster_name != project.cluster_name() { | ||
trace!( | ||
"Skipping cluster '{cluster_name}'. It does not match selected cluster '{}'.", | ||
project.cluster_name() | ||
); | ||
continue; | ||
} | ||
|
||
if query_directories.contains(directory_name) { | ||
result | ||
.entry(*job_id) | ||
.and_modify(|e| e.n += 1) | ||
.or_insert(JobDetails { | ||
action: action_name.clone(), | ||
n: 1, | ||
}); | ||
} | ||
} | ||
} | ||
|
||
Ok(result) | ||
} | ||
|
||
/** Show jobs running on given directories where the action also matches a wildcard. | ||
Print a human-readable list of job IDs, the action they are running, and the number of | ||
directories that the job acts on. | ||
*/ | ||
pub fn show<W: Write>( | ||
options: &GlobalOptions, | ||
args: Arguments, | ||
multi_progress: &mut MultiProgressContainer, | ||
output: &mut W, | ||
) -> Result<(), Box<dyn Error>> { | ||
debug!("Showing jobs."); | ||
|
||
let mut project = Project::open(options.io_threads, &options.cluster, multi_progress)?; | ||
|
||
let jobs = find(args.directories, &args.action, &project)?; | ||
|
||
let mut table = Table::new().with_hide_header(if args.short { true } else { args.no_header }); | ||
table.header = vec![ | ||
Item::new("ID".to_string(), Style::new().underlined()), | ||
Item::new("Action".to_string(), Style::new().underlined()), | ||
Item::new("Directories".to_string(), Style::new().underlined()), | ||
]; | ||
|
||
for (job_id, job_details) in jobs { | ||
let mut row = Vec::new(); | ||
|
||
row.push( | ||
Item::new(job_id.to_string(), Style::new().bold()).with_alignment(Alignment::Right), | ||
); | ||
|
||
// Only show job IDs when user requests short output. | ||
if args.short { | ||
table.rows.push(Row::Items(row)); | ||
continue; | ||
} | ||
|
||
row.push(Item::new(job_details.action, Style::new())); | ||
row.push( | ||
Item::new(job_details.n.to_string(), Style::new()).with_alignment(Alignment::Right), | ||
); | ||
|
||
table.rows.push(Row::Items(row)); | ||
} | ||
|
||
table.write(output)?; | ||
output.flush()?; | ||
|
||
project.close(multi_progress)?; | ||
|
||
Ok(()) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters