Generate query and results and charts in separate directory
This commit is contained in:
+25
-12
@@ -17,6 +17,7 @@ use feature 'say';
|
||||
|
||||
my $local_root = '/home/christoph/Notes/TU/MastersThesis/FailNix';
|
||||
my $local_archive_dir = "$local_root/injections";
|
||||
my $local_queries_dir = "$local_root/queries";
|
||||
|
||||
my $ntfy_url = 'https://ntfy.vps.chriphost.de';
|
||||
my $ntfy_token = 'tk_rx8fd6hojuz4ekcb72j7juugkbmga'; # May be public
|
||||
@@ -133,8 +134,8 @@ sub find_subdirs {
|
||||
}
|
||||
|
||||
sub execute_query {
|
||||
my ( $experiment, $queryname, $db_conf, $builds_dir, $do_notify_file,
|
||||
@filter_config_names )
|
||||
my ( $experiment, $queryname, $db_conf, $experiment_dir, $output_dir,
|
||||
$output_prefix, $do_notify_file, @filter_config_names )
|
||||
= @_;
|
||||
|
||||
my $module = "$queryname";
|
||||
@@ -150,7 +151,7 @@ sub execute_query {
|
||||
or die "$module can't postprocess()";
|
||||
|
||||
my $querystring =
|
||||
$query->( $experiment, "$builds_dir/$experiment", @filter_config_names );
|
||||
$query->( $experiment, $experiment_dir, @filter_config_names );
|
||||
my $argsstring = $args->();
|
||||
my $filenamestring = $filename->(@filter_config_names);
|
||||
|
||||
@@ -162,14 +163,16 @@ sub execute_query {
|
||||
|
||||
$postprocess->($result);
|
||||
|
||||
system( 'mkdir', '-p', "$builds_dir/$experiment" );
|
||||
open( my $results_handle, '>', "$builds_dir/$experiment/$filenamestring" )
|
||||
my $resultfile = "$output_dir/${output_prefix}${filenamestring}";
|
||||
|
||||
system( 'mkdir', '-p', $output_dir );
|
||||
open( my $results_handle, '>', $resultfile )
|
||||
or die "failed to open file: $!";
|
||||
print $results_handle $result;
|
||||
close($results_handle) or die "failed to close file: $!";
|
||||
|
||||
if ( defined $do_notify_file and $do_notify_file == 1 ) {
|
||||
notify_file("$builds_dir/$experiment/$filenamestring");
|
||||
notify_file($resultfile);
|
||||
}
|
||||
|
||||
return $result;
|
||||
@@ -359,21 +362,31 @@ sub delete_marker_info {
|
||||
"$local_archive_dir/$experiment/markers/$benchmark-$address.info" );
|
||||
}
|
||||
|
||||
sub pick_data_file {
|
||||
my ( $dir, $prefix ) = @_;
|
||||
sub pick_query_file {
|
||||
my ( $experiment, $prefix ) = @_;
|
||||
|
||||
die "No query directory $local_queries_dir\n"
|
||||
unless -d $local_queries_dir;
|
||||
|
||||
# \Q...\E treats ... as literal string
|
||||
my @files = sort grep { /^\Q$prefix\E.*\.csv$/ } find_files($dir);
|
||||
my @files =
|
||||
sort grep { /^\Q${experiment}_\E\Q$prefix\E.*\.csv$/ }
|
||||
find_files($local_queries_dir);
|
||||
|
||||
die "No $prefix CSV files found in $dir\n" unless @files;
|
||||
return $files[0] if @files == 1;
|
||||
die "No $prefix CSV files found for $experiment in $local_queries_dir\n"
|
||||
unless @files;
|
||||
|
||||
# Strip the experiment prefix
|
||||
my @names = map { s/^\Q${experiment}_\E//r } @files;
|
||||
|
||||
return $names[0] if @names == 1;
|
||||
|
||||
# Make sure the unfiltered file is at the top
|
||||
my @sorted = sort {
|
||||
( $a eq "$prefix.csv" ) ? -1
|
||||
: ( $b eq "$prefix.csv" ) ? 1
|
||||
: $a cmp $b
|
||||
} @files;
|
||||
} @names;
|
||||
|
||||
my @selected =
|
||||
TUI::select_from_list( "Select $prefix CSV file", 0, @sorted );
|
||||
|
||||
+3
-2
@@ -19,12 +19,13 @@ my $local_wamr = '/home/christoph/Notes/TU/MastersThesis/05 WAMR';
|
||||
my $local_newlib = '/home/christoph/Notes/TU/MastersThesis/07 NewLib';
|
||||
my $local_root = '/home/christoph/Notes/TU/MastersThesis/FailNix';
|
||||
my $local_archive_dir = "$local_root/injections";
|
||||
my $local_queries_dir = "$local_root/queries";
|
||||
|
||||
# Select experiment to open
|
||||
my $selected_experiment = Util::select_experiment(0);
|
||||
|
||||
my $selected_faults_csv =
|
||||
Util::pick_data_file( "$local_archive_dir/$selected_experiment", "faults" );
|
||||
Util::pick_query_file( $selected_experiment, "faults" );
|
||||
|
||||
my $cui = TUI::init_cui();
|
||||
|
||||
@@ -98,7 +99,7 @@ sub load_faults_csv {
|
||||
|
||||
# Schema: benchmark, resulttype, faults, fault_address
|
||||
my $data = Text::CSV_XS::csv(
|
||||
in => "$local_archive_dir/$selected_experiment/$selected_faults_csv",
|
||||
in => "$local_queries_dir/${selected_experiment}_$selected_faults_csv",
|
||||
headers => 'auto'
|
||||
);
|
||||
|
||||
|
||||
+55
-33
@@ -27,7 +27,9 @@ my $local_wamr = "$local_root/wamr";
|
||||
my $local_scripts_dir = "$local_root/scripts";
|
||||
my $local_builds_dir = "$local_root/builds";
|
||||
my $local_archive_dir = "$local_root/injections";
|
||||
my $local_queries_dir = "$local_root/queries";
|
||||
my $local_charts_dir = "$local_root/scripts/charts";
|
||||
my $local_charts_out_dir = "$local_root/charts";
|
||||
my $local_ghidra_projects = "$local_root/ghidra";
|
||||
my $local_ghidra_scripts = "$local_root/scripts/ghidra";
|
||||
my $local_dump_dir = "$local_root/dumps";
|
||||
@@ -154,9 +156,12 @@ my %handlers = (
|
||||
? " (" . join( "+", @filter_configs ) . ")"
|
||||
: "";
|
||||
say "Running $query$config_label on $db...";
|
||||
Util::execute_query( $experiment,
|
||||
$query, $local_db_conf, $local_archive_dir, 0,
|
||||
@filter_configs );
|
||||
Util::execute_query(
|
||||
$experiment, $query,
|
||||
$local_db_conf, "$local_archive_dir/$experiment",
|
||||
$local_queries_dir, "${experiment}_",
|
||||
0, @filter_configs
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -195,6 +200,12 @@ my %handlers = (
|
||||
foreach (@selected_dirs) {
|
||||
my $experiment = $_ =~ s/(.*?)\s+\(.+\)$/$1/r;
|
||||
|
||||
my $faults_csv = "$local_queries_dir/${experiment}_faults.csv";
|
||||
unless ( -f $faults_csv ) {
|
||||
say "Skipping $experiment: $faults_csv does not exist";
|
||||
next;
|
||||
}
|
||||
|
||||
say "Creating Ghidra project for $experiment...";
|
||||
system(
|
||||
'ghidra-analyzeHeadless',
|
||||
@@ -205,7 +216,7 @@ my %handlers = (
|
||||
'-postScript', 'DWARFLineInfoSourceMapScript',
|
||||
'-postScript', 'DWARFLineInfoCommentScript',
|
||||
'-postScript', 'ImportMarkersAsBookmarks',
|
||||
"$local_archive_dir/$experiment/faults.csv"
|
||||
$faults_csv
|
||||
);
|
||||
}
|
||||
},
|
||||
@@ -238,19 +249,17 @@ my %handlers = (
|
||||
);
|
||||
|
||||
# Insert results
|
||||
if (
|
||||
-f "$local_archive_dir/$experiment/results_no_native_call_data+no_native_call_instr.txt"
|
||||
)
|
||||
{
|
||||
open( my $fhandle, '<',
|
||||
"$local_archive_dir/$experiment/results_no_native_call_data+no_native_call_instr.txt"
|
||||
) or return;
|
||||
my $results_txt =
|
||||
"$local_queries_dir/${experiment}_results_no_native_call_data+no_native_call_instr.txt";
|
||||
|
||||
if ( -f $results_txt ) {
|
||||
open( my $fhandle, '<', $results_txt ) or return;
|
||||
my $results = join "", <$fhandle>;
|
||||
close($fhandle);
|
||||
|
||||
# Append link to results file
|
||||
system( 'obsidian', 'append', "file=zettel/$experiment",
|
||||
"content=## Results\n\n[Results File](file://$local_archive_dir/$experiment/results_no_native_call_data+no_native_call_instr.txt)\n\n"
|
||||
"content=## Results\n\n[Results File](file://$results_txt)\n\n"
|
||||
);
|
||||
|
||||
# Append results as markdown block
|
||||
@@ -260,8 +269,7 @@ my %handlers = (
|
||||
);
|
||||
}
|
||||
else {
|
||||
say
|
||||
"$local_archive_dir/$experiment/results_no_native_call_data+no_native_call_instr.txt does not exist";
|
||||
say "$results_txt does not exist";
|
||||
}
|
||||
|
||||
# Insert charts
|
||||
@@ -273,9 +281,15 @@ my %handlers = (
|
||||
my $attach_image = sub {
|
||||
my ($name) = @_;
|
||||
|
||||
my $image = "$local_charts_out_dir/${experiment}_$name.svg";
|
||||
|
||||
unless ( -f $image ) {
|
||||
say "$image does not exist";
|
||||
return;
|
||||
}
|
||||
|
||||
system( 'obsidian', 'append', "file=zettel/$experiment",
|
||||
"content=\n"
|
||||
);
|
||||
"content=\n" );
|
||||
};
|
||||
$attach_image->(
|
||||
"single_result_no_native_call_data+no_native_call_instr");
|
||||
@@ -292,8 +306,7 @@ my %handlers = (
|
||||
|
||||
# TODO: Fails silently if not every selected experiment has this datafile
|
||||
my $resultsdata_csv =
|
||||
Util::pick_data_file( "$local_archive_dir/$selected_experiments[0]",
|
||||
"resultsdata" );
|
||||
Util::pick_query_file( $selected_experiments[0], "resultsdata" );
|
||||
|
||||
# Read results
|
||||
my %all_results;
|
||||
@@ -301,7 +314,7 @@ my %handlers = (
|
||||
|
||||
# Schema: benchmark, resulttype, faults
|
||||
my $data = Text::CSV_XS::csv(
|
||||
in => "$local_archive_dir/$experiment/$resultsdata_csv",
|
||||
in => "$local_queries_dir/${experiment}_$resultsdata_csv",
|
||||
headers => 'auto'
|
||||
);
|
||||
|
||||
@@ -365,13 +378,13 @@ my %handlers = (
|
||||
#
|
||||
# # TODO: Fails silently if not every selected experiment has this datafile
|
||||
# my $resultsdata_csv =
|
||||
# Util::pick_data_file( "$local_archive_dir/$baseline", "resultsdata" );
|
||||
# Util::pick_query_file( $baseline, "resultsdata" );
|
||||
#
|
||||
# my %all_results;
|
||||
# foreach my $experiment ( $baseline, @selected_experiments ) {
|
||||
#
|
||||
# my $data = Text::CSV_XS::csv(
|
||||
# in => "$local_archive_dir/$experiment/$resultsdata_csv",
|
||||
# in => "$local_queries_dir/${experiment}_$resultsdata_csv",
|
||||
# headers => 'auto'
|
||||
# );
|
||||
#
|
||||
@@ -728,29 +741,35 @@ my %handlers = (
|
||||
# Select if faults.csv or a filtered variant should be used
|
||||
my $faults_csv;
|
||||
if (@faults_charts) {
|
||||
$faults_csv = Util::pick_data_file(
|
||||
"$local_archive_dir/$selected_experiments[0]", "faults" );
|
||||
$faults_csv =
|
||||
Util::pick_query_file( $selected_experiments[0], "faults" );
|
||||
}
|
||||
|
||||
# Select if resultsdata.csv or a filtered variant should be used
|
||||
my $resultsdata_csv;
|
||||
if (@resultsdata_charts) {
|
||||
$resultsdata_csv = Util::pick_data_file(
|
||||
"$local_archive_dir/$selected_experiments[0]",
|
||||
"resultsdata" );
|
||||
$resultsdata_csv =
|
||||
Util::pick_query_file( $selected_experiments[0], "resultsdata" );
|
||||
}
|
||||
|
||||
# Chart SVGs are written into a separate output directory
|
||||
system( 'mkdir', '-p', $local_charts_out_dir );
|
||||
|
||||
# Plot single-experiment charts
|
||||
# Args: <experiment> <queries_dir> <charts_dir> [<archive_dir>]
|
||||
# [datafile]
|
||||
my @single_charts = grep { /single/ } @selected_charts;
|
||||
foreach my $experiment (@selected_experiments) {
|
||||
foreach my $chart (@single_charts) {
|
||||
say " - Generating plot $chart for $experiment...";
|
||||
my @r_args = (
|
||||
'Rscript',
|
||||
"$local_charts_dir/$chart.r",
|
||||
"$local_archive_dir/$experiment"
|
||||
'Rscript', "$local_charts_dir/$chart.r", $experiment,
|
||||
$local_queries_dir, $local_charts_out_dir
|
||||
);
|
||||
|
||||
# single_heatmap also needs the experiment's system.elf
|
||||
push @r_args, $local_archive_dir if $chart eq 'single_heatmap';
|
||||
|
||||
# If the chart is marked in @faults_charts,
|
||||
# append the $faults_csv to the args
|
||||
push @r_args, $faults_csv
|
||||
@@ -766,15 +785,18 @@ my %handlers = (
|
||||
}
|
||||
}
|
||||
|
||||
# Plot combined charts
|
||||
# Args: <experiment1> ... <experimentN> <queries_dir> <charts_dir>
|
||||
# [datafile]
|
||||
my @combined_charts =
|
||||
grep { /combined/ } @selected_charts;
|
||||
my $print_experiments = join " ", @selected_experiments;
|
||||
my @path_experiments =
|
||||
map { "$local_archive_dir/$_" } @selected_experiments;
|
||||
foreach my $chart (@combined_charts) {
|
||||
say " - Generating plot $chart for ($print_experiments)...";
|
||||
my @r_args =
|
||||
( 'Rscript', "$local_charts_dir/$chart.r", @path_experiments );
|
||||
my @r_args = (
|
||||
'Rscript', "$local_charts_dir/$chart.r", @selected_experiments,
|
||||
$local_queries_dir, $local_charts_out_dir
|
||||
);
|
||||
|
||||
# If the chart is marked in @faults_charts,
|
||||
# append the $faults_csv to the args
|
||||
|
||||
+5
-1
@@ -284,8 +284,12 @@ sub results {
|
||||
# Keep trying even if a single query fails
|
||||
for my $query (@queries) {
|
||||
eval {
|
||||
# Remote results stay in the experiment dir so they are archived
|
||||
my $experiment_dir = "$remote_builds_dir/$experiment";
|
||||
|
||||
Util::execute_query( $experiment, $query,
|
||||
$remote_db_conf, $remote_builds_dir, 1, @configs );
|
||||
$remote_db_conf, $experiment_dir, $experiment_dir, "", 1,
|
||||
@configs );
|
||||
1;
|
||||
} or do {
|
||||
my $error = $@ || 'bullshit error';
|
||||
|
||||
Reference in New Issue
Block a user