/[BackupPC]/trunk/bin/BackupPC_updatedb
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_updatedb

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

revision 199 by dpavlin, Thu Oct 13 21:19:06 2005 UTC revision 325 by dpavlin, Tue Jan 31 16:29:30 2006 UTC
# Line 12  use Time::HiRes qw/time/; Line 12  use Time::HiRes qw/time/;
12  use File::Pid;  use File::Pid;
13  use POSIX qw/strftime/;  use POSIX qw/strftime/;
14  use BackupPC::SearchLib;  use BackupPC::SearchLib;
15    use Cwd qw/abs_path/;
16    
17  use constant BPC_FTYPE_DIR => 5;  use constant BPC_FTYPE_DIR => 5;
18  use constant EST_CHUNK => 100000;  use constant EST_CHUNK => 4096;
19    
20    # daylight saving time change offset for 1h
21    my $dst_offset = 60 * 60;
22    
23  my $debug = 0;  my $debug = 0;
24  $|=1;  $|=1;
25    
26  my $start_t = time();  my $start_t = time();
27    
28  my $pidfile = new File::Pid;  my $pid_path = abs_path($0);
29    $pid_path =~ s/\W+/_/g;
30    
31    my $pidfile = new File::Pid({
32            file => "/tmp/$pid_path",
33    });
34    
35  if (my $pid = $pidfile->running ) {  if (my $pid = $pidfile->running ) {
36          die "$0 already running: $pid\n";          die "$0 already running: $pid\n";
# Line 29  if (my $pid = $pidfile->running ) { Line 38  if (my $pid = $pidfile->running ) {
38          $pidfile->remove;          $pidfile->remove;
39          $pidfile = new File::Pid;          $pidfile = new File::Pid;
40  }  }
 $pidfile->write;  
41  print STDERR "$0 using pid ",$pidfile->pid," file ",$pidfile->file,"\n";  print STDERR "$0 using pid ",$pidfile->pid," file ",$pidfile->file,"\n";
42    $pidfile->write;
43    
44  my $t_fmt = '%Y-%m-%d %H:%M:%S';  my $t_fmt = '%Y-%m-%d %H:%M:%S';
45    
# Line 43  my $beenThere = {}; Line 52  my $beenThere = {};
52  my $dsn = $Conf{SearchDSN} || die "Need SearchDSN in config.pl\n";  my $dsn = $Conf{SearchDSN} || die "Need SearchDSN in config.pl\n";
53  my $user = $Conf{SearchUser} || '';  my $user = $Conf{SearchUser} || '';
54    
55  my $use_hest = $Conf{HyperEstraierIndex};  my $index_node_url = $Conf{HyperEstraierIndex};
 my ($index_path, $index_node_url) = BackupPC::SearchLib::getHyperEstraier_url($use_hest);  
56    
57  my $dbh = DBI->connect($dsn, $user, "", { RaiseError => 1, AutoCommit => 0 });  my $dbh = DBI->connect($dsn, $user, "", { RaiseError => 1, AutoCommit => 0 });
58    
59  my %opt;  my %opt;
60    
61  if ( !getopts("cdm:v:ij", \%opt ) ) {  if ( !getopts("cdm:v:ijfq", \%opt ) ) {
62          print STDERR <<EOF;          print STDERR <<EOF;
63  usage: $0 [-c|-d] [-m num] [-v|-v level] [-i]  usage: $0 [-c|-d] [-m num] [-v|-v level] [-i|-j|-f]
64    
65  Options:  Options:
66          -c      create database on first use          -c      create database on first use
# Line 61  Options: Line 69  Options:
69          -v num  set verbosity (debug) level (default $debug)          -v num  set verbosity (debug) level (default $debug)
70          -i      update Hyper Estraier full text index          -i      update Hyper Estraier full text index
71          -j      update full text, don't check existing files          -j      update full text, don't check existing files
72            -f      don't do anything with full text index
73            -q      be quiet for hosts without changes
74    
75  Option -j is variation on -i. It will allow faster initial creation  Option -j is variation on -i. It will allow faster initial creation
76  of full-text index from existing database.  of full-text index from existing database.
77    
78    Option -f will create database which is out of sync with full text index. You
79    will have to re-run $0 with -i to fix it.
80    
81  EOF  EOF
82          exit 1;          exit 1;
83  }  }
# Line 72  EOF Line 85  EOF
85  if ($opt{v}) {  if ($opt{v}) {
86          print "Debug level at $opt{v}\n";          print "Debug level at $opt{v}\n";
87          $debug = $opt{v};          $debug = $opt{v};
88    } elsif ($opt{f}) {
89            print "WARNING: disabling full-text index update. You need to re-run $0 -j !\n";
90            $index_node_url = undef;
91  }  }
92    
93  #---- subs ----  #---- subs ----
# Line 89  sub curr_time { Line 105  sub curr_time {
105          return strftime($t_fmt,localtime());          return strftime($t_fmt,localtime());
106  }  }
107    
 my $hest_db;  
108  my $hest_node;  my $hest_node;
109    
 sub signal {  
         my($sig) = @_;  
         if ($hest_db) {  
                 print "\nCaught a SIG$sig--syncing database and shutting down\n";  
                 $hest_db->sync();  
                 $hest_db->close();  
         }  
         exit(0);  
 }  
   
 $SIG{'INT'}  = \&signal;  
 $SIG{'QUIT'} = \&signal;  
   
110  sub hest_update {  sub hest_update {
111    
112          my ($host_id, $share_id, $num) = @_;          my ($host_id, $share_id, $num) = @_;
113    
114          my $skip_check = $opt{j} && print STDERR "Skipping check for existing files -- this should be used only with initital import\n";          my $skip_check = $opt{j} && print STDERR "Skipping check for existing files -- this should be used only with initital import\n";
115    
116          unless ($use_hest) {          unless (defined($index_node_url)) {
117                  print STDERR "HyperEstraier support not enabled in configuration\n";                  print STDERR "HyperEstraier support not enabled in configuration\n";
118                    $index_node_url = 0;
119                  return;                  return;
120          }          }
121    
122          print curr_time," updating HyperEstraier:";          print curr_time," updating Hyper Estraier:";
123    
124          my $t = time();          my $t = time();
125    
126          my $offset = 0;          my $offset = 0;
127          my $added = 0;          my $added = 0;
128    
129          print " opening index $use_hest";          if ($index_node_url) {
130          if ($index_path) {                  print " opening index $index_node_url";
131                  $hest_db = HyperEstraier::Database->new();                  $hest_node ||= Search::Estraier::Node->new(
132                  $hest_db->open($TopDir . $index_path, $HyperEstraier::Database::DBWRITER | $HyperEstraier::Database::DBCREAT);                          url => $index_node_url,
133                  print " directly";                          user => 'admin',
134          } elsif ($index_node_url) {                          passwd => 'admin',
135                  $hest_node ||= HyperEstraier::Node->new($index_node_url);                          croak_on_error => 1,
136                  $hest_node->set_auth('admin', 'admin');                  );
137                  print " via node URL";                  print " via node URL";
         } else {  
                 die "don't know how to use HyperEstraier Index $use_hest";  
138          }          }
         print " increment is " . EST_CHUNK . " files:";  
139    
140          my $results = 0;          my $results = 0;
141    
# Line 182  sub hest_update { Line 182  sub hest_update {
182    
183                  if ($results == 0) {                  if ($results == 0) {
184                          print " - no new files\n";                          print " - no new files\n";
185                          last;                          return;
186                    } else {
187                            print "...";
188                  }                  }
189    
190                  sub fmt_date {                  sub fmt_date {
# Line 194  sub hest_update { Line 196  sub hest_update {
196    
197                  while (my $row = $sth->fetchrow_hashref()) {                  while (my $row = $sth->fetchrow_hashref()) {
198    
199                          my $fid = $row->{'fid'} || die "no fid?";                          my $uri = $row->{hname} . ':' . $row->{sname} . '#' . $row->{backupnum} . ' ' . $row->{filepath};
200                          my $uri = 'file:///' . $fid;                          unless ($skip_check && $hest_node) {
201                                    my $id = $hest_node->uri_to_id($uri);
202                          unless ($skip_check) {                                  next if ($id && $id == -1);
                                 my $id = ($hest_db || $hest_node)->uri_to_id($uri);  
                                 next unless ($id == -1);  
203                          }                          }
204    
205                          # create a document object                          # create a document object
206                          my $doc = HyperEstraier::Document->new;                          my $doc = Search::Estraier::Document->new;
207    
208                          # add attributes to the document object                          # add attributes to the document object
209                          $doc->add_attr('@uri', $uri);                          $doc->add_attr('@uri', $uri);
210    
211                          foreach my $c (@{ $sth->{NAME} }) {                          foreach my $c (@{ $sth->{NAME} }) {
212                                  $doc->add_attr($c, $row->{$c}) if ($row->{$c});                                  print STDERR "attr $c = $row->{$c}\n" if ($debug > 2);
213                                    $doc->add_attr($c, $row->{$c}) if (defined($row->{$c}));
214                          }                          }
215    
216                          #$doc->add_attr('@cdate', fmt_date($row->{'date'}));                          #$doc->add_attr('@cdate', fmt_date($row->{'date'}));
# Line 223  sub hest_update { Line 224  sub hest_update {
224                          print STDERR $doc->dump_draft,"\n" if ($debug > 1);                          print STDERR $doc->dump_draft,"\n" if ($debug > 1);
225    
226                          # register the document object to the database                          # register the document object to the database
227                          if ($hest_db) {                          if ($hest_node) {
                                 $hest_db->put_doc($doc, $HyperEstraier::Database::PDCLEAN);  
                         } elsif ($hest_node) {  
228                                  $hest_node->put_doc($doc);                                  $hest_node->put_doc($doc);
229                          } else {                          } else {
230                                  die "not supported";                                  die "not supported";
# Line 233  sub hest_update { Line 232  sub hest_update {
232                          $added++;                          $added++;
233                  }                  }
234    
235                  print " $added";                  print "$added";
                 $hest_db->sync() if ($index_path);  
236    
237                  $offset += EST_CHUNK;                  $offset += EST_CHUNK;
238    
239          } while ($results == EST_CHUNK);          } while ($results == EST_CHUNK);
240    
         if ($index_path) {  
                 print ", close";  
                 $hest_db->close();  
         }  
   
241          my $dur = (time() - $t) || 1;          my $dur = (time() - $t) || 1;
242          printf(" [%.2f/s dur: %s]\n",          printf(" [%.2f/s dur: %s]\n",
243                  ( $added / $dur ),                  ( $added / $dur ),
# Line 256  sub hest_update { Line 249  sub hest_update {
249    
250    
251  ## update index ##  ## update index ##
252  if (($opt{i} || $opt{j} || ($index_path && ! -e $index_path)) && !$opt{c}) {  if ( ( $opt{i} || $opt{j} ) && !$opt{c} ) {
253          # update all          # update all
254          print "force update of HyperEstraier index ";          print "force update of Hyper Estraier index ";
         print "importing existing data" unless (-e $index_path);  
255          print "by -i flag" if ($opt{i});          print "by -i flag" if ($opt{i});
256          print "by -j flag" if ($opt{j});          print "by -j flag" if ($opt{j});
257          print "\n";          print "\n";
# Line 310  if ($opt{c}) { Line 302  if ($opt{c}) {
302                          size    bigint          not null,                          size    bigint          not null,
303                          inc_size bigint         not null default -1,                          inc_size bigint         not null default -1,
304                          inc_deleted boolean     default false,                          inc_deleted boolean     default false,
305                          parts   integer         not null default 1,                          parts   integer         not null default 0,
306                          PRIMARY KEY(id)                          PRIMARY KEY(id)
307                  );                              );            
308    
# Line 344  if ($opt{c}) { Line 336  if ($opt{c}) {
336    
337                  create table archive_burned (                  create table archive_burned (
338                          archive_id      int references archive(id),                          archive_id      int references archive(id),
339                          date            date default now(),                          date            timestamp default now(),
340                          part            int not null default 1,                          part            int not null default 1,
341                            copy            int not null default 1,
342                          iso_size bigint default -1                          iso_size bigint default -1
343                  );                  );
344    
345                    create table backup_parts (
346                            id serial,
347                            backup_id int references backups(id),
348                            part_nr int not null check (part_nr > 0),
349                            tar_size bigint not null check (tar_size > 0),
350                            size bigint not null check (size > 0),
351                            md5 text not null,
352                            items int not null check (items > 0),
353                            date timestamp default now(),
354                            primary key(id)
355                    );
356          });          });
357    
358          print "creating indexes: ";          print "creating indexes: ";
# Line 367  if ($opt{c}) { Line 371  if ($opt{c}) {
371                  files:size                  files:size
372                  archive:dvd_nr                  archive:dvd_nr
373                  archive_burned:archive_id                  archive_burned:archive_id
374                    backup_parts:backup_id,part_nr
375          )) {          )) {
376                  do_index($index);                  do_index($index);
377          }          }
# Line 377  if ($opt{c}) { Line 382  if ($opt{c}) {
382                  $dbh->do( qq{ CREATE SEQUENCE $seq } );                  $dbh->do( qq{ CREATE SEQUENCE $seq } );
383          }          }
384    
385            print " creating triggers ";
386            $dbh->do( qq{
387                    create or replace function backup_parts_check() returns trigger as '
388                    declare
389                            b_parts integer;
390                            b_counted integer;
391                            b_id    integer;
392                    begin
393                            if (TG_OP=''UPDATE'') then
394                                    b_id := old.id;
395                                    b_parts := old.parts;
396                            elsif (TG_OP = ''INSERT'') then
397                                    b_id := new.id;
398                                    b_parts := new.parts;
399                            end if;
400                            b_counted := (select count(*) from backup_parts where backup_id = b_id);
401                            if ( b_parts != b_counted ) then
402                                    raise exception ''Update of backup % aborted, requested % parts and there are really % parts'', b_id, b_parts, b_counted;
403                            end if;
404                            return null;
405                    end;
406                    ' language plpgsql;
407    
408                    create trigger do_backup_parts_check
409                            after insert or update or delete on backups
410                            for each row execute procedure backup_parts_check();
411            });
412    
413          print "...\n";          print "...\n";
414    
# Line 421  WHERE hostID=? AND num=? AND shareid=? Line 453  WHERE hostID=? AND num=? AND shareid=?
453    
454  $sth->{insert_backups} = $dbh->prepare(qq{  $sth->{insert_backups} = $dbh->prepare(qq{
455  INSERT INTO backups (hostID, num, date, type, shareid, size)  INSERT INTO backups (hostID, num, date, type, shareid, size)
456  VALUES (?,?,?,?,?,?)  VALUES (?,?,?,?,?,-1)
457    });
458    
459    $sth->{update_backups_size} = $dbh->prepare(qq{
460    UPDATE backups SET size = ?
461    WHERE hostID = ? and num = ? and date = ? and type =? and shareid = ?
462  });  });
463    
464  $sth->{insert_files} = $dbh->prepare(qq{  $sth->{insert_files} = $dbh->prepare(qq{
# Line 430  INSERT INTO files Line 467  INSERT INTO files
467          VALUES (?,?,?,?,?,?,?)          VALUES (?,?,?,?,?,?,?)
468  });  });
469    
470  foreach my $host_key (keys %{$hosts}) {  my @hosts = keys %{$hosts};
471    my $host_nr = 0;
472    
473    foreach my $host_key (@hosts) {
474    
475          my $hostname = $hosts->{$host_key}->{'host'} || die "can't find host for $host_key";          my $hostname = $hosts->{$host_key}->{'host'} || die "can't find host for $host_key";
476    
# Line 445  foreach my $host_key (keys %{$hosts}) { Line 485  foreach my $host_key (keys %{$hosts}) {
485                  $hostID = $dbh->last_insert_id(undef,undef,'hosts',undef);                  $hostID = $dbh->last_insert_id(undef,undef,'hosts',undef);
486          }          }
487    
488          print "host ".$hosts->{$host_key}->{'host'}.": ";          $host_nr++;
   
489          # get backups for a host          # get backups for a host
490          my @backups = $bpc->BackupInfoRead($hostname);          my @backups = $bpc->BackupInfoRead($hostname);
491          my $incs = scalar @backups;          my $incs = scalar @backups;
         print  "$incs increments\n";  
492    
493            my $host_header = sprintf("host %s [%d/%d]: %d increments\n",
494                    $hosts->{$host_key}->{'host'},
495                    $host_nr,
496                    ($#hosts + 1),
497                    $incs
498            );
499            print $host_header unless ($opt{q});
500    
501          my $inc_nr = 0;          my $inc_nr = 0;
502          $beenThere = {};          $beenThere = {};
503    
# Line 463  foreach my $host_key (keys %{$hosts}) { Line 509  foreach my $host_key (keys %{$hosts}) {
509                  my $backupNum = $backup->{'num'};                  my $backupNum = $backup->{'num'};
510                  my @backupShares = ();                  my @backupShares = ();
511    
512                  printf("%-10s %2d/%-2d #%-2d %s %5s/%5s files (date: %s dur: %s)\n",                  my $share_header = sprintf("%-10s %2d/%-2d #%-2d %s %5s/%5s files (date: %s dur: %s)\n",
513                          $hosts->{$host_key}->{'host'},                          $hosts->{$host_key}->{'host'},
514                          $inc_nr, $incs, $backupNum,                          $inc_nr, $incs, $backupNum,
515                          $backup->{type} || '?',                          $backup->{type} || '?',
# Line 471  foreach my $host_key (keys %{$hosts}) { Line 517  foreach my $host_key (keys %{$hosts}) {
517                          strftime($t_fmt,localtime($backup->{startTime})),                          strftime($t_fmt,localtime($backup->{startTime})),
518                          fmt_time($backup->{endTime} - $backup->{startTime})                          fmt_time($backup->{endTime} - $backup->{startTime})
519                  );                  );
520                    print $share_header unless ($opt{q});
521    
522                  my $files = BackupPC::View->new($bpc, $hostname, \@backups, 1);                  my $files = BackupPC::View->new($bpc, $hostname, \@backups, 1);
523                  foreach my $share ($files->shareList($backupNum)) {                  foreach my $share ($files->shareList($backupNum)) {
# Line 484  foreach my $host_key (keys %{$hosts}) { Line 531  foreach my $host_key (keys %{$hosts}) {
531                          # skip if allready in database!                          # skip if allready in database!
532                          next if ($count > 0);                          next if ($count > 0);
533    
534                            # dump host and share header for -q
535                            if ($opt{q}) {
536                                    if ($host_header) {
537                                            print $host_header;
538                                            $host_header = undef;
539                                    }
540                                    print $share_header;
541                            }
542    
543                          # dump some log                          # dump some log
544                          print curr_time," ", $share;                          print curr_time," ", $share;
545    
                         my ($f, $nf, $d, $nd, $size) = recurseDir($bpc, $hostname, $files, $backupNum, $share, "", $shareID);  
   
546                          $sth->{insert_backups}->execute(                          $sth->{insert_backups}->execute(
547                                  $hostID,                                  $hostID,
548                                  $backupNum,                                  $backupNum,
549                                  $backup->{'endTime'},                                  $backup->{'endTime'},
550                                  substr($backup->{'type'},0,4),                                  substr($backup->{'type'},0,4),
551                                  $shareID,                                  $shareID,
                                 $size,  
552                          );                          );
553    
554                          print " commit";                          my ($f, $nf, $d, $nd, $size) = recurseDir($bpc, $hostname, $files, $backupNum, $share, "", $shareID);
555                          $dbh->commit();  
556                            eval {
557                                    $sth->{update_backups_size}->execute(
558                                            $size,
559                                            $hostID,
560                                            $backupNum,
561                                            $backup->{'endTime'},
562                                            substr($backup->{'type'},0,4),
563                                            $shareID,
564                                    );
565                                    print " commit";
566                                    $dbh->commit();
567                            };
568                            if ($@) {
569                                    print " rollback";
570                                    $dbh->rollback();
571                            }
572    
573                          my $dur = (time() - $t) || 1;                          my $dur = (time() - $t) || 1;
574                          printf(" %d/%d files %d/%d dirs %0.2f MB [%.2f/s dur: %s]\n",                          printf(" %d/%d files %d/%d dirs %0.2f MB [%.2f/s dur: %s]\n",
# Line 562  sub found_in_db { Line 631  sub found_in_db {
631                  SELECT 1 FROM files                  SELECT 1 FROM files
632                  WHERE shareID = ? and                  WHERE shareID = ? and
633                          path = ? and                          path = ? and
634                          date = ? and                          size = ? and
635                          size = ?                          ( date = ? or date = ? or date = ? )
636                  LIMIT 1                  LIMIT 1
637          });          });
638    
639          my @param = ($shareID,$path,$date,$size);          my @param = ($shareID,$path,$size,$date, $date-$dst_offset, $date+$dst_offset);
640          $sth->{file_in_db}->execute(@param);          $sth->{file_in_db}->execute(@param);
641          my $rows = $sth->{file_in_db}->rows;          my $rows = $sth->{file_in_db}->rows;
642          print STDERR "## found_in_db($shareID,$path,$date,$size) ",( $rows ? '+' : '-' ), join(" ",@param), "\n" if ($debug >= 3);          print STDERR "## found_in_db($shareID,$path,$date,$size) ",( $rows ? '+' : '-' ), join(" ",@param), "\n" if ($debug >= 3);
# Line 617  sub recurseDir($$$$$$$$) { Line 686  sub recurseDir($$$$$$$$) {
686                                  $filesInBackup->{$path_key}->{'size'}                                  $filesInBackup->{$path_key}->{'size'}
687                          ));                          ));
688    
689                            my $key_dst_prev = join(" ", (
690                                    $shareID,
691                                    $dir,
692                                    $path_key,
693                                    $filesInBackup->{$path_key}->{'mtime'} - $dst_offset,
694                                    $filesInBackup->{$path_key}->{'size'}
695                            ));
696    
697                            my $key_dst_next = join(" ", (
698                                    $shareID,
699                                    $dir,
700                                    $path_key,
701                                    $filesInBackup->{$path_key}->{'mtime'} + $dst_offset,
702                                    $filesInBackup->{$path_key}->{'size'}
703                            ));
704    
705                          my $found;                          my $found;
706                          if (! defined($beenThere->{$key}) && ! ($found = found_in_db($key, @data)) ) {                          if (
707                                    ! defined($beenThere->{$key}) &&
708                                    ! defined($beenThere->{$key_dst_prev}) &&
709                                    ! defined($beenThere->{$key_dst_next}) &&
710                                    ! ($found = found_in_db($key, @data))
711                            ) {
712                                  print STDERR "# key: $key [", $beenThere->{$key},"]" if ($debug >= 2);                                  print STDERR "# key: $key [", $beenThere->{$key},"]" if ($debug >= 2);
713    
714                                  if ($filesInBackup->{$path_key}->{'type'} == BPC_FTYPE_DIR) {                                  if ($filesInBackup->{$path_key}->{'type'} == BPC_FTYPE_DIR) {

Legend:
Removed from v.199  
changed lines
  Added in v.325

  ViewVC Help
Powered by ViewVC 1.1.26