From 16fc4e131c1206726831394b024c45c57357e70f Mon Sep 17 00:00:00 2001 From: digimer Date: Wed, 18 Jan 2023 22:53:15 -0500 Subject: [PATCH] * Fixed a bug where, if a specific request to do a DB resync was made but the active_uuid wasn't matching the host, it wouldn't resync. This broke peering Strikers when the peer source was not the active_uuid. * Updated anvil-manage-dr to check and delete duplicate dr_link entries. Signed-off-by: digimer --- Anvil/Tools/Database.pm | 9 ++-- tools/anvil-manage-dr | 96 ++++++++++++++++++++++++++++++++++++++ tools/striker-manage-peers | 22 ++++----- 3 files changed, 112 insertions(+), 15 deletions(-) diff --git a/Anvil/Tools/Database.pm b/Anvil/Tools/Database.pm index 505edfcf..0b46e385 100644 --- a/Anvil/Tools/Database.pm +++ b/Anvil/Tools/Database.pm @@ -1327,6 +1327,7 @@ sub connect $anvil->data->{sys}{database}{timestamp} = "" if not defined $anvil->data->{sys}{database}{timestamp}; # We need the host_uuid before we connect. + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "sys::host_uuid" => $anvil->data->{sys}{host_uuid} }}); if (not $anvil->data->{sys}{host_uuid}) { $anvil->data->{sys}{host_uuid} = $anvil->Get->host_uuid({debug => 2}); @@ -2182,9 +2183,9 @@ sub connect "sys::host_uuid" => $anvil->data->{sys}{host_uuid}, check_for_resync => $check_for_resync, }}); - if (($anvil->data->{sys}{database}{connections} > 1) && - ($anvil->data->{sys}{database}{active_uuid} eq $anvil->data->{sys}{host_uuid}) && - ($check_for_resync)) + if (($anvil->data->{sys}{database}{connections} > 1) && + (($anvil->data->{sys}{database}{active_uuid} eq $anvil->data->{sys}{host_uuid}) or + ($check_for_resync))) { $anvil->Database->_find_behind_databases({ debug => $debug, @@ -17597,7 +17598,7 @@ sub write { $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0090", variables => { query => (not $secure) ? $query : $anvil->Log->is_secure($query), - server => $say_server, + server => $say_server." (".$uuid.")", db_error => $DBI::errstr, }}); if (($count) or ($transaction)) diff --git a/tools/anvil-manage-dr b/tools/anvil-manage-dr index 0f8afe67..762d56ce 100755 --- a/tools/anvil-manage-dr +++ b/tools/anvil-manage-dr @@ -94,6 +94,102 @@ sub sanity_check anvil_uuid => $anvil_uuid, }}); + # Somehow, duplicate entries are being created in dr_links. Look for and purge them. + if (1) + { + if (exists $anvil->data->{dr_links}) + { + delete $anvil->data->{dr_links}; + } + my $query = " +SELECT + dr_link_uuid, + dr_link_host_uuid, + dr_link_anvil_uuid, + dr_link_note +FROM + dr_links +ORDER BY + modified_date DESC;"; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); + my $results = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__}); + my $count = @{$results}; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + results => $results, + count => $count, + }}); + foreach my $row (@{$results}) + { + my $dr_link_uuid = $row->[0]; + my $dr_link_host_uuid = $row->[1]; + my $dr_link_anvil_uuid = $row->[2]; + my $dr_link_note = $row->[3]; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + dr_link_uuid => $dr_link_uuid, + dr_link_host_uuid => $dr_link_host_uuid, + dr_link_anvil_uuid => $dr_link_anvil_uuid, + dr_link_note => $dr_link_note, + }}); + + if (exists $anvil->data->{dr_links}{host_uuid}{$dr_link_host_uuid}{$dr_link_anvil_uuid}{dr_link_note}) + { + # Duplicate! + my $previous_note = $anvil->data->{dr_links}{host_uuid}{$dr_link_host_uuid}{$dr_link_anvil_uuid}{dr_link_note}; + my $this_note = $dr_link_note; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + previous_note => $previous_note, + this_note => $this_note, + }}); + + # If the previous note was "DELETED", delete it. Otherwise we'll delete this one. + if ($previous_note eq "DELETED") + { + # Delete the previous one. + my $old_dr_link_uuid = $anvil->data->{dr_links}{host_uuid}{$dr_link_host_uuid}{$dr_link_anvil_uuid}{dr_link_uuid}; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { old_dr_link_uuid => $old_dr_link_uuid }}); + + my $queries = []; + push @{$queries}, "DELETE FROM history.dr_links WHERE dr_link_uuid = ".$anvil->Database->quote($old_dr_link_uuid).";"; + push @{$queries}, "DELETE FROM dr_links WHERE dr_link_uuid = ".$anvil->Database->quote($old_dr_link_uuid).";"; + foreach my $query (@{$queries}) + { + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); + } + $anvil->Database->write({query => $queries, source => $THIS_FILE, line => __LINE__}); + + # Update the local record to store this one. + $anvil->data->{dr_links}{host_uuid}{$dr_link_host_uuid}{$dr_link_anvil_uuid}{dr_link_uuid} = $dr_link_uuid; + $anvil->data->{dr_links}{host_uuid}{$dr_link_host_uuid}{$dr_link_anvil_uuid}{dr_link_note} = $dr_link_note; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + "dr_links::host_uuid::${dr_link_host_uuid}::${dr_link_anvil_uuid}::dr_link_uuid" => $anvil->data->{dr_links}{host_uuid}{$dr_link_host_uuid}{$dr_link_anvil_uuid}{dr_link_uuid}, + "dr_links::host_uuid::${dr_link_host_uuid}::${dr_link_anvil_uuid}::dr_link_note" => $anvil->data->{dr_links}{host_uuid}{$dr_link_host_uuid}{$dr_link_anvil_uuid}{dr_link_note}, + }}); + } + else + { + # Delete this one. + my $queries = []; + push @{$queries}, "DELETE FROM history.dr_links WHERE dr_link_uuid = ".$anvil->Database->quote($dr_link_uuid).";"; + push @{$queries}, "DELETE FROM dr_links WHERE dr_link_uuid = ".$anvil->Database->quote($dr_link_uuid).";"; + foreach my $query (@{$queries}) + { + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); + } + $anvil->Database->write({query => $queries, source => $THIS_FILE, line => __LINE__}); + } + } + else + { + $anvil->data->{dr_links}{host_uuid}{$dr_link_host_uuid}{$dr_link_anvil_uuid}{dr_link_uuid} = $dr_link_uuid; + $anvil->data->{dr_links}{host_uuid}{$dr_link_host_uuid}{$dr_link_anvil_uuid}{dr_link_note} = $dr_link_note; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { + "dr_links::host_uuid::${dr_link_host_uuid}::${dr_link_anvil_uuid}::dr_link_uuid" => $anvil->data->{dr_links}{host_uuid}{$dr_link_host_uuid}{$dr_link_anvil_uuid}{dr_link_uuid}, + "dr_links::host_uuid::${dr_link_host_uuid}::${dr_link_anvil_uuid}::dr_link_note" => $anvil->data->{dr_links}{host_uuid}{$dr_link_host_uuid}{$dr_link_anvil_uuid}{dr_link_note}, + }}); + } + } + } + # If we're (dis}connecting, is the server being protected in the first place? if (($anvil->data->{switches}{'connect'}) or ($anvil->data->{switches}{'disconnect'})) { diff --git a/tools/striker-manage-peers b/tools/striker-manage-peers index a7a862df..5322c51b 100755 --- a/tools/striker-manage-peers +++ b/tools/striker-manage-peers @@ -41,17 +41,14 @@ $| = 1; my $anvil = Anvil::Tools->new(); # Read switches -$anvil->data->{switches}{list} = ""; -$anvil->data->{switches}{add} = 0; -$anvil->data->{switches}{remove} = 0; -$anvil->data->{switches}{'job-uuid'} = ""; -$anvil->data->{switches}{'host-uuid'} = ""; -$anvil->data->{switches}{'host'} = ""; -$anvil->data->{switches}{'port'} = 5432; -$anvil->data->{switches}{'password-file'} = ""; -$anvil->data->{switches}{'ping'} = 0; -$anvil->Get->switches; +$anvil->Get->switches({list => ["add", "list", "remove", "host", "host-uuid", "job-uuid", "port", "password-file", "ping"], man => $THIS_FILE}); +$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => $anvil->data->{switches}}); $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, secure => 0, key => "log_0115", variables => { program => $THIS_FILE }}); +if ($anvil->data->{switches}{'port'} eq "") +{ + $anvil->data->{switches}{'port'} = 5432; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, secure => 1, level => 3, list => { "switches::port" => $anvil->data->{switches}{'port'} }}); +} # Make sure we're running as 'root' # $< == real UID, $> == effective UID @@ -63,7 +60,10 @@ if (($< != 0) && ($> != 0)) } # We'll try to connect in case we're adding additional peers. -$anvil->Database->connect({check_for_resync => 1}); +$anvil->Database->connect({ + debug => 3, + check_for_resync => 1, +}); $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, secure => 0, key => "log_0132"}); # Am I adding, editing or deleting?