/[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 7 by dpavlin, Thu Jun 23 10:14:10 2005 UTC revision 248 by dpavlin, Fri Dec 9 14:41:13 2005 UTC
# Line 1  Line 1 
1  #!/usr/local/bin/perl -w  #!/usr/local/bin/perl -w
 $| = 1;  
2    
3  use strict;  use strict;
 use DBI;  
4  use lib "__INSTALLDIR__/lib";  use lib "__INSTALLDIR__/lib";
5    
6    use DBI;
7  use BackupPC::Lib;  use BackupPC::Lib;
8  use BackupPC::View;  use BackupPC::View;
9  use Data::Dumper;  use Data::Dumper;
10  use Getopt::Std;  use Getopt::Std;
11    use Time::HiRes qw/time/;
12    use File::Pid;
13    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;
23    $|=1;
24    
25    my $start_t = time();
26    
27    my $pidfile = new File::Pid;
28    
29    if (my $pid = $pidfile->running ) {
30            die "$0 already running: $pid\n";
31    } elsif ($pidfile->pid ne $$) {
32            $pidfile->remove;
33            $pidfile = new File::Pid;
34    }
35    $pidfile->write;
36    print STDERR "$0 using pid ",$pidfile->pid," file ",$pidfile->file,"\n";
37    
38    my $t_fmt = '%Y-%m-%d %H:%M:%S';
39    
40  my $hosts;  my $hosts;
41  my $bpc = BackupPC::Lib->new || die;  my $bpc = BackupPC::Lib->new || die;
42  my %Conf = $bpc->Conf();  my %Conf = $bpc->Conf();
43  my $TopDir = $bpc->TopDir();  my $TopDir = $bpc->TopDir();
44  my @beenThere = ();  my $beenThere = {};
45    
46    my $dsn = $Conf{SearchDSN} || die "Need SearchDSN in config.pl\n";
47    my $user = $Conf{SearchUser} || '';
48    
49  my $dbh = DBI->connect("dbi:SQLite:dbname=$TopDir/$Conf{SearchDB}", "", "", { RaiseError => 1, AutoCommit => 0 });  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 });
53    
54  my %opt;  my %opt;
55    
56  if ( !getopts("cdu", \%opt ) ) {  if ( !getopts("cdm:v:ijf", \%opt ) ) {
57          print STDERR <<EOF;          print STDERR <<EOF;
58  usage: $0 (-c|-df|-u)  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          -u      Update database (import new revisions)          -m num  import just num increments for one host
64            -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  if ($opt{c})          my $skip_check = $opt{j} && print STDERR "Skipping check for existing files -- this should be used only with initital import\n";
123      {  
124        print "creating database...";          unless (defined($use_hest)) {
125                          print STDERR "HyperEstraier support not enabled in configuration\n";
126        $dbh->do(                  $use_hest = 0;
127            q{                  return;
128                create table hosts          }
129                  (   ID             INTEGER              PRIMARY KEY,  
130                      name             VARCHAR(30)        NOT NULL,          print curr_time," updating HyperEstraier:";
131                      IP       VARCHAR(20)        NOT NULL  
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}) {
282            sub do_index {
283                    my $index = shift || return;
284                    my ($table,$col,$unique) = split(/:/, $index);
285                    $unique ||= '';
286                    $index =~ s/\W+/_/g;
287                    print "$index on $table($col)" . ( $unique ? "u" : "" ) . " ";
288                    $dbh->do(qq{ create $unique index $index on $table($col) });
289            }
290    
291            print "creating tables...\n";
292    
293            $dbh->do( qq{
294                    create table hosts (
295                            ID      SERIAL          PRIMARY KEY,
296                            name    VARCHAR(30)     NOT NULL,
297                            IP      VARCHAR(15)
298                  );                              );            
299            }  
300        );                  create table shares (
301                                          ID      SERIAL          PRIMARY KEY,
302        $dbh->do(                          hostID  INTEGER         NOT NULL references hosts(id),
303            q{                          name    VARCHAR(30)     NOT NULL,
304                create table shares                          share   VARCHAR(200)    NOT NULL
                 (   ID             INTEGER           PRIMARY KEY,  
                     hostID         INTEGER           NOT NULL,  
                     name           VARCHAR(30)       NOT NULL,  
                     share          VARCHAR(200)      NOT NULL,  
                     localpath      VARCHAR(200)        
305                  );                              );            
306            }  
307        );                  create table dvds (
308                                    ID      SERIAL          PRIMARY KEY,
309        $dbh->do(                          num     INTEGER         NOT NULL,
310            q{                          name    VARCHAR(255)    NOT NULL,
311                create table backups                          mjesto  VARCHAR(255)
312                  ( hostID     INTEGER            NOT NULL,                  );
313                      num      INTEGER            NOT NULL,  
314                      date             DATE,                  create table backups (
315                      type             CHAR(1),                          id      serial,
316                      PRIMARY KEY(hostID, num)                          hostID  INTEGER         NOT NULL references hosts(id),
317                            num     INTEGER         NOT NULL,
318                            date    integer         NOT NULL,
319                            type    CHAR(4)         not null,
320                            shareID integer         not null references shares(id),
321                            size    bigint          not null,
322                            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        $dbh->do(                  create table files (
329            q{                          ID              SERIAL,
330                create table dvds                          shareID         INTEGER NOT NULL references shares(id),
331                  ( ID         INTEGER            PRIMARY KEY,                          backupNum       INTEGER NOT NULL,
332                      num      INTEGER            NOT NULL,                          name            VARCHAR(255) NOT NULL,
333                      name             VARCHAR(255)       NOT NULL,                          path            VARCHAR(255) NOT NULL,
334                      mjesto     VARCHAR(255)                          date            integer NOT NULL,
335                            type            INTEGER NOT NULL,
336                            size            bigint  NOT NULL,
337                            primary key(id)
338                  );                  );
           }  
       );  
339    
340        $dbh->do(                  create table archive (
341            q{                              id              serial,
342                create table files                          dvd_nr          int not null,
343                  (   ID         INTEGER          NOT NULL PRIMARY KEY,                            total_size      bigint default -1,
344                      shareID    INTEGER          NOT NULL,                          note            text,
345                      backupNum  INTEGER          NOT NULL,                          username        varchar(20) not null,
346                      name       VARCHAR(255)     NOT NULL,                          date            timestamp default now(),
347                      path       VARCHAR(255)     NOT NULL,                          primary key(id)
348                      fullpath   VARCHAR(255)     NOT NULL,                  );      
349                      date       TIMESTAMP        NOT NULL,  
350                      type       INTEGER          NOT NULL,                  create table archive_backup (
351                      size       INTEGER          NOT NULL,                          archive_id      int not null references archive(id) on delete cascade,
352                      dvdid      INTEGER                                    backup_id       int not null references backups(id),
353                            primary key(archive_id, backup_id)
354                  );                  );
           }  
       );  
       print "done\n";  
   }  
   
 if ($opt{d})  
   {  
       print("deleting db first...\n");  
         
       $dbh->do(  
           q{ DELETE FROM hosts; }  
           );  
       $dbh->do(  
           q{ DELETE FROM shares; }  
           );  
       $dbh->do(  
           q{ DELETE FROM files;}  
           );  
       $dbh->do(  
           q{ DELETE FROM dvds;}  
           );  
       $dbh->do(  
           q{ DELETE FROM backups; }  
           );  
   }  
355    
356  #################################INSERT VALUES#############################                  create table archive_burned (
357                            archive_id      int references archive(id),
358                            date            timestamp default now(),
359                            part            int not null default 1,
360                            copy            int not null default 1,
361                            iso_size bigint default -1
362                    );
363    
364                    create table backup_parts (
365                            id serial,
366                            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: ";
378    
379            foreach my $index (qw(
380                    hosts:name
381                    backups:hostID
382                    backups:num
383                    backups:shareID
384                    shares:hostID
385                    shares:name
386                    files:shareID
387                    files:path
388                    files:name
389                    files:date
390                    files:size
391                    archive:dvd_nr
392                    archive_burned:archive_id
393                    backup_parts:backup_id,part_nr
394            )) {
395                    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";
406    
407            $dbh->commit;
408    
409    }
410    
411    ## delete data before inseting ##
412    if ($opt{d}) {
413            print "deleting ";
414            foreach my $table (qw(files dvds backups shares hosts)) {
415                    print "$table ";
416                    $dbh->do(qq{ DELETE FROM $table });
417            }
418            print " done...\n";
419    
420            $dbh->commit;
421    }
422    
423    ## insert new values ##
424    
425  # get hosts  # get hosts
426  $hosts = $bpc->HostInfoRead("localhost");  $hosts = $bpc->HostInfoRead();
 my $host_key;  
427  my $hostID;  my $hostID;
428  my $shareID;  my $shareID;
429  foreach $host_key (keys %{$hosts})  
430  {  my $sth;
431    my $hostname = $hosts->{$host_key}->{'host'};  
432    my $backups;  $sth->{insert_hosts} = $dbh->prepare(qq{
433    my $sql;  INSERT INTO hosts (name, IP) VALUES (?,?)
434    });
435    $sql = q{ SELECT ID FROM hosts WHERE name=? };  
436    my $st = $dbh->prepare($sql);  $sth->{hosts_by_name} = $dbh->prepare(qq{
437    $st->bind_param(1,$hosts->{$host_key}->{'host'});  SELECT ID FROM hosts WHERE name=?
438    $st->execute();  });
439    my $tmp = $st->fetchrow_hashref();  
440    if ($tmp->{'ID'} ne "")  $sth->{backups_count} = $dbh->prepare(qq{
441        {  SELECT COUNT(*)
442            $hostID = $tmp->{'ID'};  FROM backups
443        }  WHERE hostID=? AND num=? AND shareid=?
444      else  });
445        {  
446            $sql = q{ INSERT INTO hosts ( ID, name, IP) VALUES (NULL,"}.  $sth->{insert_backups} = $dbh->prepare(qq{
447                      $hosts->{$host_key}->{'host'}."\", \"".  INSERT INTO backups (hostID, num, date, type, shareid, size)
448                     $hosts->{$host_key}->{'ip'}."\");";  VALUES (?,?,?,?,?,-1)
449    });
450            $dbh->do($sql);  
451            $hostID = $dbh->func('last_insert_rowid');  $sth->{update_backups_size} = $dbh->prepare(qq{
452    UPDATE backups SET size = ?
453        }  WHERE hostID = ? and num = ? and date = ? and type =? and shareid = ?
454    $st->finish();  });
455    print("processing host ".$hosts->{$host_key}->{'host'}.":\n");  
456    $sth->{insert_files} = $dbh->prepare(qq{
457    INSERT INTO files
458            (shareID, backupNum, name, path, date, type, size)
459            VALUES (?,?,?,?,?,?,?)
460    });
461    
462    my @hosts = keys %{$hosts};
463    my $host_nr = 0;
464    
465    foreach my $host_key (@hosts) {
466    
467            my $hostname = $hosts->{$host_key}->{'host'} || die "can't find host for $host_key";
468    
469            $sth->{hosts_by_name}->execute($hosts->{$host_key}->{'host'});
470    
471            unless (($hostID) = $sth->{hosts_by_name}->fetchrow_array()) {
472                    $sth->{insert_hosts}->execute(
473                            $hosts->{$host_key}->{'host'},
474                            $hosts->{$host_key}->{'ip'}
475                    );
476    
477                    $hostID = $dbh->last_insert_id(undef,undef,'hosts',undef);
478            }
479    
480            $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);
486    foreach my $backup (@backups)          my $incs = scalar @backups;
487    {          print  "$incs increments\n";
488      my $backupNum = $backup->{'num'};  
489      my @backupShares = ();          my $inc_nr = 0;
490            $beenThere = {};
491          
492      if ($opt{u})          foreach my $backup (@backups) {
493          {  
494              my $sql = q{                  $inc_nr++;
495                    SELECT COUNT(*) AS broj                  last if ($opt{m} && $inc_nr > $opt{m});
496                    FROM backups  
497                    WHERE hostID=? AND                  my $backupNum = $backup->{'num'};
498                          num=?                  my @backupShares = ();
499                  };  
500                                printf("%-10s %2d/%-2d #%-2d %s %5s/%5s files (date: %s dur: %s)\n",
501              my $st  = $dbh->prepare($sql);                          $hosts->{$host_key}->{'host'},
502              $st->bind_param(1,$hostID);                          $inc_nr, $incs, $backupNum,
503              $st->bind_param(2,$backupNum);                          $backup->{type} || '?',
504              $st->execute();                          $backup->{nFilesNew} || '?', $backup->{nFiles} || '?',
505              my $tmp = $st->fetchrow_hashref();                          strftime($t_fmt,localtime($backup->{startTime})),
506              $st->finish();                          fmt_time($backup->{endTime} - $backup->{startTime})
507              if ($tmp->{'broj'} > 0)                  );
508                {  
509                    next;                  my $files = BackupPC::View->new($bpc, $hostname, \@backups, 1);
510                }                  foreach my $share ($files->shareList($backupNum)) {
511          }  
512                                  my $t = time();
513      print "\tprocessing backup no. $backupNum...";  
514      my $sql =                              $shareID = getShareID($share, $hostID, $hostname);
515          q{                  
516              INSERT INTO backups (hostID, num, date, type)                          $sth->{backups_count}->execute($hostID, $backupNum, $shareID);
517                VALUES                          my ($count) = $sth->{backups_count}->fetchrow_array();
518                (}.$hostID.",". $backupNum.q{, }.$backup->{'endTime'}.",\"". $backup->{'type'}.q{");                          # skip if allready in database!
519           };                          next if ($count > 0);
520      $dbh->do($sql);  
521                            # dump some log
522      my $files = BackupPC::View->new($bpc, $hostname, \@backups);                          print curr_time," ", $share;
523      @backupShares = $files->shareList($backupNum);  
524      foreach my $share (@backupShares)                          $sth->{insert_backups}->execute(
525      {                                        $hostID,
526        my @flattenedFiles = ();                                  $backupNum,
527        clearBeenThereCache();                                  $backup->{'endTime'},
528        print "\n\t\tprocessing share ".$share."...";                                  substr($backup->{'type'},0,4),
529        $shareID = getShareID($share, $hostID, $hostname);                                  $shareID,
530                                    );
531        @flattenedFiles = recurseDir($bpc, $hostname, \@backups, $backupNum, $share, "");  
532        print "done\n";                          my ($f, $nf, $d, $nd, $size) = recurseDir($bpc, $hostname, $files, $backupNum, $share, "", $shareID);
533        print "\t\tinserting data into db...";  
534        foreach my $file (@flattenedFiles)                          $sth->{update_backups_size}->execute(
535            {                                  $size,
536                $dbh->do("INSERT INTO files(ID, shareID, backupNum, name, path, fullpath, date, type, size) VALUES "                                  $hostID,
537                    ."( NULL, $shareID, "                                  $backupNum,
538                    .$backupNum.", \""                                  $backup->{'endTime'},
539                    .$file->{'fileName'}."\", \""                                  substr($backup->{'type'},0,4),
540                    .$file->{'relPath'}. "\", \""                                  $shareID,
541                    .$file->{'fullPath'}."\", "                          );
542                    .$file->{'mtime'}.", "  
543                    .$file->{'type'}.", "                          print " commit";
544                    .$file->{'size'}.")"                          $dbh->commit();
545                    );  
546            }                          my $dur = (time() - $t) || 1;
547        print "done\n";                          printf(" %d/%d files %d/%d dirs %0.2f MB [%.2f/s dur: %s]\n",
548      }                                  $nf, $f, $nd, $d,
549    }                                  ($size / 1024 / 1024),
550    print "done.\n";                                  ( ($f+$d) / $dur ),
551                                    fmt_time($dur)
552                            );
553    
554                            hest_update($hostID, $shareID, $backupNum) if ($nf + $nd > 0);
555                    }
556    
557            }
558  }  }
559    undef $sth;
560  $dbh->commit();  $dbh->commit();
561  $dbh->disconnect();  $dbh->disconnect();
562    
563    print "total duration: ",fmt_time(time() - $start_t),"\n";
564    
565    $pidfile->remove;
566    
567    sub getShareID() {
568    
569            my ($share, $hostID, $hostname) = @_;
570    
571            $sth->{share_id} ||= $dbh->prepare(qq{
572                    SELECT ID FROM shares WHERE hostID=? AND name=?
573            });
574    
575            $sth->{share_id}->execute($hostID,$share);
576    
577            my ($id) = $sth->{share_id}->fetchrow_array();
578    
579            return $id if (defined($id));
580    
581            $sth->{insert_share} ||= $dbh->prepare(qq{
582                    INSERT INTO shares
583                            (hostID,name,share)
584                    VALUES (?,?,?)
585            });
586    
587            my $drop_down = $hostname . '/' . $share;
588            $drop_down =~ s#//+#/#g;
589    
590            $sth->{insert_share}->execute($hostID,$share, $drop_down);
591            return $dbh->last_insert_id(undef,undef,'shares',undef);
592    }
593    
594    sub found_in_db {
595    
596  sub haveBeenThere          my @data = @_;
597  {          shift @data;
598    my ($where) = @_;  
599              my ($key, $shareID,undef,$name,$path,$date,undef,$size) = @_;
600    foreach my $st (@beenThere)  
601    {          return $beenThere->{$key} if (defined($beenThere->{$key}));
602      if ($where eq $st)  
603      {          $sth->{file_in_db} ||= $dbh->prepare(qq{
604        return 1;                  SELECT 1 FROM files
605      }                  WHERE shareID = ? and
606    }                          path = ? and
607                              size = ? and
608    push(@beenThere, $where);                          ( date = ? or date = ? or date = ? )
609    return 0;                  LIMIT 1
610  }          });
611    
612  sub clearBeenThereCache          my @param = ($shareID,$path,$size,$date, $date-$dst_offset, $date+$dst_offset);
613  {          $sth->{file_in_db}->execute(@param);
614    @beenThere = ();          my $rows = $sth->{file_in_db}->rows;
615  }          print STDERR "## found_in_db($shareID,$path,$date,$size) ",( $rows ? '+' : '-' ), join(" ",@param), "\n" if ($debug >= 3);
616    
617  sub getShareID()          $beenThere->{$key}++;
618    {  
619        my ($share, $hostID, $hostname) = @_;          $sth->{'insert_files'}->execute(@data) unless ($rows);
620        my $tmp;          return $rows;
621          }
       my $st = $dbh -> prepare(" SELECT shares.ID AS ID FROM shares WHERE hostID=? AND name=?");  
       $st -> execute($hostID,$share);  
       my $tmp = $st->fetchrow_hashref();  
       $st->finish();  
       if ($tmp)  
         {  
             return $tmp->{'ID'};  
         }  
       my $sql =  
           q{  
               INSERT INTO shares(ID,hostID,name,share,localpath)  
                 VALUES    
                (NULL,}.                    
               "$hostID,\"$share\",\"//$hostname$share\",NULL);";                
       $dbh->do($sql);  
       return $dbh->func('last_insert_rowid');            
   }  
622    
623  ####################################################  ####################################################
624  # recursing through filesystem structure and       #  # recursing through filesystem structure and       #
625  # and returning flattened files list               #  # and returning flattened files list               #
626  ####################################################  ####################################################
627  sub recurseDir  sub recurseDir($$$$$$$$) {
 {  
   my ($bpc, $hostname, $backups, $backupNo, $share, $dir) = @_;  
   my @ret = ();  
   my $files = BackupPC::View->new($bpc, $hostname, $backups);              
   my $filesInBackup = $files->dirAttrib($backupNo, $share, $dir);  
   my $file_key = "";  
628    
629            my ($bpc, $hostname, $files, $backupNum, $share, $dir, $shareID) = @_;
630    # first, add all the entries in current directory  
631    foreach $file_key (keys %{$filesInBackup})          print STDERR "\nrecurse($hostname,$backupNum,$share,$dir,$shareID)\n" if ($debug >= 1);
632    {  
633      push(@ret, {          my ($nr_files, $new_files, $nr_dirs, $new_dirs, $size) = (0,0,0,0,0);
634                   'fileName' => $file_key,  
635                   'relPath'  => $filesInBackup->{$file_key}->{'relPath'},          { # scope
636                   'fullPath' => $filesInBackup->{$file_key}->{'fullPath'},                  my @stack;
637                   'sharePath'=> $filesInBackup->{$file_key}->{'sharePathM'},  
638                   'size'     => $filesInBackup->{$file_key}->{'size'},                  print STDERR "# dirAttrib($backupNum, $share, $dir)\n" if ($debug >= 2);
639                   'mtime'    => $filesInBackup->{$file_key}->{'mtime'},                  my $filesInBackup = $files->dirAttrib($backupNum, $share, $dir);
640                   'type'     => $filesInBackup->{$file_key}->{'type'}  
641                 });                    # first, add all the entries in current directory
642    }                  foreach my $path_key (keys %{$filesInBackup}) {
643                                print STDERR "# file ",Dumper($filesInBackup->{$path_key}),"\n" if ($debug >= 3);
644    # then, recurse thru subfolders                          my @data = (
645    foreach my $fold (@ret)                                  $shareID,
646    {                                  $backupNum,
647     if ($fold->{'type'} == BPC_FTYPE_DIR &&                                  $path_key,
648         haveBeenThere($fold->{'relPath'}) != 1                                  $filesInBackup->{$path_key}->{'relPath'},
649        )                                  $filesInBackup->{$path_key}->{'mtime'},
650      {                                  $filesInBackup->{$path_key}->{'type'},
651                                          $filesInBackup->{$path_key}->{'size'}
652        push(@ret,                          );
653             recurseDir($bpc, $hostname, $backups, $backupNo, $share, $fold->{'relPath'})  
654            );                          my $key = join(" ", (
655      }                                  $shareID,
656    }                                  $dir,
657    return @ret;                                  $path_key,
658                                    $filesInBackup->{$path_key}->{'mtime'},
659                                    $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;
679                            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);
686    
687                                    if ($filesInBackup->{$path_key}->{'type'} == BPC_FTYPE_DIR) {
688                                            $new_dirs++ unless ($found);
689                                            print STDERR " dir\n" if ($debug >= 2);
690                                    } else {
691                                            $new_files++ unless ($found);
692                                            print STDERR " file\n" if ($debug >= 2);
693                                    }
694                                    $size += $filesInBackup->{$path_key}->{'size'} || 0;
695                            }
696    
697                            if ($filesInBackup->{$path_key}->{'type'} == BPC_FTYPE_DIR) {
698                                    $nr_dirs++;
699    
700                                    my $full_path = $dir . '/' . $path_key;
701                                    push @stack, $full_path;
702                                    print STDERR "### store to stack: $full_path\n" if ($debug >= 3);
703    
704    #                               my ($f,$nf,$d,$nd) = recurseDir($bpc, $hostname, $backups, $backupNum, $share, $path_key, $shareID) unless ($beenThere->{$key});
705    #
706    #                               $nr_files += $f;
707    #                               $new_files += $nf;
708    #                               $nr_dirs += $d;
709    #                               $new_dirs += $nd;
710    
711                            } else {
712                                    $nr_files++;
713                            }
714                    }
715    
716                    print STDERR "## STACK ",join(", ", @stack),"\n" if ($debug >= 2);
717    
718                    while ( my $dir = shift @stack ) {
719                            my ($f,$nf,$d,$nd, $s) = recurseDir($bpc, $hostname, $files, $backupNum, $share, $dir, $shareID);
720                            print STDERR "# $dir f: $f nf: $nf d: $d nd: $nd\n" if ($debug >= 1);
721                            $nr_files += $f;
722                            $new_files += $nf;
723                            $nr_dirs += $d;
724                            $new_dirs += $nd;
725                            $size += $s;
726                    }
727            }
728    
729            return ($nr_files, $new_files, $nr_dirs, $new_dirs, $size);
730  }  }
731    

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

  ViewVC Help
Powered by ViewVC 1.1.26