Changeset 222

Show
Ignore:
Timestamp:
02/10/11 18:32:36 (3 years ago)
Author:
depesz
Message:

Fix problem which caused omnipitr-backup-slave to produce sometimes backups that can't be restarted, on 9.0 with Streaming Replication enabled.

In passing - refactor waiting for file method to parent class.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/omnipitr/doc/changes.pod

    r221 r222  
    66 
    77=item * Make the IMMEDIATE finish of recovery actually work. 
     8 
     9=item * Make omnipitr-backup-slave compatible with Streaming Replication in 
     10PostgreSQL 9.0 
    811 
    912=back 
  • trunk/omnipitr/lib/OmniPITR/Program/Backup.pm

    r214 r222  
    4949    my $self = shift; 
    5050    croak( "make_xlog_archive() method in OmniPITR::Program::Backup was not overridden!" ); 
     51} 
     52 
     53=head1 wait_for_file() 
     54 
     55Helper function which waits for file to appear. 
     56 
     57It will return only if the file appeared. 
     58 
     59Return value is name of file. 
     60 
     61=cut 
     62 
     63sub wait_for_file { 
     64    my $self = shift; 
     65    my ( $dir, $filename_regexp ) = @_; 
     66 
     67    my $max_wait = 3600;    # It's 1 hour. There is no technical need to wait longer. 
     68    for my $i ( 0 .. $max_wait ) { 
     69        $self->log->log( 'Waiting for file matching %s in directory %s', $filename_regexp, $dir ) if 10 == $i; 
     70 
     71        opendir( my $dh, $dir ) or $self->log->fatal( 'Cannot open %s for scanning: %s', $dir, $OS_ERROR ); 
     72        my @matching = grep { $_ =~ $filename_regexp } readdir $dh; 
     73        closedir $dh; 
     74 
     75        if ( 0 == scalar @matching ) { 
     76            sleep 1; 
     77            next; 
     78        } 
     79 
     80        my $reply_filename = shift @matching; 
     81        $self->log->log( 'File %s arrived after %u seconds.', $reply_filename, $i ) if $self->verbose; 
     82        return $reply_filename; 
     83    } 
     84 
     85    $self->log->fatal( 'Waited 1 hour for file matching %s, but it did not appear. Something is wrong. No sense in waiting longer.', $filename_regexp ); 
     86 
     87    return; 
    5188} 
    5289 
  • trunk/omnipitr/lib/OmniPITR/Program/Backup/Master.pm

    r214 r222  
    4343    $self->wait_for_final_xlog_and_remove_dst_backup(); 
    4444    $self->compress_xlogs(); 
    45     return; 
    46 } 
    47  
    48 =head1 wait_for_file() 
    49  
    50 Helper function which waits for file to appear. 
    51  
    52 It will return only if the file appeared. 
    53  
    54 Return value is name of file. 
    55  
    56 =cut 
    57  
    58 sub wait_for_file { 
    59     my $self = shift; 
    60     my ( $dir, $filename_regexp ) = @_; 
    61  
    62     my $max_wait = 3600;    # It's 1 hour. There is no technical need to wait longer. 
    63     for my $i ( 0 .. $max_wait ) { 
    64         $self->log->log( 'Waiting for file matching %s in directory %s', $filename_regexp, $dir ) if 10 == $i; 
    65  
    66         opendir( my $dh, $dir ) or $self->log->fatal( 'Cannot open %s for scanning: %s', $dir, $OS_ERROR ); 
    67         my @matching = grep { $_ =~ $filename_regexp } readdir $dh; 
    68         closedir $dh; 
    69  
    70         if ( 0 == scalar @matching ) { 
    71             sleep 1; 
    72             next; 
    73         } 
    74  
    75         my $reply_filename = shift @matching; 
    76         $self->log->log( 'File %s arrived after %u seconds.', $reply_filename, $i ) if $self->verbose; 
    77         return $reply_filename; 
    78     } 
    79  
    80     $self->log->fatal( 'Waited 1 hour for file matching %s, but it did not appear. Something is wrong. No sense in waiting longer.', $filename_regexp ); 
    81  
    8245    return; 
    8346} 
  • trunk/omnipitr/lib/OmniPITR/Program/Backup/Slave.pm

    r220 r222  
    138138    my $self = shift; 
    139139 
    140     my $redo_location  = $self->{ 'CONTROL' }->{ 'initial' }->{ "Latest checkpoint's REDO location" }; 
     140    my $redo_location = $self->{ 'CONTROL' }->{ 'initial' }->{ "Latest checkpoint's REDO location" }; 
     141    my $timeline      = $self->{ 'CONTROL' }->{ 'initial' }->{ "Latest checkpoint's TimeLineID" }; 
     142 
    141143    my $final_location = $self->{ 'CONTROL' }->{ 'final' }->{ "Latest checkpoint location" }; 
    142     my $timeline       = $self->{ 'CONTROL' }->{ 'initial' }->{ "Latest checkpoint's TimeLineID" }; 
    143     my $offset         = $redo_location; 
     144    if (   ( defined $self->{ 'CONTROL' }->{ 'final' }->{ 'Minimum recovery ending location' } ) 
     145        && ( $self->{ 'CONTROL' }->{ 'final' }->{ 'Minimum recovery ending location' } =~ m{\A[a-f0-9]+/[a-f0-9]+\z}i ) 
     146        && ( '0/0' ne $self->{ 'CONTROL' }->{ 'final' }->{ 'Minimum recovery ending location' } ) ) 
     147    { 
     148        $final_location = $self->{ 'CONTROL' }->{ 'final' }->{ 'Minimum recovery ending location' }; 
     149    } 
     150    my $final_wal_filename = $self->convert_wal_location_and_timeline_to_filename( $final_location, $timeline ); 
     151 
     152    my $final_wal_filename_re = qr{\A$final_wal_filename}; 
     153    $self->wait_for_file( $self->{ 'source' }->{ 'path' }, $final_wal_filename_re ); 
     154 
     155    my $offset = $redo_location; 
    144156    $offset =~ s#.*/##; 
    145157    $offset =~ s/^.*?(.{0,6})$/$1/; 
     
    148160 
    149161    my @content_lines = @{ $self->{ 'backup_file_data' } }; 
    150     splice( @content_lines, 1, 0, sprintf 'STOP WAL LOCATION: %s (file %s)', $final_location, $self->convert_wal_location_and_timeline_to_filename( $final_location, $timeline ) ); 
     162    splice( @content_lines, 1, 0, sprintf 'STOP WAL LOCATION: %s (file %s)', $final_location, $final_wal_filename ); 
    151163    splice( @content_lines, 4, 0, sprintf 'START TIME: %s', strftime( '%Y-%m-%d %H:%M:%S %Z', localtime time ) ); 
    152164