Skip to content

Commit

Permalink
Add Soft level
Browse files Browse the repository at this point in the history
  • Loading branch information
hkctkuy authored and hkctkuy committed Dec 22, 2023
1 parent 9c72749 commit 6b0eb62
Show file tree
Hide file tree
Showing 2 changed files with 114 additions and 7 deletions.
75 changes: 74 additions & 1 deletion casr/src/bin/casr-cluster.rs
Original file line number Diff line number Diff line change
Expand Up @@ -451,7 +451,18 @@ fn update_clusters(
// Handle deviant casreps
let (result, before, after) = if !deviants.is_empty() {
// Get clusters from deviants
let (deviant_clusters, before, after) = gen_clusters(&deviants, max, dedup)?;
let (mut deviant_clusters, before, mut after) = gen_clusters(&deviants, max, dedup)?;
if let ToleranceLevel::Soft = tolerance_level {
// Merge old and new clusters
let removed = if let Ok(removed) =
merge_clusters(&mut clusters, &mut deviant_clusters, oldpath, dedup)

Check warning on line 458 in casr/src/bin/casr-cluster.rs

View check run for this annotation

Codecov / codecov/patch

casr/src/bin/casr-cluster.rs#L456-L458

Added lines #L456 - L458 were not covered by tests
{
removed

Check warning on line 460 in casr/src/bin/casr-cluster.rs

View check run for this annotation

Codecov / codecov/patch

casr/src/bin/casr-cluster.rs#L460

Added line #L460 was not covered by tests
} else {
0
};
after -= removed;

Check warning on line 464 in casr/src/bin/casr-cluster.rs

View check run for this annotation

Codecov / codecov/patch

casr/src/bin/casr-cluster.rs#L462-L464

Added lines #L462 - L464 were not covered by tests
}
// Save deviant clusters
util::save_clusters(&deviant_clusters, oldpath)?;
(deviant_clusters.len(), before, after)
Expand All @@ -461,6 +472,68 @@ fn update_clusters(
Ok((added, duplicates, deduplicated, result, before, after))
}

/// Try to merge new clusters to old clusters
///
/// # Arguments
///
/// * `olds` - list of old clusters represented as `HashMap` of `Cluster`
///
/// * `news` - list of new clusters represented as `HashMap` of `Cluster`
///
/// * `dir` - out directory
///
/// * `dedup` - deduplicate crashline, if true
///
/// # Return value
///
/// Number of removed by crashline deduplication CASR reports
pub fn merge_clusters(
olds: &mut HashMap<usize, Cluster>,
news: &mut HashMap<usize, Cluster>,
dir: &Path,
dedup: bool,
) -> Result<usize> {
let mut duplicate = 0usize;
for old in olds.values_mut() {
let mut merged = Vec::new();
for new in news.values() {
if !old.may_merge(new) {
continue;
}

Check warning on line 502 in casr/src/bin/casr-cluster.rs

View check run for this annotation

Codecov / codecov/patch

casr/src/bin/casr-cluster.rs#L490-L502

Added lines #L490 - L502 were not covered by tests
// Copy casreps from new to old
for (casrep, stacktrace, crashline) in new.reports() {

Check warning on line 504 in casr/src/bin/casr-cluster.rs

View check run for this annotation

Codecov / codecov/patch

casr/src/bin/casr-cluster.rs#L504

Added line #L504 was not covered by tests
// Update cluster (and dedup crashline)
if !old.insert(
casrep.to_path_buf(),
stacktrace.to_vec(),
crashline.to_string(),
dedup,
) {
duplicate += 1;
continue;
}
// Save report
fs::copy(
&casrep,
format!(
"{}/cl{}/{}",
&dir.display(),
old.number,
&casrep.file_name().unwrap().to_str().unwrap()
),
)?;
}

Check warning on line 525 in casr/src/bin/casr-cluster.rs

View check run for this annotation

Codecov / codecov/patch

casr/src/bin/casr-cluster.rs#L506-L525

Added lines #L506 - L525 were not covered by tests
// Mark merged cluster for drop
merged.push(new.number);

Check warning on line 527 in casr/src/bin/casr-cluster.rs

View check run for this annotation

Codecov / codecov/patch

casr/src/bin/casr-cluster.rs#L527

Added line #L527 was not covered by tests
}
// Drop marked cluster
for number in merged {
news.remove(&number);
}
}
Ok(duplicate)
}

Check warning on line 535 in casr/src/bin/casr-cluster.rs

View check run for this annotation

Codecov / codecov/patch

casr/src/bin/casr-cluster.rs#L530-L535

Added lines #L530 - L535 were not covered by tests

/// Calculate silhouette coefficient
///
/// # Arguments
Expand Down
46 changes: 40 additions & 6 deletions libcasr/src/stacktrace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ pub struct Cluster {
/// Cluster diameter
diam: Option<f64>,
/// Cluster report crashlines
crashlines: HashSet<String>,
crashlines: HashMap<String, usize>,
}

impl Cluster {
Expand All @@ -96,8 +96,10 @@ impl Cluster {
stacktraces: Vec<Stacktrace>,
crashlines: Vec<String>,
) -> Self {
let mut unique_crashlines: HashSet<String> = HashSet::new();
unique_crashlines.extend(crashlines);
let mut unique_crashlines: HashMap<String, usize> = HashMap::new();
for (i, crashline) in crashlines.iter().enumerate().take(crashlines.len()) {
unique_crashlines.insert(crashline.clone(), i);
}
Cluster {
number,
paths,
Expand Down Expand Up @@ -135,12 +137,14 @@ impl Cluster {
crashline: String,
dedup: bool,
) -> bool {
if dedup && !crashline.is_empty() && !self.crashlines.insert(crashline.to_string()) {
if dedup && !crashline.is_empty() && self.crashlines.contains_key(&crashline) {
return false;

Check warning on line 141 in libcasr/src/stacktrace.rs

View check run for this annotation

Codecov / codecov/patch

libcasr/src/stacktrace.rs#L141

Added line #L141 was not covered by tests
}
self.paths.push(path);
self.stacktraces.push(stacktrace);
self.diam = None;
self.crashlines
.insert(crashline.to_string(), self.paths.len());
true
}
/// Get cluster diameter
Expand Down Expand Up @@ -204,10 +208,40 @@ impl Cluster {
Relation::Outer(rel)
}
}
/// Check if cluster may be merged with another one
pub fn may_merge(&self, cluster: &Cluster) -> bool {
let mut stacktraces1 = self.stacktraces.clone();
let mut stacktraces2 = cluster.stacktraces().clone();
stacktraces1.append(&mut stacktraces2);
diam(&stacktraces1) < THRESHOLD
}

Check warning on line 217 in libcasr/src/stacktrace.rs

View check run for this annotation

Codecov / codecov/patch

libcasr/src/stacktrace.rs#L212-L217

Added lines #L212 - L217 were not covered by tests
// TODO: change type
/// Convert cluster to iterator
pub fn reports(&self) -> Vec<(PathBuf, Stacktrace, String)> {
let mut reports: Vec<(PathBuf, Stacktrace, String)> = Vec::new();
let mut crashlines = self.crashlines.clone();
for i in 0..self.paths.len() {

Check warning on line 223 in libcasr/src/stacktrace.rs

View check run for this annotation

Codecov / codecov/patch

libcasr/src/stacktrace.rs#L220-L223

Added lines #L220 - L223 were not covered by tests
// Get crashline for cur casrep
let mut crashline = String::new();
for (line, &number) in &crashlines {
if number == i {
crashline = line.to_string();
break;
}

Check warning on line 230 in libcasr/src/stacktrace.rs

View check run for this annotation

Codecov / codecov/patch

libcasr/src/stacktrace.rs#L225-L230

Added lines #L225 - L230 were not covered by tests
}
// Drop cur crashline from crashlines
crashlines.remove(&crashline);
// Update results
reports.push((
self.paths[i].clone(),
self.stacktraces[i].clone(),
crashline,
));

Check warning on line 239 in libcasr/src/stacktrace.rs

View check run for this annotation

Codecov / codecov/patch

libcasr/src/stacktrace.rs#L233-L239

Added lines #L233 - L239 were not covered by tests
}
reports
}

Check warning on line 242 in libcasr/src/stacktrace.rs

View check run for this annotation

Codecov / codecov/patch

libcasr/src/stacktrace.rs#L241-L242

Added lines #L241 - L242 were not covered by tests
}

// TODO: Write a better description...
// NOTE: It's just interlayer between `Cluster` and `cluster_stacktrace` fn
/// Generate clusters from CASR report info
///
/// # Arguments
Expand Down

0 comments on commit 6b0eb62

Please sign in to comment.