diff --git a/scripts/Util.pm b/scripts/Util.pm index 09f2442..49bc845 100644 --- a/scripts/Util.pm +++ b/scripts/Util.pm @@ -8,6 +8,9 @@ use DateTime; use feature 'say'; +my $local_root = '/home/christoph/Notes/TU/MastersThesis/FailNix'; +my $local_archive_dir = "$local_root/injections"; + my $ntfy_url = 'https://ntfy.vps.chriphost.de'; my $ntfy_token = 'tk_rx8fd6hojuz4ekcb72j7juugkbmga'; # May be public my $ntfy_topic = 'fail-alerts'; @@ -187,4 +190,77 @@ sub get_section_name { return $name; } +sub read_experiment_info { + my ($exp) = @_; + + return unless ( -f "$local_archive_dir/$exp/0.info" ); + + open( my $fhandle, '<', "$local_archive_dir/$exp/0.info" ) + or die "Failed to open 0.info: $!"; + my $info = <$fhandle>; + chomp $info; + close($fhandle); + + return $info; +} + +sub read_marker_info { + my ( $experiment, $benchmark, $address ) = @_; + + return "" + unless ( + -f "$local_archive_dir/$experiment/markers/$benchmark-$address.info" ); + + open( my $fhandle, '<', + "$local_archive_dir/$experiment/markers/$benchmark-$address.info" ) + or die "Failed to open $benchmark-$address.info: $!"; + my $info = <$fhandle>; + chomp $info; + close($fhandle); + + return $info; +} + +sub overwrite_marker_info { + my ( $experiment, $benchmark, $address, $info ) = @_; + + system( 'mkdir', '-p', "$local_archive_dir/$experiment/markers" ); + + open( my $fhandle, '>', + "$local_archive_dir/$experiment/markers/$benchmark-$address.info" ) + or die "Failed to open $benchmark-$address.info: $!"; + print $fhandle $info; + close($fhandle); +} + +sub delete_marker_info { + my ( $experiment, $benchmark, $address ) = @_; + + system( 'rm', + "$local_archive_dir/$experiment/markers/$benchmark-$address.info" ); +} + +sub select_experiment { + my ($multi) = @_; + + my @experiments = find_subdirs($local_archive_dir); + + my @exp_with_notes; + foreach my $exp (@experiments) { + my $info = read_experiment_info($exp); + + push @exp_with_notes, + defined $info ? sprintf( "%-50s (Note: %s)", $exp, $info ) : $exp; + } + + my @selected_experiments = + TUI::select_from_list( "Select Archived Experiment to Open", + $multi, @exp_with_notes ); + die "No experiment selected" unless @selected_experiments; + + map { s/(.*?)\s+\(Note:.+\)$/$1/ } @selected_experiments; + + return $multi == 1 ? @selected_experiments : $selected_experiments[0]; +} + 1; diff --git a/scripts/explore.pl b/scripts/explore.pl index a30d1bb..b9be773 100644 --- a/scripts/explore.pl +++ b/scripts/explore.pl @@ -21,12 +21,7 @@ my $local_root = '/home/christoph/Notes/TU/MastersThesis/FailNix'; my $local_archive_dir = "$local_root/injections"; # Select experiment to open -my @experiments = Util::find_subdirs($local_archive_dir); -my @selected_experiments = - TUI::select_from_list( "Select Archived Experiment to Open", 0, - @experiments ); -die "No experiment selected" unless @selected_experiments; -my $selected_experiment = $selected_experiments[0]; +my $selected_experiment = Util::select_experiment(0); my $cui = TUI::init_cui(); @@ -75,6 +70,25 @@ my %index_of_markers; my $selected_threshold = 0; +my @sections; + +sub marker_label { + my ($marker) = @_; + + return sprintf( + "%4s %8s %5s %17s %12sx %-40s", + $marker->{benchmark}, + $marker->{fault_address}, + Util::get_section_name( $marker->{fault_address}, @sections ), + $marker->{resulttype}, + Util::format_number_sep( $marker->{faults} ), + Util::read_marker_info( + $selected_experiment, $marker->{benchmark}, + $marker->{fault_address} + ), + ); +} + sub load_faults_csv { @marker_values = (); %marker_labels = (); @@ -85,7 +99,7 @@ sub load_faults_csv { headers => 'auto' ); - my @sections = Util::elf_read_sections( + @sections = Util::elf_read_sections( "$local_archive_dir/$selected_experiment/system.elf"); # Result: @@ -95,16 +109,7 @@ sub load_faults_csv { @marker_values = @$data; @filtered_marker_values = @marker_values; %marker_labels = - map { - $_ => sprintf( - "%5s %10s %10s %20s %15sx", - $_->{benchmark}, - $_->{fault_address}, - Util::get_section_name( $_->{fault_address}, @sections ), - $_->{resulttype}, - Util::format_number_sep( $_->{faults} ), - ); - } @marker_values; + map { $_ => marker_label($_); } @marker_values; } sub filter_marker_values { @@ -360,7 +365,7 @@ $win->add( 'info', 'Label', -y => -1, -text => -"Space = toggle, F = filter markers, S = open source, A = open assembly, R = resize, Q = quit", +"Space = toggle, F = filter markers, S = open source, A = open assembly, N = edit notes, R = resize, Q = quit", ); sub set_geometry { @@ -465,6 +470,7 @@ sub markers_filter_popup { -title => "By Count Threshold", -border => 1, -text => $selected_threshold, + -pos => length($selected_threshold), -regexp => '/^\d*$/', ); @@ -533,6 +539,79 @@ sub markers_filter_popup { $focus->(); } +# ============================================================================= +# Notes Popup +# ============================================================================= + +sub edit_notes_popup { + my $w = 60; + my $h = 24; + + my $marker = $markers_panel->get_active_value(); + my $marker_text = + Util::read_marker_info( $selected_experiment, $marker->{benchmark}, + $marker->{fault_address} ); + + my $popup = $cui->add( + 'popup', 'Window', + -x => int( $cui->width() / 2 - $w / 2 ), + -y => int( $cui->height() / 2 - $h / 2 ), + -width => $w, + -height => $h, + -border => 1, + -title => "Edit Notes", + ); + + my $notes = $popup->add( + 'marker_notes', + 'TextEditor', + -height => $h - 3, + -border => 1, + -text => $marker_text, + -pos => length($marker_text), + ); + + $popup->add( + 'popup_info', 'Label', + -y => -1, + -text => "^S/^C = save, ^Q = quit", + ); + + $popup->set_binding( + sub { + my $text = $notes->get(); + + if ( length($text) > 0 ) { + Util::overwrite_marker_info( $selected_experiment, + $marker->{benchmark}, $marker->{fault_address}, $text, ); + } + else { + Util::delete_marker_info( $selected_experiment, + $marker->{benchmark}, $marker->{fault_address} ); + } + + $marker_labels{$marker} = marker_label($marker); + + $cui->delete('popup'); + $cui->layout(); + $markers_panel->draw(); + }, + "\cS", + "\cC", + ); + + $popup->set_binding( + sub { + $cui->delete('popup'); + $cui->layout(); + }, + "\cQ" + ); + + $cui->layout(); + $notes->focus(); +} + # ============================================================================= # Bindings # ============================================================================= @@ -544,6 +623,13 @@ $win->set_binding( 'f', ); +$win->set_binding( + sub { + edit_notes_popup(); + }, + 'n', +); + $win->set_binding( sub { layout_resize(); diff --git a/scripts/menu.pl b/scripts/menu.pl index 15fdbad..e647b5e 100644 --- a/scripts/menu.pl +++ b/scripts/menu.pl @@ -68,6 +68,9 @@ my %handlers = ( Mars::download_dir( "$remote_builds_dir/$_", "$local_archive_dir/" . $_ =~ s/:/-/gr ) for @selected_dirs; + + system( 'touch', "$local_archive_dir/" . $_ =~ s/:/-/gr . "/0.info" ) + for @selected_dirs; }, '04. Query Databases (Mars)' => sub { @@ -213,12 +216,7 @@ my %handlers = ( }, '12. Open Experiment in Binsider' => sub { - my @experiments = Util::find_subdirs($local_archive_dir); - my @selected_experiments = - TUI::select_from_list( "Select Experiments to Open in Binsider", - 0, @experiments ); - die "No experiment selected" unless @selected_experiments; - my $selected_experiment = $selected_experiments[0]; + my $selected_experiment = Util::select_experiment(0); system( 'binsider', "$local_archive_dir/$selected_experiment/system.elf" ); @@ -242,22 +240,7 @@ my %handlers = ( '14. Compare Experiment Results' => sub { - # TODO: To util function (select_experiments, - # could also include the file-existance filter) - my @experiments = Util::find_subdirs($local_archive_dir); - - # Only include experiments with resultsdata.csv - my @viable_experiments; - foreach my $experiment (@experiments) { - push @viable_experiments, $experiment - if ( -f "$local_archive_dir/$experiment/resultsdata.csv" ); - } - - # Select experiments - my @selected_experiments = - TUI::select_from_list( "Select Experiments to Compare", - 1, @viable_experiments ); - die "No experiments selected" unless @selected_experiments; + my @selected_experiments = Util::select_experiment(1); # Read results my %all_results; @@ -283,12 +266,15 @@ my %handlers = ( 'ACCESS_OUTERSPACE' ); - my $heading = sprintf( "%5s %20s ", "BENCH", "TYPE" ); + my $heading = sprintf( "%5s %20s ", "BENCH", "TYPE" ); + my $subheading = sprintf( "%5s %20s ", "", "" ); foreach my $experiment (@selected_experiments) { $heading .= sprintf( "%50s ", $experiment ); + $subheading .= + sprintf( "%50s ", Util::read_experiment_info($experiment) ); } - my @entries = ( $heading, "" ); + my @entries = ( $heading, $subheading, "" ); foreach my $benchmark (@benchs) { foreach my $marker (@markers) { my $entry = sprintf( "%5s %20s ", $benchmark, $marker );