Add fspgroup repair action to menu

This commit is contained in:
2026-09-01 00:35:55 +02:00
parent 00383e15fe
commit 09c821b8ee
2 changed files with 142 additions and 0 deletions
+12
View File
@@ -166,6 +166,18 @@ sub db_do {
$db->do(@cmd) or die "Database command failed (@cmd): " . $db->errstr;
}
# db_do only reports affected rows, this one also reads the value back
sub db_selectrow {
my (@cmd) = @_;
my $db = db_connect();
my @row = $db->selectrow_array(@cmd);
die "Database query failed (@cmd): " . $db->errstr if $db->err;
return @row;
}
sub db_create {
my ($db_name) = @_;
say " - Creating database $db_name...";
+130
View File
@@ -848,6 +848,136 @@ my %handlers = (
'<', Util::shell_quote($dump_file) );
},
'33. Repair fspgroup Write Groups (Mars)' => sub {
# Retroactively fixes (hopefully) the missing equivalence class
# mappings (EC <-> Pilot) the BasicPruner misses (because it maps
# multiple classes to a single pilot, but uses the pilot as the
# primary key)
my @dbs = Mars::db_list();
my @dbs_with_notes;
foreach my $db (@dbs) {
my $info =
Util::read_experiment_info( $db =~ s/smchurla_//r =~ s/:/-/gr );
push @dbs_with_notes,
( defined $info && length($info) > 0 )
? sprintf( "%-60s (%s)", $db, $info )
: $db;
}
my @selected_dbs = TUI::select_from_list( "Select Databases to Repair",
1, @dbs_with_notes );
die "No database selected" unless @selected_dbs;
@selected_dbs =
map { s/(.*?)\s+\(.+\)$/$1/r } @selected_dbs;
# The PRIMARY KEY gets dropped by the repair and replaced with a KEY.
# To not run this shit on already repaired DBs, check for the PRIMARY
# index as a determinant
my $index_exists = sub {
my ($index) = @_;
my ($count) = Mars::db_selectrow(
"SELECT COUNT(*) FROM information_schema.STATISTICS
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'fspgroup'
AND INDEX_NAME = '$index'"
);
return $count;
};
foreach my $db (@selected_dbs) {
say "Repairing $db...";
# Select the DB so index_exists works
Mars::db_do("use `$db`");
# Update the variant names, so the queries still work
my $expected_variant = $db =~ s/^smchurla_//r;
my ($variant_count) =
Mars::db_selectrow("SELECT COUNT(DISTINCT variant) FROM variant");
my ($current_variant) =
Mars::db_selectrow("SELECT DISTINCT variant FROM variant");
if ( !defined $variant_count || $variant_count != 1 ) {
say " - WARNING: $variant_count distinct variants!";
}
elsif ( $current_variant ne $expected_variant ) {
say " - Variant is '$current_variant' but queries look up"
. " '$expected_variant' (from the database name), renaming...";
Mars::db_do("UPDATE variant SET variant = '$expected_variant'");
}
# Drop the primary key
if ( $index_exists->('PRIMARY') ) {
say " - Dropping PRIMARY KEY (pilot_id)...";
Mars::db_do("ALTER TABLE fspgroup DROP PRIMARY KEY");
}
# Add an index for the columns we actually join on (mostly)
unless ( $index_exists->('eq_class') ) {
say " - Adding eq_class index...";
Mars::db_do(
"ALTER TABLE fspgroup
ADD KEY eq_class (variant_id, instr2, data_physical_address)"
);
}
# I'm currently only using BasicPruner, but don't touch other
# pruning methods for now, for safety
my ($fspmethod_id) =
Mars::db_selectrow(
"SELECT id FROM fspmethod WHERE method = 'basic'");
die "No 'basic' fspmethod in $db" unless defined $fspmethod_id;
# The first row succeeded before the duplicate key error, remove it
Mars::db_do(
"DELETE g
FROM fspgroup g
JOIN fsppilot p ON p.id = g.pilot_id
WHERE p.known_outcome = 1 AND p.fspmethod_id = $fspmethod_id"
);
my ($expected) =
Mars::db_selectrow(
"SELECT COUNT(*) FROM trace WHERE accesstype = 'W'");
# Query from BasicPruner.cc, now ran against the updated DB
say " - Inserting $expected write groups...";
Mars::db_do(
"INSERT INTO
fspgroup (variant_id, instr2, data_physical_address, bit_pos, fspmethod_id, pilot_id)
SELECT STRAIGHT_JOIN t.variant_id, t.instr2, t.data_physical_address, p.bit_pos, p.fspmethod_id, p.id
FROM fsppilot p
JOIN trace t
ON t.variant_id = p.variant_id AND p.fspmethod_id = $fspmethod_id AND p.known_outcome = 1
WHERE t.accesstype = 'W'"
);
# We expect one row per write group/EC.
# Otherwise no idea what's going on :O
my ($actual) = Mars::db_selectrow(
"SELECT COUNT(*)
FROM fspgroup g
JOIN fsppilot p ON p.id = g.pilot_id
WHERE p.known_outcome = 1 AND p.fspmethod_id = $fspmethod_id"
);
if ( $actual == $expected ) {
say " - OK: $actual write groups match the write ECs in trace";
}
else {
say " - WARNING: inserted $actual, expected $expected."
. " Check for duplicate known_outcome pilots:"
. " SELECT variant_id, COUNT(*) FROM fsppilot"
. " WHERE known_outcome = 1 GROUP BY variant_id;";
}
}
say "Queries have to be re-run.";
},
'95. Delete Builds' => sub {
# Delete old build files