Add error NOTIFY when reload fails
authorJoshua Tolley <josh@endpoint.com>
Thu, 10 Apr 2014 17:18:42 +0000 (11:18 -0600)
committerJoshua Tolley <josh@endpoint.com>
Fri, 11 Apr 2014 17:32:23 +0000 (11:32 -0600)
Bucardo.pm
bucardo

index 24a703f5027a3dcd8274ebe57508dd059311b26e..d7a5442184892a42acf4e1c239898e19a5be2ea6 100644 (file)
@@ -986,6 +986,7 @@ sub mcp_main {
             ## Request that a named sync get reloaded
             elsif ($name =~ /^reload_sync_(.+)/o) {
                 my $syncname = $1;
+                my $succeeded = 0;
 
                 ## Skip if the sync does not exist or is inactive
                 if (! exists $sync->{$syncname}) {
@@ -1041,9 +1042,14 @@ sub mcp_main {
                     else {
                         ## Let anyone listening know the sync is now ready
                         $self->db_notify($maindbh, "reloaded_sync_$syncname", 1);
+                        $succeeded = 1;
                     }
                     $maindbh->commit();
+
+                    $self->glog("Succeeded: $succeeded", LOG_WARN);
                 }
+                $self->db_notify($maindbh, "reload_error_sync_$syncname", 1)
+                    if ($succeeded != 1);
             }
 
             ## Request that a named sync get activated
@@ -5941,7 +5947,14 @@ sub validate_sync {
     ## Call validate_sync: checks tables, columns, sets up supporting
     ## schemas, tables, functions, and indexes as needed
 
-    $self->{masterdbh}->do("SELECT validate_sync('$syncname')");
+    eval {
+        local $SIG{__DIE__} = undef;
+        $self->{masterdbh}->do("SELECT validate_sync('$syncname')");
+    };
+    if ($@) {
+        $self->{masterdbh}->rollback;
+        return 0;
+    }
 
     ## Prepare some SQL statements for immediate and future use
     my %SQL;
diff --git a/bucardo b/bucardo
index b865c4d7a40f7cc35d2bc9f4e5adbeb22c5a8cbb..704ca4e1663b4b69c97f0a6f64e2a1fb5dfe8b2d 100755 (executable)
--- a/bucardo
+++ b/bucardo
@@ -912,23 +912,42 @@ sub wait_for_notice {
     ## Keep hanging out until we get the notice we are waiting for
     ## Arguments: three
     ## 1. Database handle
-    ## 2. String to listen for
+    ## 2. String(s) to listen for
     ## 3. How long to wait (default is forever)
     ## Returns: 1
+    ## If the strings argument is an array ref, this will return a hash ref
+    ## where each key is a string we found, and the value is how many times we
+    ## found it. Note that we return as soon as we've found at least one
+    ## matching NOTIFY; we don't wait for the full timeout to see which
+    ## messages show up.
 
     my ($ldbh, $string, $howlong) = @_;
+    my ($num_strings, %search_strings, %matches);
+    my $found = 0;
+    if (ref $string eq 'ARRAY') {
+        $num_strings = scalar @$string;
+        map { $search_strings{$_} = 1 } @$string;
+    }
+    else {
+        $num_strings = 1;
+        $search_strings{$string} = 1;
+    }
 
     my $start_time = [gettimeofday];
 
   WAITIN: {
         for my $notice (@{ db_get_notices($ldbh) }) {
             my ($name) = @$notice;
-            last WAITIN if $name eq $string;
+            if (exists $search_strings{$name}) {
+                $found = 1;
+                $matches{$name}++;
+            }
         }
+        last WAITIN if $found;
 
         if (defined $howlong) {
             my $elapsed = tv_interval( $start_time );
-            return 0 if $elapsed >= $howlong;
+            return 0 if ($elapsed >= $howlong and (scalar keys %matches == 0));
         }
 
         $dbh->commit();
@@ -936,8 +955,22 @@ sub wait_for_notice {
         redo;
     }
 
-    return 1;
-
+    if (scalar keys %matches) {
+        if ($num_strings == 1) {
+            return 1;
+        }
+        else {
+            return \%matches;
+        }
+    }
+    else {
+        if ($num_strings == 1) {
+            return 0;
+        }
+        else {
+            return {};
+        }
+    }
 } ## end of wait_for_notice
 
 
@@ -974,14 +1007,28 @@ sub reload {
 
         ## We wait for the MCP to tell us that each sync is done reloading
         my $done = "bucardo_reloaded_sync_$syncname";
+        my $err  = "bucardo_reload_error_sync_$syncname";
         print "Reloading sync $syncname...";
         $dbh->do(qq{LISTEN "$done"});
+        $dbh->do(qq{LISTEN "$err"});
         $dbh->do(qq{NOTIFY "bucardo_reload_sync_$syncname"});
         $dbh->commit();
 
         ## Sleep a little, then wait until we hear a confirmation from the MCP
         sleep 0.1;
-        wait_for_notice($dbh, $done);
+        my $res = wait_for_notice($dbh, [$err, $done], 10);
+        if ($res == 0 or scalar keys %$res == 0) {
+            print "Reload of sync $syncname failed; reload response message never received\n";
+        }
+        elsif (exists $res->{$done}) {
+            print "Reload of sync $syncname successful\n";
+        }
+        elsif (exists $res->{$err}) {
+            print "Reload of sync $syncname failed\n";
+        }
+        else {
+            print "ERROR. Reload results unavailable, because something weird happened.\n";
+        }
         print "\n";
 
     } ## end each sync to be reloaded