* Updated Database->shutdown() to disconnect, stop the postgresql daemon, then reconnect.

* Updated anvil-daemon to not stop a database until both/all DB hosts are in both/all DB's hosts table.

Signed-off-by: Digimer <digimer@alteeve.ca>
main
Digimer 3 years ago
parent 0ebe589c93
commit 7b090e1623
  1. 14
      Anvil/Tools/Database.pm
  2. 1
      share/words.xml
  3. 105
      tools/anvil-daemon

@ -15262,6 +15262,7 @@ sub mark_active
my $pid = $$; my $pid = $$;
my $state_name = "db_in_use::".$uuid."::".$pid; my $state_name = "db_in_use::".$uuid."::".$pid;
my $state_uuid = $anvil->Database->insert_or_update_states({ my $state_uuid = $anvil->Database->insert_or_update_states({
debug => $debug,
state_name => $state_name, state_name => $state_name,
state_host_uuid => $anvil->data->{sys}{host_uuid}, state_host_uuid => $anvil->data->{sys}{host_uuid},
state_note => $value, state_note => $value,
@ -16471,6 +16472,9 @@ sub shutdown
} }
} }
$host_uuid = $anvil->Get->host_uuid;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { host_uuid => $host_uuid }});
# Delete all jobs on our local database, and then stop the DB # Delete all jobs on our local database, and then stop the DB
$query = "DELETE FROM history.jobs; DELETE FROM jobs;"; $query = "DELETE FROM history.jobs; DELETE FROM jobs;";
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "log_0124", variables => { query => $query }}); $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "log_0124", variables => { query => $query }});
@ -16480,6 +16484,7 @@ sub shutdown
my $pid = $$; my $pid = $$;
my $state_name = "db_in_use::".$host_uuid."::".$pid; my $state_name = "db_in_use::".$host_uuid."::".$pid;
my $state_uuid = $anvil->Database->insert_or_update_states({ my $state_uuid = $anvil->Database->insert_or_update_states({
debug => $debug,
state_name => $state_name, state_name => $state_name,
state_host_uuid => $anvil->data->{sys}{host_uuid}, state_host_uuid => $anvil->data->{sys}{host_uuid},
state_note => "0", state_note => "0",
@ -16492,8 +16497,9 @@ sub shutdown
# Close our own connection. # Close our own connection.
$anvil->Database->locking({debug => $debug, release => 1}); $anvil->Database->locking({debug => $debug, release => 1});
$anvil->data->{cache}{database_handle}{$host_uuid}->disconnect;
delete $anvil->data->{cache}{database_handle}{$host_uuid}; # Disconnect from all databases and then stop the daemon, then reconnect.
$anvil->Database->disconnect({debug => $debug});
# Stop the daemon. # Stop the daemon.
my $return_code = $anvil->System->stop_daemon({daemon => $anvil->data->{sys}{daemon}{postgresql}}); my $return_code = $anvil->System->stop_daemon({daemon => $anvil->data->{sys}{daemon}{postgresql}});
@ -16504,6 +16510,10 @@ sub shutdown
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "log_0660"}); $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "log_0660"});
} }
# Reconnect
$anvil->refresh();
$anvil->Database->connect({debug => $debug});
return(0); return(0);
} }

@ -3131,6 +3131,7 @@ We will sleep a bit and try again.
<key name="warning_0140">[ Warning ] - A no-longer active PID: [#!variable!pid!#] had marked our database as "in_use", but the PID is gone now. Reaping the flag.</key> <key name="warning_0140">[ Warning ] - A no-longer active PID: [#!variable!pid!#] had marked our database as "in_use", but the PID is gone now. Reaping the flag.</key>
<key name="warning_0141">[ Warning ] - We waited for: [#!variable!wait_time!#] seconds for all users of the local database to exit. Giving up waiting and taking the database down now.</key> <key name="warning_0141">[ Warning ] - We waited for: [#!variable!wait_time!#] seconds for all users of the local database to exit. Giving up waiting and taking the database down now.</key>
<key name="warning_0142">[ Warning ] - The command: [#!variable!command!#] is still using our database.</key> <key name="warning_0142">[ Warning ] - The command: [#!variable!command!#] is still using our database.</key>
<key name="warning_0143">[ Warning ] - While evaluating database shutdown, the host UUID: [#!variable!host_uuid!#] was not yet found in the database on host: [#!variable!db_uuid!#]. DB shutdown will not happen until all hosts are in all DBs.</key>
<!-- The entries below here are not sequential, but use a key to find the entry. --> <!-- The entries below here are not sequential, but use a key to find the entry. -->
<!-- Run 'striker-parse-os-list to find new entries. --> <!-- Run 'striker-parse-os-list to find new entries. -->

@ -250,7 +250,7 @@ while(1)
check_ram($anvil); check_ram($anvil);
# Disconnect from the database(s) and sleep now. # Disconnect from the database(s) and sleep now.
$anvil->Database->disconnect(); $anvil->Database->disconnect({debug => 2});
sleep(2); sleep(2);
} }
@ -621,71 +621,76 @@ sub handle_periodic_tasks
host_uuid => $host_uuid, host_uuid => $host_uuid,
}}); }});
# Are we a Striker and is there two or more connections? If so, evaluate if we should shut down our # Are we a Striker and is there two or more connections? If so, evaluate if we should shut
# database. # down our database.
if ($host_type eq "striker") if ($host_type eq "striker")
{ {
if ($anvil->data->{sys}{database}{connections} > 1) if ($anvil->data->{sys}{database}{connections} > 1)
{ {
# Sort by UUID, skip the first, and see if we're one of the others. # Make sure that all active databases are in the host's table. If they're
my $first_uuid = ""; # not, we're still early in setup. To do this, we create an array of hosts
# and then query both/all DBs to ensure they all have all hosts.
my $all_in_hosts = 1;
my $db_hosts = [];
foreach my $uuid (sort {$a cmp $b} keys %{$anvil->data->{cache}{database_handle}}) foreach my $uuid (sort {$a cmp $b} keys %{$anvil->data->{cache}{database_handle}})
{ {
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { uuid => $uuid }}); push @{$db_hosts}, $uuid;
if (not $first_uuid) }
{ foreach my $db_uuid (@{$db_hosts})
$first_uuid = $uuid; {
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { first_uuid => $first_uuid }}); my $query = "SELECT COUNT(*) FROM hosts WHERE host_uuid = ".$anvil->Database->quote($db_uuid).";";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
# Skip the first UUID so it doesn't evaluate for shutdown. 's1:db_uuid' => $db_uuid,
next; 's2:query' => $query,
} }});
elsif ($uuid eq $host_uuid) foreach my $host_uuid (@{$db_hosts})
{ {
# This won't return until we're down. my $count = $anvil->Database->query({debug => 2, uuid => $db_uuid, query => $query, source => $THIS_FILE, line => __LINE__})->[0]->[0];
$anvil->Database->shutdown({debug => 2}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
=cut 's1:host_uuid' => $host_uuid,
### TODO: We need to have a way to tell clients to disconnect 's2:db_uuid' => $db_uuid,
### and then shutdown cleanly. This "Wait for an hour" 's2:count' => $count,
### is a kludge. }});
# This is us, Have we been up for at least an hour? if (not $count)
my $uptime = $anvil->Get->uptime();
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { uptime => $uptime }});
if ($uptime > 3600)
{ {
# backup and shut down. $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "warning_0143", variables => {
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "log_0659"}); db_uuid => $db_uuid,
host_uuid => $host_uuid,
# Switch the read_uuid and then close
$anvil->data->{sys}{database}{read_uuid} = $first_uuid;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => {
"sys::database::read_uuid" => $anvil->data->{sys}{database}{read_uuid},
}}); }});
# Disconnect $all_in_hosts = 0;
$anvil->data->{cache}{database_handle}{$uuid}->disconnect; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { all_in_hosts => $all_in_hosts }});
delete $anvil->data->{cache}{database_handle}{$uuid}; }
}
# Create a backup, this is useful also for setting }
# the mtime of the last time we were up.
my $dump_file = $anvil->Database->backup_database({debug => 3}); # Sort by UUID, skip the first, and see if we're one of the others.
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { dump_file => $dump_file }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { all_in_hosts => $all_in_hosts }});
if ($all_in_hosts)
{
my $first_uuid = "";
foreach my $uuid (sort {$a cmp $b} keys %{$anvil->data->{cache}{database_handle}})
{
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { uuid => $uuid }});
if (not $first_uuid)
{
$first_uuid = $uuid;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { first_uuid => $first_uuid }});
# Stop the daemon # Skip the first UUID so it doesn't evaluate for
my $return_code = $anvil->System->stop_daemon({daemon => $anvil->data->{sys}{daemon}{postgresql}}); # shutdown.
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { return_code => $return_code }}); next;
if ($return_code eq "0") }
{ elsif ($uuid eq $host_uuid)
# Stopped the daemon. {
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "log_0660"}); # This won't return until we're down.
} $anvil->Database->shutdown({debug => 2});
} }
=cut
} }
} }
} }
# If we're the active database, dump out database out and rsync it to our peers. # If we're the active database, dump our database out and rsync it to our peers.
my $peers = keys %{$anvil->data->{database}}; my $peers = keys %{$anvil->data->{database}};
my $connections = $anvil->data->{sys}{database}{connections}; my $connections = $anvil->data->{sys}{database}{connections};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {

Loading…
Cancel
Save