/[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 74 by dpavlin, Fri Aug 26 17:18:27 2005 UTC revision 248 by dpavlin, Fri Dec 9 14:41:13 2005 UTC
# Line 11  use Getopt::Std; Line 11  use Getopt::Std;
11  use Time::HiRes qw/time/;  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;
15    
16  use constant BPC_FTYPE_DIR => 5;  use constant BPC_FTYPE_DIR => 5;
17    use constant EST_CHUNK => 100000;
18    
19    # daylight saving time change offset for 1h
20    my $dst_offset = 60 * 60;
21    
22  my $debug = 0;  my $debug = 0;
23  $|=1;  $|=1;
# Line 41  my $beenThere = {}; Line 46  my $beenThere = {};
46  my $dsn = $Conf{SearchDSN} || die "Need SearchDSN in config.pl\n";  my $dsn = $Conf{SearchDSN} || die "Need SearchDSN in config.pl\n";
47  my $user = $Conf{SearchUser} || '';  my $user = $Conf{SearchUser} || '';
48    
49    my $use_hest = $Conf{HyperEstraierIndex};
50    my ($index_path, $index_node_url) = BackupPC::SearchLib::getHyperEstraier_url($use_hest);
51    
52  my $dbh = DBI->connect($dsn, $user, "", { RaiseError => 1, AutoCommit => 0 });  my $dbh = DBI->connect($dsn, $user, "", { RaiseError => 1, AutoCommit => 0 });
53    
54  my %opt;  my %opt;
55    
56  if ( !getopts("cdm:v:", \%opt ) ) {  if ( !getopts("cdm:v:ijf", \%opt ) ) {
57          print STDERR <<EOF;          print STDERR <<EOF;
58  usage: $0 [-c|-d] [-m num] [-v|-v level]  usage: $0 [-c|-d] [-m num] [-v|-v level] [-i|-j|-f]
59    
60  Options:  Options:
61          -c      create database on first use          -c      create database on first use
62          -d      delete database before import          -d      delete database before import
63          -m num  import just num increments for one host          -m num  import just num increments for one host
64          -v num  set verbosity (debug) level (default $debug)          -v num  set verbosity (debug) level (default $debug)
65            -i      update Hyper Estraier full text index
66            -j      update full text, don't check existing files
67            -f      don't do anything with full text index
68    
69    Option -j is variation on -i. It will allow faster initial creation
70    of full-text index from existing database.
71    
72    Option -f will create database which is out of sync with full text index. You
73    will have to re-run $0 with -i to fix it.
74    
75  EOF  EOF
76          exit 1;          exit 1;
77  }  }
78    
79  ###################################create tables############################3  if ($opt{v}) {
80            print "Debug level at $opt{v}\n";
81            $debug = $opt{v};
82    } elsif ($opt{f}) {
83            print "WARNING: disabling full-text index update. You need to re-run $0 -j !\n";
84            ($use_hest, $index_path, $index_node_url) = (undef, undef, undef);
85    }
86    
87    #---- subs ----
88    
89    sub fmt_time {
90            my $t = shift || return;
91            my $out = "";
92            my ($ss,$mm,$hh) = gmtime($t);
93            $out .= "${hh}h" if ($hh);
94            $out .= sprintf("%02d:%02d", $mm,$ss);
95            return $out;
96    }
97    
98    sub curr_time {
99            return strftime($t_fmt,localtime());
100    }
101    
102    my $hest_db;
103    my $hest_node;
104    
105    sub signal {
106            my($sig) = @_;
107            if ($hest_db) {
108                    print "\nCaught a SIG$sig--syncing database and shutting down\n";
109                    $hest_db->sync();
110                    $hest_db->close();
111            }
112            exit(0);
113    }
114    
115    $SIG{'INT'}  = \&signal;
116    $SIG{'QUIT'} = \&signal;
117    
118    sub hest_update {
119    
120            my ($host_id, $share_id, $num) = @_;
121    
122            my $skip_check = $opt{j} && print STDERR "Skipping check for existing files -- this should be used only with initital import\n";
123    
124            unless (defined($use_hest)) {
125                    print STDERR "HyperEstraier support not enabled in configuration\n";
126                    $use_hest = 0;
127                    return;
128            }
129    
130            print curr_time," updating HyperEstraier:";
131    
132            my $t = time();
133    
134            my $offset = 0;
135            my $added = 0;
136    
137            print " opening index $use_hest";
138            if ($index_path) {
139                    $hest_db = HyperEstraier::Database->new();
140                    $hest_db->open($TopDir . $index_path, $HyperEstraier::Database::DBWRITER | $HyperEstraier::Database::DBCREAT);
141                    print " directly";
142            } elsif ($index_node_url) {
143                    $hest_node ||= HyperEstraier::Node->new($index_node_url);
144                    $hest_node->set_auth('admin', 'admin');
145                    print " via node URL";
146            } else {
147                    die "don't know how to use HyperEstraier Index $use_hest";
148            }
149            print " increment is " . EST_CHUNK . " files:";
150    
151            my $results = 0;
152    
153            do {
154    
155                    my $where = '';
156                    my @data;
157                    if (defined($host_id) && defined($share_id) && defined($num)) {
158                            $where = qq{
159                            WHERE
160                                    hosts.id = ? AND
161                                    shares.id = ? AND
162                                    files.backupnum = ?
163                            };
164                            @data = ( $host_id, $share_id, $num );
165                    }
166    
167                    my $limit = sprintf('LIMIT '.EST_CHUNK.' OFFSET %d', $offset);
168    
169                    my $sth = $dbh->prepare(qq{
170                            SELECT
171                                    files.id                        AS fid,
172                                    hosts.name                      AS hname,
173                                    shares.name                     AS sname,
174                                    -- shares.share                 AS sharename,
175                                    files.backupnum                 AS backupnum,
176                                    -- files.name                   AS filename,
177                                    files.path                      AS filepath,
178                                    files.date                      AS date,
179                                    files.type                      AS type,
180                                    files.size                      AS size,
181                                    files.shareid                   AS shareid,
182                                    backups.date                    AS backup_date
183                            FROM files
184                                    INNER JOIN shares       ON files.shareID=shares.ID
185                                    INNER JOIN hosts        ON hosts.ID = shares.hostID
186                                    INNER JOIN backups      ON backups.num = files.backupNum and backups.hostID = hosts.ID AND backups.shareID = shares.ID
187                            $where
188                            $limit
189                    });
190    
191                    $sth->execute(@data);
192                    $results = $sth->rows;
193    
194                    if ($results == 0) {
195                            print " - no new files\n";
196                            last;
197                    }
198    
199                    sub fmt_date {
200                            my $t = shift || return;
201                            my $iso = BackupPC::Lib::timeStamp($t);
202                            $iso =~ s/\s/T/;
203                            return $iso;
204                    }
205    
206                    while (my $row = $sth->fetchrow_hashref()) {
207    
208                            my $fid = $row->{'fid'} || die "no fid?";
209                            my $uri = 'file:///' . $fid;
210    
211                            unless ($skip_check) {
212                                    my $id = ($hest_db || $hest_node)->uri_to_id($uri);
213                                    next unless ($id == -1);
214                            }
215    
216                            # create a document object
217                            my $doc = HyperEstraier::Document->new;
218    
219                            # add attributes to the document object
220                            $doc->add_attr('@uri', $uri);
221    
222                            foreach my $c (@{ $sth->{NAME} }) {
223                                    $doc->add_attr($c, $row->{$c}) if (defined($row->{$c}));
224                            }
225    
226                            #$doc->add_attr('@cdate', fmt_date($row->{'date'}));
227    
228                            # add the body text to the document object
229                            my $path = $row->{'filepath'};
230                            $doc->add_text($path);
231                            $path =~ s/(.)/$1 /g;
232                            $doc->add_hidden_text($path);
233    
234                            print STDERR $doc->dump_draft,"\n" if ($debug > 1);
235    
236                            # register the document object to the database
237                            if ($hest_db) {
238                                    $hest_db->put_doc($doc, $HyperEstraier::Database::PDCLEAN);
239                            } elsif ($hest_node) {
240                                    $hest_node->put_doc($doc);
241                            } else {
242                                    die "not supported";
243                            }
244                            $added++;
245                    }
246    
247                    print " $added";
248                    $hest_db->sync() if ($index_path);
249    
250                    $offset += EST_CHUNK;
251    
252            } while ($results == EST_CHUNK);
253    
254            if ($index_path) {
255                    print ", close";
256                    $hest_db->close();
257            }
258    
259            my $dur = (time() - $t) || 1;
260            printf(" [%.2f/s dur: %s]\n",
261                    ( $added / $dur ),
262                    fmt_time($dur)
263            );
264    }
265    
266    #---- /subs ----
267    
268    
269    ## update index ##
270    if (($opt{i} || $opt{j} || ($index_path && ! -e $TopDir . $index_path)) && !$opt{c}) {
271            # update all
272            print "force update of HyperEstraier index ";
273            print "importing existing data" unless (-e $TopDir . $index_path);
274            print "by -i flag" if ($opt{i});
275            print "by -j flag" if ($opt{j});
276            print "\n";
277            hest_update();
278    }
279    
280    ## create tables ##
281  if ($opt{c}) {  if ($opt{c}) {
282          sub do_index {          sub do_index {
283                  my $index = shift || return;                  my $index = shift || return;
284                  my ($table,$col,$unique) = split(/_/, $index);                  my ($table,$col,$unique) = split(/:/, $index);
285                  $unique ||= '';                  $unique ||= '';
286                  $index =~ s/,/_/g;                  $index =~ s/\W+/_/g;
287                    print "$index on $table($col)" . ( $unique ? "u" : "" ) . " ";
288                  $dbh->do(qq{ create $unique index $index on $table($col) });                  $dbh->do(qq{ create $unique index $index on $table($col) });
289          }          }
290    
291          print "creating tables...\n";          print "creating tables...\n";
292          
293          $dbh->do(qq{          $dbh->do( qq{
294                  create table hosts (                  create table hosts (
295                          ID      SERIAL          PRIMARY KEY,                          ID      SERIAL          PRIMARY KEY,
296                          name    VARCHAR(30)     NOT NULL,                          name    VARCHAR(30)     NOT NULL,
297                          IP      VARCHAR(15)                          IP      VARCHAR(15)
298                  );                              );            
299          });  
                 
         $dbh->do(qq{  
300                  create table shares (                  create table shares (
301                          ID      SERIAL          PRIMARY KEY,                          ID      SERIAL          PRIMARY KEY,
302                          hostID  INTEGER         NOT NULL references hosts(id),                          hostID  INTEGER         NOT NULL references hosts(id),
303                          name    VARCHAR(30)     NOT NULL,                          name    VARCHAR(30)     NOT NULL,
304                          share   VARCHAR(200)    NOT NULL,                          share   VARCHAR(200)    NOT NULL
                         localpath VARCHAR(200)        
305                  );                              );            
306          });  
307                            create table dvds (
308          $dbh->do(qq{                          ID      SERIAL          PRIMARY KEY,
309                            num     INTEGER         NOT NULL,
310                            name    VARCHAR(255)    NOT NULL,
311                            mjesto  VARCHAR(255)
312                    );
313    
314                  create table backups (                  create table backups (
315                            id      serial,
316                          hostID  INTEGER         NOT NULL references hosts(id),                          hostID  INTEGER         NOT NULL references hosts(id),
317                          num     INTEGER         NOT NULL,                          num     INTEGER         NOT NULL,
318                          date    integer         NOT NULL,                          date    integer         NOT NULL,
319                          type    CHAR(4)         not null,                          type    CHAR(4)         not null,
320                          shareID integer         not null references shares(id),                          shareID integer         not null references shares(id),
321                          size    integer         not null,                          size    bigint          not null,
322                          PRIMARY KEY(hostID, num, shareID)                          inc_size bigint         not null default -1,
323                            inc_deleted boolean     default false,
324                            parts   integer         not null default 1,
325                            PRIMARY KEY(id)
326                  );                              );            
         });  
327    
328          #do_index('backups_hostid,num_unique');                  create table files (
329                            ID              SERIAL,
330                            shareID         INTEGER NOT NULL references shares(id),
331                            backupNum       INTEGER NOT NULL,
332                            name            VARCHAR(255) NOT NULL,
333                            path            VARCHAR(255) NOT NULL,
334                            date            integer NOT NULL,
335                            type            INTEGER NOT NULL,
336                            size            bigint  NOT NULL,
337                            primary key(id)
338                    );
339    
340          $dbh->do(qq{                  create table archive (
341                  create table dvds (                          id              serial,
342                          ID      SERIAL          PRIMARY KEY,                          dvd_nr          int not null,
343                          num     INTEGER         NOT NULL,                          total_size      bigint default -1,
344                          name    VARCHAR(255)    NOT NULL,                          note            text,
345                          mjesto  VARCHAR(255)                          username        varchar(20) not null,
346                            date            timestamp default now(),
347                            primary key(id)
348                    );      
349    
350                    create table archive_backup (
351                            archive_id      int not null references archive(id) on delete cascade,
352                            backup_id       int not null references backups(id),
353                            primary key(archive_id, backup_id)
354                  );                  );
         });  
355    
356          $dbh->do(qq{                      create table archive_burned (
357                  create table files (                          archive_id      int references archive(id),
358                          ID      SERIAL          PRIMARY KEY,                            date            timestamp default now(),
359                          shareID INTEGER         NOT NULL references shares(id),                          part            int not null default 1,
360                          backupNum  INTEGER      NOT NULL,                          copy            int not null default 1,
361                          name       VARCHAR(255) NOT NULL,                          iso_size bigint default -1
362                          path       VARCHAR(255) NOT NULL,                  );
363                          date       integer      NOT NULL,  
364                          type       INTEGER      NOT NULL,                  create table backup_parts (
365                          size       INTEGER      NOT NULL,                          id serial,
366                          dvdid      INTEGER      references dvds(id)                              backup_id int references backups(id),
367                            part_nr int not null check (part_nr > 0),
368                            tar_size bigint not null check (tar_size > 0),
369                            size bigint not null check (size > 0),
370                            md5 text not null,
371                            items int not null check (items > 0),
372                            date timestamp default now(),
373                            primary key(id)
374                  );                  );
375          });          });
376    
377          print "creating indexes:";          print "creating indexes: ";
378    
379          foreach my $index (qw(          foreach my $index (qw(
380                  hosts_name                  hosts:name
381                  backups_hostID                  backups:hostID
382                  backups_num                  backups:num
383                  shares_hostID                  backups:shareID
384                  shares_name                  shares:hostID
385                  files_shareID                  shares:name
386                  files_path                  files:shareID
387                  files_name                  files:path
388                  files_date                  files:name
389                  files_size                  files:date
390                    files:size
391                    archive:dvd_nr
392                    archive_burned:archive_id
393                    backup_parts:backup_id,part_nr
394          )) {          )) {
                 print " $index";  
395                  do_index($index);                  do_index($index);
396          }          }
397    
398            print " creating sequence: ";
399            foreach my $seq (qw/dvd_nr/) {
400                    print "$seq ";
401                    $dbh->do( qq{ CREATE SEQUENCE $seq } );
402            }
403    
404    
405          print "...\n";          print "...\n";
406    
407          $dbh->commit;          $dbh->commit;
408    
409  }  }
410    
411    ## delete data before inseting ##
412  if ($opt{d}) {  if ($opt{d}) {
413          print "deleting ";          print "deleting ";
414          foreach my $table (qw(files dvds backups shares hosts)) {          foreach my $table (qw(files dvds backups shares hosts)) {
# Line 160  if ($opt{d}) { Line 420  if ($opt{d}) {
420          $dbh->commit;          $dbh->commit;
421  }  }
422    
423  if ($opt{v}) {  ## insert new values ##
         print "Debug level at $opt{v}\n";  
         $debug = $opt{v};  
 }  
   
 #################################INSERT VALUES#############################  
424    
425  # get hosts  # get hosts
426  $hosts = $bpc->HostInfoRead();  $hosts = $bpc->HostInfoRead();
# Line 190  WHERE hostID=? AND num=? AND shareid=? Line 445  WHERE hostID=? AND num=? AND shareid=?
445    
446  $sth->{insert_backups} = $dbh->prepare(qq{  $sth->{insert_backups} = $dbh->prepare(qq{
447  INSERT INTO backups (hostID, num, date, type, shareid, size)  INSERT INTO backups (hostID, num, date, type, shareid, size)
448  VALUES (?,?,?,?,?,?)  VALUES (?,?,?,?,?,-1)
449    });
450    
451    $sth->{update_backups_size} = $dbh->prepare(qq{
452    UPDATE backups SET size = ?
453    WHERE hostID = ? and num = ? and date = ? and type =? and shareid = ?
454  });  });
455    
456  $sth->{insert_files} = $dbh->prepare(qq{  $sth->{insert_files} = $dbh->prepare(qq{
# Line 199  INSERT INTO files Line 459  INSERT INTO files
459          VALUES (?,?,?,?,?,?,?)          VALUES (?,?,?,?,?,?,?)
460  });  });
461    
462  sub fmt_time {  my @hosts = keys %{$hosts};
463          my $t = shift || return;  my $host_nr = 0;
         my $out = "";  
         my ($ss,$mm,$hh) = gmtime($t);  
         $out .= "${hh}h" if ($hh);  
         $out .= sprintf("%02d:%02d", $mm,$ss);  
         return $out;  
 }  
464    
465  foreach my $host_key (keys %{$hosts}) {  foreach my $host_key (@hosts) {
466    
467          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";
468    
# Line 223  foreach my $host_key (keys %{$hosts}) { Line 477  foreach my $host_key (keys %{$hosts}) {
477                  $hostID = $dbh->last_insert_id(undef,undef,'hosts',undef);                  $hostID = $dbh->last_insert_id(undef,undef,'hosts',undef);
478          }          }
479    
480          print "host ".$hosts->{$host_key}->{'host'}.": ";          $host_nr++;
481            print "host ", $hosts->{$host_key}->{'host'}, " [",
482                    $host_nr, "/", ($#hosts + 1), "]: ";
483    
484          # get backups for a host          # get backups for a host
485          my @backups = $bpc->BackupInfoRead($hostname);          my @backups = $bpc->BackupInfoRead($hostname);
# Line 263  foreach my $host_key (keys %{$hosts}) { Line 519  foreach my $host_key (keys %{$hosts}) {
519                          next if ($count > 0);                          next if ($count > 0);
520    
521                          # dump some log                          # dump some log
522                          print strftime($t_fmt,localtime())," ", $share;                          print curr_time," ", $share;
   
                         my ($f, $nf, $d, $nd, $size) = recurseDir($bpc, $hostname, $files, $backupNum, $share, "", $shareID);  
523    
524                          $sth->{insert_backups}->execute(                          $sth->{insert_backups}->execute(
525                                  $hostID,                                  $hostID,
526                                  $backupNum,                                  $backupNum,
527                                  $backup->{'endTime'},                                  $backup->{'endTime'},
528                                  $backup->{'type'},                                  substr($backup->{'type'},0,4),
529                                  $shareID,                                  $shareID,
530                            );
531    
532                            my ($f, $nf, $d, $nd, $size) = recurseDir($bpc, $hostname, $files, $backupNum, $share, "", $shareID);
533    
534                            $sth->{update_backups_size}->execute(
535                                  $size,                                  $size,
536                                    $hostID,
537                                    $backupNum,
538                                    $backup->{'endTime'},
539                                    substr($backup->{'type'},0,4),
540                                    $shareID,
541                          );                          );
542    
543                          print " commit";                          print " commit";
# Line 286  foreach my $host_key (keys %{$hosts}) { Line 550  foreach my $host_key (keys %{$hosts}) {
550                                  ( ($f+$d) / $dur ),                                  ( ($f+$d) / $dur ),
551                                  fmt_time($dur)                                  fmt_time($dur)
552                          );                          );
553    
554                            hest_update($hostID, $shareID, $backupNum) if ($nf + $nd > 0);
555                  }                  }
556    
557          }          }
# Line 314  sub getShareID() { Line 580  sub getShareID() {
580    
581          $sth->{insert_share} ||= $dbh->prepare(qq{          $sth->{insert_share} ||= $dbh->prepare(qq{
582                  INSERT INTO shares                  INSERT INTO shares
583                          (hostID,name,share,localpath)                          (hostID,name,share)
584                  VALUES (?,?,?,?)                  VALUES (?,?,?)
585          });          });
586    
587          my $drop_down = $hostname . '/' . $share;          my $drop_down = $hostname . '/' . $share;
588          $drop_down =~ s#//+#/#g;          $drop_down =~ s#//+#/#g;
589    
590          $sth->{insert_share}->execute($hostID,$share, $drop_down ,undef);          $sth->{insert_share}->execute($hostID,$share, $drop_down);
591          return $dbh->last_insert_id(undef,undef,'shares',undef);          return $dbh->last_insert_id(undef,undef,'shares',undef);
592  }  }
593    
# Line 338  sub found_in_db { Line 604  sub found_in_db {
604                  SELECT 1 FROM files                  SELECT 1 FROM files
605                  WHERE shareID = ? and                  WHERE shareID = ? and
606                          path = ? and                          path = ? and
607                          date = ? and                          size = ? and
608                          size = ?                          ( date = ? or date = ? or date = ? )
609                  LIMIT 1                  LIMIT 1
610          });          });
611    
612          my @param = ($shareID,$path,$date,$size);          my @param = ($shareID,$path,$size,$date, $date-$dst_offset, $date+$dst_offset);
613          $sth->{file_in_db}->execute(@param);          $sth->{file_in_db}->execute(@param);
614          my $rows = $sth->{file_in_db}->rows;          my $rows = $sth->{file_in_db}->rows;
615          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 393  sub recurseDir($$$$$$$$) { Line 659  sub recurseDir($$$$$$$$) {
659                                  $filesInBackup->{$path_key}->{'size'}                                  $filesInBackup->{$path_key}->{'size'}
660                          ));                          ));
661    
662                            my $key_dst_prev = join(" ", (
663                                    $shareID,
664                                    $dir,
665                                    $path_key,
666                                    $filesInBackup->{$path_key}->{'mtime'} - $dst_offset,
667                                    $filesInBackup->{$path_key}->{'size'}
668                            ));
669    
670                            my $key_dst_next = join(" ", (
671                                    $shareID,
672                                    $dir,
673                                    $path_key,
674                                    $filesInBackup->{$path_key}->{'mtime'} + $dst_offset,
675                                    $filesInBackup->{$path_key}->{'size'}
676                            ));
677    
678                          my $found;                          my $found;
679                          if (! defined($beenThere->{$key}) && ! ($found = found_in_db($key, @data)) ) {                          if (
680                                    ! defined($beenThere->{$key}) &&
681                                    ! defined($beenThere->{$key_dst_prev}) &&
682                                    ! defined($beenThere->{$key_dst_next}) &&
683                                    ! ($found = found_in_db($key, @data))
684                            ) {
685                                  print STDERR "# key: $key [", $beenThere->{$key},"]" if ($debug >= 2);                                  print STDERR "# key: $key [", $beenThere->{$key},"]" if ($debug >= 2);
686    
687                                  if ($filesInBackup->{$path_key}->{'type'} == BPC_FTYPE_DIR) {                                  if ($filesInBackup->{$path_key}->{'type'} == BPC_FTYPE_DIR) {

Legend:
Removed from v.74  
changed lines
  Added in v.248

  ViewVC Help
Powered by ViewVC 1.1.26