/[BackupPC]/trunk/bin/BackupPC_incPartsUpdate
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Diff of /trunk/bin/BackupPC_incPartsUpdate

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 269 by dpavlin, Tue Dec 13 18:08:48 2005 UTC revision 371 by iklaric, Mon May 7 08:48:47 2007 UTC
# Line 16  use Archive::Tar::Streamed; Line 16  use Archive::Tar::Streamed;
16  use Algorithm::Diff;  use Algorithm::Diff;
17  use Getopt::Std;  use Getopt::Std;
18  use File::Slurp;  use File::Slurp;
19    use File::Pid;
20    
21    =head1 NAME
22    
23    BackupPC_incPartsUpdate
24    
25    =head1 DESCRIPTION
26    
27    Create C<.tar.gz> increments on disk calling C<BackupPC_tarIncCreate>.
28    
29    Following options are supported (but all are optional):
30    
31    =over 4
32    
33    =item -h hostname
34    
35    Update parts for just single C<hostname>
36    
37    =item -c
38    
39    Force check for tar archives which exist on disk
40    
41    =item -d
42    
43    Turn debugging output
44    
45    =back
46    
47    =cut
48    
49    my %opt;
50    getopts("cdh:", \%opt );
51    
52    my $debug = $opt{d};
53    my $check = $opt{c} && print STDERR "NOTICE: tar archive check forced\n";
54    
55    my $pid_path = abs_path($0);
56    $pid_path =~ s/\W+/_/g;
57    
58    my $pidfile = new File::Pid({
59            file => "/tmp/$pid_path",
60    });
61    
62    if (my $pid = $pidfile->running ) {
63            die "$0 already running: $pid\n";
64    } elsif ($pidfile->pid ne $$) {
65            $pidfile->remove;
66            $pidfile = new File::Pid;
67    }
68    
69    print STDERR "$0 using pid ",$pidfile->pid," file ",$pidfile->file,"\n";
70    $pidfile->write;
71    
72  my $bpc = BackupPC::Lib->new || die "can't create BackupPC::Lib";  my $bpc = BackupPC::Lib->new || die "can't create BackupPC::Lib";
73  my %Conf = $bpc->Conf();  my %Conf = $bpc->Conf();
# Line 34  foreach my $c (qw/gzip md5sum/) { Line 86  foreach my $c (qw/gzip md5sum/) {
86          $bin->{$c} = which($c) || die "$0 needs $c, install it\n";          $bin->{$c} = which($c) || die "$0 needs $c, install it\n";
87  }  }
88    
 my %opt;  
 getopts("cd", \%opt );  
   
 my $debug = $opt{d};  
 my $check = $opt{c} && print STDERR "NOTICE: tar archive check forced\n";  
   
89  $|=1;  $|=1;
90    
91  my $start_t = time();  my $start_t = time();
# Line 84  sub get_backup_id($$$) { Line 130  sub get_backup_id($$$) {
130                  FROM backups                  FROM backups
131                  INNER JOIN shares       ON backups.shareID=shares.ID                  INNER JOIN shares       ON backups.shareID=shares.ID
132                  INNER JOIN hosts        ON backups.hostID = hosts.ID                  INNER JOIN hosts        ON backups.hostID = hosts.ID
133                  where hosts.name = ? and shares.name = ? and backups.num = ?                  WHERE hosts.name = ? and shares.name = ? and backups.num = ?
134          });          });
135          $sth->execute($host, $share, $num);          $sth->execute($host, $share, $num);
136          my ($id) = $sth->fetchrow_array;          my ($id) = $sth->fetchrow_array;
# Line 96  sub get_backup_id($$$) { Line 142  sub get_backup_id($$$) {
142          return $id;          return $id;
143  }  }
144    
145    sub backup_inc_deleted($) {
146            my $backup_id = shift;
147            my $sth_inc_deleted = $dbh->prepare(qq{
148                    update backups set
149                            inc_deleted = true
150                    where id = ?
151            });
152            $sth_inc_deleted->execute($backup_id);
153    }
154    
155  sub tar_check($$$$) {  sub tar_check($$$$) {
156          my ($host,$share,$num,$filename) = @_;          my ($host,$share,$num,$filename) = @_;
157    
158            my $t = time();
159            print curr_time, " check $host:$share#$num -> $filename";
160    
161            # depending on expected returned value this is used like:
162            # my $uncompress_size = get_gzip_size('/full/path/to.gz');
163            # my ($compress_size, $uncompress_size) = get_gzip_size('/path.gz');
164            sub get_gzip_size($) {
165                    my $filename = shift;
166                    die "file $filename problem: $!" unless (-r $filename);
167                    open(my $gzip, $bin->{gzip}." -l $filename |") || die "can't gzip -l $filename: $!";
168                    my $line = <$gzip>;
169                    chomp($line);
170                    $line = <$gzip> if ($line =~ /^\s+compressed/);
171    
172                    my ($comp, $uncomp) = (0,0);
173    
174                    if ($line =~ m/^\s+(\d+)\s+(\d+)\s+\d+\.\d+/) {
175                            if (wantarray) {
176                                    return [ $1, $2 ];
177                            } else {
178                                    return $2;
179                            }
180                    } else {
181                            die "can't find size in line: $line";
182                    }
183            }
184    
185          sub check_part {          sub check_part {
186                  my ($host, $share, $num, $part_nr, $tar_size, $size, $md5, $items) = @_;                  my ($host, $share, $num, $part_nr, $tar_size, $size, $md5, $items) = @_;
187                  my $backup_id = get_backup_id($host, $share, $num);                  my $backup_id = get_backup_id($host, $share, $num);
# Line 119  sub tar_check($$$$) { Line 201  sub tar_check($$$$) {
201                                  $row->{md5} eq $md5 &&                                  $row->{md5} eq $md5 &&
202                                  $row->{items} == $items                                  $row->{items} == $items
203                          );                          );
204                          print STDERR "# deleting invalid row $row->{id}\n" if ($opt{d});                          print ", deleting invalid backup_parts $row->{id}";
205                          $dbh->do(qq{ delete from backup_parts where id = $row->{id} });                          $dbh->do(qq{ delete from backup_parts where id = $row->{id} });
206                  }                  }
207                  print STDERR "# inserting new backup_part row\n";                  print ", inserting new";
208                  my $sth_insert = $dbh->prepare(qq{                  my $sth_insert = $dbh->prepare(qq{
209                          insert into backup_parts (                          insert into backup_parts (
210                                  backup_id,                                  backup_id,
# Line 138  sub tar_check($$$$) { Line 220  sub tar_check($$$$) {
220                  $dbh->commit;                  $dbh->commit;
221          }          }
222    
         if ($debug) {  
                 print STDERR " {{ CHECK: ${host}:${share}#${num} and $filename";  
         } else {  
                 print " check $filename";  
         }  
   
223          my @tar_parts;          my @tar_parts;
224    
225          if (-d "$tar_dir/$filename") {          if (-d "$tar_dir/$filename") {
226                  print STDERR " multi-part" if ($opt{d});                  print ", multi-part";
227                  opendir(my $dir, "$tar_dir/$filename") || die "can't readdir $tar_dir/$filename: $!";                  opendir(my $dir, "$tar_dir/$filename") || die "can't readdir $tar_dir/$filename: $!";
228                  @tar_parts = map { my $p = $_; $p =~ s#^#${filename}/#; $p } grep { !/^\./ && !/md5/ && -f "$tar_dir/$filename/$_" } readdir($dir);                  @tar_parts = map { my $p = $_; $p =~ s#^#${filename}/#; $p } grep { !/^\./ && !/md5/ && -f "$tar_dir/$filename/$_" } readdir($dir);
229                  closedir($dir);                  closedir($dir);
# Line 166  sub tar_check($$$$) { Line 242  sub tar_check($$$$) {
242    
243          foreach my $tarfilename (@tar_parts) {          foreach my $tarfilename (@tar_parts) {
244    
245                  print STDERR " $tarfilename" if ($debug);                  print "\n\t- $tarfilename";
246    
247                    my $path = "$tar_dir/$tarfilename";
248    
249                  my $size = (stat( "$tar_dir/$tarfilename" ))[7] || die "can't stat $tar_dir/$tarfilename";                  my $size = (stat( $path ))[7] || die "can't stat $path: $!";
250    
251                  if ($size > $Conf{MaxArchiveSize}) {                  if ($size > $Conf{MaxArchiveSize}) {
252                          print STDERR " part bigger than media $size > $Conf{MaxArchiveSize} }}" if ($debug);                          print ", part bigger than media $size > $Conf{MaxArchiveSize}\n";
253                          $same = 0;                          return 0;
                         last;  
254                  }                  }
255    
256                  my $path = "$tar_dir/$tarfilename";                  print ", $size bytes";
257    
258    
259                  open(my $fh, "gzip -cd $tar_dir/$tarfilename |") or die "can't open $tar_dir/$tarfilename: $!";                  open(my $fh, "gzip -cd $path |") or die "can't open $path: $!";
260                  binmode($fh);                  binmode($fh);
261                  my $tar = Archive::Tar::Streamed->new($fh);                  my $tar = Archive::Tar::Streamed->new($fh);
262    
263                  my $tar_size = 0;                  my $tar_size_inarc = 0;
264                  my $items = 0;                  my $items = 0;
265    
266                  while(my $entry = $tar->next) {                  while(my $entry = $tar->next) {
267                          push @tar_files, $entry->name;                          push @tar_files, $entry->name;
268                          $items++;                          $items++;
269                          $tar_size += $entry->size;                          $tar_size_inarc += $entry->size;
270    
271                          if ($tar_size > $Conf{MaxArchiveFileSize}) {                          if ($tar_size_inarc > $Conf{MaxArchiveFileSize}) {
272                                  print STDERR " part too big $tar_size > $Conf{MaxArchiveFileSize} }}" if ($debug);                                  print ", part $tarfilename is too big $tar_size_inarc > $Conf{MaxArchiveFileSize}\n";
273                                  $same = 0;                                  return 0;
                                 last;  
274                          }                          }
275    
276                  }                  }
277    
278                    close($fh);
279    
280                    print ", $items items";
281    
282                    if ($tar_size_inarc == 0 && $items == 0) {
283                            print ", EMPTY tar\n";
284    
285                            my $backup_id = get_backup_id($host, $share, $num);
286                            backup_inc_deleted( $backup_id );
287    
288                            $dbh->commit;
289    
290                            return 1;
291                    }
292    
293                    my $tar_size = get_gzip_size( $path );
294    
295                    # real tar size is bigger because of padding    
296                    if ($tar_size_inarc > $tar_size) {
297                            print ", size of files in tar ($tar_size_inarc) bigger than whole tar ($tar_size)!\n";
298                            return 0;
299                    }
300    
301                  #                  #
302                  # check if md5 exists, and if not, create one                  # check if md5 exists, and if not, create one
303                  #                  #
# Line 207  sub tar_check($$$$) { Line 307  sub tar_check($$$$) {
307                  if (! -e $md5_path || -z $md5_path) {                  if (! -e $md5_path || -z $md5_path) {
308                          print ", creating md5";                          print ", creating md5";
309                          system( $bin->{md5sum} . " $path > $md5_path") == 0 or die "can't create md5 $path: $!";                          system( $bin->{md5sum} . " $path > $md5_path") == 0 or die "can't create md5 $path: $!";
310                    } else {
311                            ## FIXME check if existing md5 is valid
312                  }                  }
313    
314                  my $md5 = read_file( $md5_path ) || die "can't read md5sum file $md5_path: $!";                  my $md5 = read_file( $md5_path ) || die "can't read md5sum file $md5_path: $!";
# Line 227  sub tar_check($$$$) { Line 329  sub tar_check($$$$) {
329          return $same unless($same);          return $same unless($same);
330    
331          @tar_files = sort @tar_files;          @tar_files = sort @tar_files;
332          print STDERR " ",($#tar_files + 1), " files" if ($debug);          print "\n\t",($#tar_files + 1), " tar files";
   
         print STDERR ", database" if ($debug);  
333    
334          my $sth = $dbh->prepare(qq{          my $sth = $dbh->prepare(qq{
335                  SELECT path,type                  SELECT path,type
# Line 248  sub tar_check($$$$) { Line 348  sub tar_check($$$$) {
348                  push @db_files, $path;                  push @db_files, $path;
349          }          }
350    
351          print STDERR " ",($#db_files + 1), " files, diff" if ($debug);          print " ",($#db_files + 1), " database files, diff";
352    
353          @db_files = sort @db_files;          @db_files = sort @db_files;
354    
355          if ($#tar_files != $#db_files) {          if ($#tar_files != $#db_files) {
356                  $same = 0;                  $same = 0;
357                  print STDERR " NUMBER" if ($debug);                  print " NUMBER";
358          } else {          } else {
359                  my $diff = Algorithm::Diff->new(\@tar_files, \@db_files);                  my $diff = Algorithm::Diff->new(\@tar_files, \@db_files);
360                  while ( $diff->Next() ) {                  while ( $diff->Next() ) {
# Line 265  sub tar_check($$$$) { Line 365  sub tar_check($$$$) {
365                  }                  }
366          }          }
367    
368          print " ",($same ? 'ok' : 'DIFFERENT');          print " ",($same ? 'ok' : 'DIFFERENT'),
369          print STDERR " }} " if ($debug);                  ", dur: ",fmt_time(time() - $t), "\n";
370    
371          return $same;          return $same;
372  }  }
# Line 281  select Line 381  select
381          hosts.name as host,          hosts.name as host,
382          shares.name as share,          shares.name as share,
383          backups.num as num,          backups.num as num,
384            backups.date,
385          inc_size,          inc_size,
386          parts          parts,
387            count(backup_parts.backup_id) as backup_parts
388  from backups  from backups
389          join shares on backups.hostid = shares.hostid          join shares on backups.hostid = shares.hostid
390                  and shares.id = backups.shareid                  and shares.id = backups.shareid
391          join hosts on shares.hostid = hosts.id          join hosts on shares.hostid = hosts.id
392  where not inc_deleted          full outer join backup_parts on backups.id = backup_parts.backup_id
393    where not inc_deleted and backups.size > 0
394    group by backups.id, hosts.name, shares.name, backups.num, backups.date, inc_size, parts, backup_parts.backup_id
395  order by backups.date  order by backups.date
396    
397  } );  } );
# Line 296  $sth->execute(); Line 400  $sth->execute();
400  my $num_backups = $sth->rows;  my $num_backups = $sth->rows;
401  my $curr_backup = 1;  my $curr_backup = 1;
402    
403    if ($opt{h}) {
404            warn "making increments just for host $opt{h}\n";
405    }
406    
407  while (my $row = $sth->fetchrow_hashref) {  while (my $row = $sth->fetchrow_hashref) {
408    
409            if ($opt{h} && $row->{host} ne $opt{h}) {
410                    warn "skipped $row->{host}\n" if ($debug);
411                    next;
412            }
413    
414            $curr_backup++;
415    
416          my $tar_file = BackupPC::SearchLib::getGzipName($row->{'host'}, $row->{'share'}, $row->{'num'});          my $tar_file = BackupPC::SearchLib::getGzipName($row->{'host'}, $row->{'share'}, $row->{'num'});
417    
418          # this will return -1 if file doesn't exist          # this will return -1 if file doesn't exist
419          my $size = BackupPC::SearchLib::get_tgz_size_by_name($tar_file);          my $size = BackupPC::SearchLib::get_tgz_size_by_name($tar_file);
420    
421          print "# size: $size backup.size: ", $row->{inc_size},"\n" if ($opt{d});          print "# host: ".${row->{host}}.", share: ".$row->{'share'}.", backup_num:".$row->{num}." size: $size backup.size: ", $row->{inc_size},"\n" if ($opt{d});
422    
423          if ( $row->{'inc_size'} != -1 && $size != -1 && $row->{'inc_size'} >= $size) {          if ( $row->{'inc_size'} != -1 && $size != -1 && $row->{'inc_size'} >= $size && $row->{parts} == $row->{backup_parts}) {
424                  if ($check) {                  if ($check) {
425                          tar_check($row->{'host'}, $row->{'share'}, $row->{'num'}, $tar_file) && next;                          tar_check($row->{'host'}, $row->{'share'}, $row->{'num'}, $tar_file) && next;
426                  } else {                  } else {
# Line 312  while (my $row = $sth->fetchrow_hashref) Line 428  while (my $row = $sth->fetchrow_hashref)
428                  }                  }
429          }          }
430    
431          print curr_time, " $curr_backup/$num_backups ", $row->{'host'}, ":", $row->{'share'}, " #", $row->{'num'}, " -> $tar_file";          print curr_time, " creating $curr_backup/$num_backups ", $row->{host}, ":", $row->{share}, " #", $row->{num},
432          $curr_backup++;                  " ", strftime('%Y-%m-%d', localtime($row->{date})), " -> $tar_file";
433    
434          my $t = time();          my $t = time();
435    
436          # re-create archive?          # re-create archive?
437          my $cmd = qq{ $tarIncCreate -h "$row->{'host'}" -s "$row->{'share'}" -n $row->{'num'} -f };          my $cmd = qq[ $tarIncCreate -h "$row->{host}" -s "$row->{share}" -n $row->{num} -f ];
438          print STDERR "## $cmd\n" if ($debug);          print STDERR "## $cmd\n" if ($debug);
439    
440          if (system($cmd) != 0) {          if (system($cmd) != 0) {
441                  print STDERR " FAILED";                  print STDERR " FAILED, marking this backup deleted";
442                    backup_inc_deleted( $row->{backup_id} );
443          }          }
444    
445          print ", dur: ",fmt_time(time() - $t), "\n";          print ", dur: ",fmt_time(time() - $t), "\n";

Legend:
Removed from v.269  
changed lines
  Added in v.371

  ViewVC Help
Powered by ViewVC 1.1.26