/[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 6 by dpavlin, Thu Jun 23 09:47:59 2005 UTC revision 52 by dpavlin, Sat Aug 20 16:45:02 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    
15  use constant BPC_FTYPE_DIR => 5;  use constant BPC_FTYPE_DIR => 5;
16    
17    my $debug = 0;
18    $|=1;
19    
20    my $start_t = time();
21    
22    my $pidfile = new File::Pid;
23    
24    if (my $pid = $pidfile->running ) {
25            die "$0 already running: $pid\n";
26    } elsif ($pidfile->pid ne $$) {
27            $pidfile->remove;
28            $pidfile = new File::Pid;
29    }
30    $pidfile->write;
31    print STDERR "$0 using pid ",$pidfile->pid," file ",$pidfile->file,"\n";
32    
33    my $t_fmt = '%Y-%m-%d %H:%M:%S';
34    
35  my $hosts;  my $hosts;
36  my $bpc = BackupPC::Lib->new || die;  my $bpc = BackupPC::Lib->new || die;
37  my %Conf = $bpc->Conf();  my %Conf = $bpc->Conf();
38  my $TopDir = $bpc->TopDir();  my $TopDir = $bpc->TopDir();
39  my @beenThere = ();  my $beenThere = {};
40    
41  print Dumper(\%Conf);  my $dsn = $Conf{SearchDSN} || die "Need SearchDSN in config.pl\n";
42    my $user = $Conf{SearchUser} || '';
43    
44  my $dbh = DBI->connect("dbi:SQLite:dbname=$TopDir/$Conf{SearchDB}", "", "", { RaiseError => 1, AutoCommit => 0 });  my $dbh = DBI->connect($dsn, $user, "", { RaiseError => 1, AutoCommit => 0 });
45    
46  my %opt;  my %opt;
47    
48  if ( !getopts("cdu", \%opt ) ) {  if ( !getopts("cdm:v:", \%opt ) ) {
49          print STDERR <<EOF;          print STDERR <<EOF;
50  usage: $0 (-c|-df|-u)  usage: $0 [-c|-d] [-m num] [-v|-v level]
51    
52  Options:  Options:
53          -c      Create database on first use          -c      create database on first use
54          -d      Delete database before import          -d      delete database before import
55          -u      Update database (import new revisions)          -m num  import just num increments for one host
56            -v num  set verbosity (debug) level (default $debug)
57  EOF  EOF
58          exit 1;          exit 1;
59  }  }
60    
61  ###################################create tables############################3  ###################################create tables############################3
62    
63  if ($opt{c})  if ($opt{c}) {
64      {          sub do_index {
65        print "creating database...";                  my $index = shift || return;
66                    my ($table,$col,$unique) = split(/_/, $index);
67                    $unique ||= '';
68                    $index =~ s/,/_/g;
69                    $dbh->do(qq{ create $unique index $index on $table($col) });
70            }
71    
72            print "creating tables...\n";
73                
74        $dbh->do(          $dbh->do(qq{
75            q{                  create table hosts (
76                create table hosts                          ID      SERIAL          PRIMARY KEY,
77                  (   ID             INTEGER              PRIMARY KEY,                          name    VARCHAR(30)     NOT NULL,
78                      name             VARCHAR(30)        NOT NULL,                          IP      VARCHAR(15)
                     IP       VARCHAR(20)        NOT NULL  
79                  );                              );            
80            }          });
       );  
81                                
82        $dbh->do(          $dbh->do(qq{
83            q{                  create table shares (
84                create table shares                          ID      SERIAL          PRIMARY KEY,
85                  (   ID             INTEGER           PRIMARY KEY,                          hostID  INTEGER         NOT NULL references hosts(id),
86                      hostID         INTEGER           NOT NULL,                          name    VARCHAR(30)     NOT NULL,
87                      name           VARCHAR(30)       NOT NULL,                          share   VARCHAR(200)    NOT NULL,
88                      share          VARCHAR(200)      NOT NULL,                          localpath VARCHAR(200)      
                     localpath      VARCHAR(200)        
89                  );                              );            
90            }          });
       );  
91                    
92        $dbh->do(          $dbh->do(qq{
93            q{                  create table backups (
94                create table backups                          hostID  INTEGER         NOT NULL references hosts(id),
95                  ( hostID     INTEGER            NOT NULL,                          num     INTEGER         NOT NULL,
96                      num      INTEGER            NOT NULL,                          date    integer         NOT NULL,
97                      date             DATE,                          type    CHAR(4)         not null,
98                      type             CHAR(1),                          PRIMARY KEY(hostID, num)
                     PRIMARY KEY(hostID, num)  
99                  );                              );            
100            }          });
101        );  
102            do_index('backups_hostid,num_unique');
103    
104        $dbh->do(          $dbh->do(qq{
105            q{                  create table dvds (
106                create table dvds                          ID      SERIAL          PRIMARY KEY,
107                  ( ID         INTEGER            PRIMARY KEY,                          num     INTEGER         NOT NULL,
108                      num      INTEGER            NOT NULL,                          name    VARCHAR(255)    NOT NULL,
109                      name             VARCHAR(255)       NOT NULL,                          mjesto  VARCHAR(255)
                     mjesto     VARCHAR(255)  
110                  );                  );
111            }          });
       );  
112    
113        $dbh->do(          $dbh->do(qq{    
114            q{                      create table files (
115                create table files                          ID      SERIAL          PRIMARY KEY,  
116                  (   ID         INTEGER          NOT NULL PRIMARY KEY,                            shareID INTEGER         NOT NULL references shares(id),
117                      shareID    INTEGER          NOT NULL,                          backupNum  INTEGER      NOT NULL,
118                      backupNum  INTEGER          NOT NULL,                          name       VARCHAR(255) NOT NULL,
119                      name       VARCHAR(255)     NOT NULL,                          path       VARCHAR(255) NOT NULL,
120                      path       VARCHAR(255)     NOT NULL,                          fullpath   VARCHAR(255) NOT NULL,
121                      fullpath   VARCHAR(255)     NOT NULL,                          date       integer      NOT NULL,
122                      date       TIMESTAMP        NOT NULL,                          type       INTEGER      NOT NULL,
123                      type       INTEGER          NOT NULL,                          size       INTEGER      NOT NULL,
124                      size       INTEGER          NOT NULL,                          dvdid      INTEGER      references dvds(id)    
                     dvdid      INTEGER            
125                  );                  );
126            }          });
127        );  
128        print "done\n";          print "creating indexes:";
129    }  
130            foreach my $index (qw(
131  if ($opt{d})                  hosts_name
132    {                  backups_hostID
133        print("deleting db first...\n");                  backups_num
134                          shares_hostID
135        $dbh->do(                  shares_name
136            q{ DELETE FROM hosts; }                  files_shareID
137            );                  files_path
138        $dbh->do(                  files_name
139            q{ DELETE FROM shares; }                  files_date
140            );                  files_size
141        $dbh->do(          )) {
142            q{ DELETE FROM files;}                  print " $index";
143            );                  do_index($index);
144        $dbh->do(          }
145            q{ DELETE FROM dvds;}          print "...\n";
146            );  
147        $dbh->do(          $dbh->commit;
148            q{ DELETE FROM backups; }  
149            );  }
150    }  
151    if ($opt{d}) {
152            print "deleting ";
153            foreach my $table (qw(files dvds backups shares hosts)) {
154                    print "$table ";
155                    $dbh->do(qq{ DELETE FROM $table });
156            }
157            print " done...\n";
158    
159            $dbh->commit;
160    }
161    
162    if ($opt{v}) {
163            print "Debug level at $opt{v}\n";
164            $debug = $opt{v};
165    }
166    
167  #################################INSERT VALUES#############################  #################################INSERT VALUES#############################
168    
169  # get hosts  # get hosts
170  $hosts = $bpc->HostInfoRead("localhost");  $hosts = $bpc->HostInfoRead();
 my $host_key;  
171  my $hostID;  my $hostID;
172  my $shareID;  my $shareID;
173  foreach $host_key (keys %{$hosts})  
174  {  my $sth;
175    my $hostname = $hosts->{$host_key}->{'host'};  
176    my $backups;  $sth->{insert_hosts} = $dbh->prepare(qq{
177    my $sql;  INSERT INTO hosts (name, IP) VALUES (?,?)
178    });
179    $sql = q{ SELECT ID FROM hosts WHERE name=? };  
180    my $st = $dbh->prepare($sql);  $sth->{hosts_by_name} = $dbh->prepare(qq{
181    $st->bind_param(1,$hosts->{$host_key}->{'host'});  SELECT ID FROM hosts WHERE name=?
182    $st->execute();  });
183    my $tmp = $st->fetchrow_hashref();  
184    if ($tmp->{'ID'} ne "")  $sth->{backups_broj} = $dbh->prepare(qq{
185        {  SELECT COUNT(*)
186            $hostID = $tmp->{'ID'};  FROM backups
187        }  WHERE hostID=? AND num=?
188      else  });
189        {  
190            $sql = q{ INSERT INTO hosts ( ID, name, IP) VALUES (NULL,"}.  $sth->{insert_backups} = $dbh->prepare(qq{
191                      $hosts->{$host_key}->{'host'}."\", \"".  INSERT INTO backups (hostID, num, date, type)
192                     $hosts->{$host_key}->{'ip'}."\");";  VALUES (?,?,?,?)
193    });
194            $dbh->do($sql);  
195            $hostID = $dbh->func('last_insert_rowid');  $sth->{insert_files} = $dbh->prepare(qq{
196    INSERT INTO files
197        }          (shareID, backupNum, name, path, fullpath, date, type, size)
198    $st->finish();          VALUES (?,?,?,?,?,?,?,?)
199    print("processing host ".$hosts->{$host_key}->{'host'}.":\n");  });
200    
201    sub fmt_time {
202            my $t = shift || return;
203            my $out = "";
204            my ($ss,$mm,$hh) = gmtime($t);
205            $out .= "${hh}h" if ($hh);
206            $out .= sprintf("%02d:%02d", $mm,$ss);
207            return $out;
208    }
209    
210    foreach my $host_key (keys %{$hosts}) {
211    
212            my $hostname = $hosts->{$host_key}->{'host'} || die "can't find host for $host_key";
213    
214            $sth->{hosts_by_name}->execute($hosts->{$host_key}->{'host'});
215    
216            unless (($hostID) = $sth->{hosts_by_name}->fetchrow_array()) {
217                    $sth->{insert_hosts}->execute(
218                            $hosts->{$host_key}->{'host'},
219                            $hosts->{$host_key}->{'ip'}
220                    );
221    
222                    $hostID = $dbh->last_insert_id(undef,undef,'hosts',undef);
223            }
224    
225            print("host ".$hosts->{$host_key}->{'host'}.": ");
226    
227    # get backups for a host          # get backups for a host
228    my @backups = $bpc->BackupInfoRead($hostname);          my @backups = $bpc->BackupInfoRead($hostname);
229    foreach my $backup (@backups)          print scalar @backups, " increments\n";
230    {  
231      my $backupNum = $backup->{'num'};          my $inc_nr = 0;
232      my @backupShares = ();  
233            foreach my $backup (@backups) {
234    
235                    $inc_nr++;
236                    last if ($opt{m} && $inc_nr > $opt{m});
237    
238                    my $backupNum = $backup->{'num'};
239                    my @backupShares = ();
240    
241                    print $hosts->{$host_key}->{'host'},
242                            "\t#$backupNum\t", $backup->{type} || '?', " ",
243                            $backup->{nFilesNew} || '?', "/", $backup->{nFiles} || '?',
244                            " files\n";
245    
246                    $sth->{backups_broj}->execute($hostID, $backupNum);
247                    my ($broj) = $sth->{backups_broj}->fetchrow_array();
248                    next if ($broj > 0);
249    
250                    $sth->{insert_backups}->execute(
251                            $hostID,
252                            $backupNum,
253                            $backup->{'endTime'},
254                            $backup->{'type'}
255                    );
256                    $dbh->commit();
257    
258                    my $files = BackupPC::View->new($bpc, $hostname, \@backups, 1);
259                    foreach my $share ($files->shareList($backupNum)) {
260    
261                            my $t = time();
262    
263                            print strftime($t_fmt,localtime())," ", $share;
264                            $shareID = getShareID($share, $hostID, $hostname);
265                    
266                            my ($f, $nf, $d, $nd) = recurseDir($bpc, $hostname, $files, $backupNum, $share, "", $shareID);
267                            my $dur = (time() - $t) || 1;
268                            printf(" %d/%d files %d/%d dirs [%.2f/s dur: %s]\n",
269                                    $nf, $f, $nd, $d,
270                                    ( ($f+$d) / $dur ),
271                                    fmt_time($dur)
272                            );
273                            $dbh->commit();
274                    }
275    
         
     if ($opt{u})  
         {  
             my $sql = q{  
                   SELECT COUNT(*) AS broj  
                   FROM backups  
                   WHERE hostID=? AND  
                         num=?  
                 };  
               
             my $st  = $dbh->prepare($sql);  
             $st->bind_param(1,$hostID);  
             $st->bind_param(2,$backupNum);  
             $st->execute();  
             my $tmp = $st->fetchrow_hashref();  
             $st->finish();  
             if ($tmp->{'broj'} > 0)  
               {  
                   next;  
               }  
276          }          }
         
     print "\tprocessing backup no. $backupNum...";  
     my $sql =      
         q{  
             INSERT INTO backups (hostID, num, date, type)  
               VALUES  
               (}.$hostID.",". $backupNum.q{, }.$backup->{'endTime'}.",\"". $backup->{'type'}.q{");  
          };  
     $dbh->do($sql);  
   
     my $files = BackupPC::View->new($bpc, $hostname, \@backups);  
     @backupShares = $files->shareList($backupNum);  
     foreach my $share (@backupShares)  
     {        
       my @flattenedFiles = ();  
       clearBeenThereCache();  
       print "\n\t\tprocessing share ".$share."...";  
       $shareID = getShareID($share, $hostID, $hostname);  
           
       @flattenedFiles = recurseDir($bpc, $hostname, \@backups, $backupNum, $share, "");  
       print "done\n";  
       print "\t\tinserting data into db...";  
       foreach my $file (@flattenedFiles)  
           {  
               $dbh->do("INSERT INTO files(ID, shareID, backupNum, name, path, fullpath, date, type, size) VALUES "  
                   ."( NULL, $shareID, "  
                   .$backupNum.", \""  
                   .$file->{'fileName'}."\", \""  
                   .$file->{'relPath'}. "\", \""  
                   .$file->{'fullPath'}."\", "  
                   .$file->{'mtime'}.", "  
                   .$file->{'type'}.", "  
                   .$file->{'size'}.")"  
                   );  
           }  
       print "done\n";  
     }  
   }  
   print "done.\n";  
277  }  }
278    undef $sth;
279  $dbh->commit();  $dbh->commit();
280  $dbh->disconnect();  $dbh->disconnect();
281    
282    print "total duration: ",fmt_time(time() - $start_t),"\n";
283    
284  sub haveBeenThere  $pidfile->remove;
285  {  
286    my ($where) = @_;  sub getShareID() {
287      
288    foreach my $st (@beenThere)          my ($share, $hostID, $hostname) = @_;
289    {  
290      if ($where eq $st)          $sth->{share_id} ||= $dbh->prepare(qq{
291      {                  SELECT ID FROM shares WHERE hostID=? AND name=?
292        return 1;          });
293      }  
294    }          $sth->{share_id}->execute($hostID,$share);
295      
296    push(@beenThere, $where);          my ($id) = $sth->{share_id}->fetchrow_array();
297    return 0;  
298  }          return $id if (defined($id));
299    
300            $sth->{insert_share} ||= $dbh->prepare(qq{
301                    INSERT INTO shares
302                            (hostID,name,share,localpath)
303                    VALUES (?,?,?,?)
304            });
305    
306            my $drop_down = $hostname . '/' . $share;
307            $drop_down =~ s#//+#/#g;
308    
309  sub clearBeenThereCache          $sth->{insert_share}->execute($hostID,$share, $drop_down ,undef);
310  {          return $dbh->last_insert_id(undef,undef,'shares',undef);
   @beenThere = ();  
311  }  }
312    
313  sub getShareID()  sub found_in_db {
314    {  
315        my ($share, $hostID, $hostname) = @_;          my @data = @_;
316        my $tmp;          shift @data;
317          
318        my $st = $dbh -> prepare(" SELECT shares.ID AS ID FROM shares WHERE hostID=? AND name=?");          my ($key, $shareID,undef,$name,$path,undef,$date,undef,$size) = @_;
319        $st -> execute($hostID,$share);  
320        my $tmp = $st->fetchrow_hashref();          return $beenThere->{$key} if (defined($beenThere->{$key}));
321        $st->finish();  
322        if ($tmp)          $sth->{file_in_db} ||= $dbh->prepare(qq{
323          {                  SELECT 1 FROM files
324              return $tmp->{'ID'};                  WHERE shareID = ? and
325          }                          path = ? and
326        my $sql =                          name = ? and
327            q{                          date = ? and
328                INSERT INTO shares(ID,hostID,name,share,localpath)                          size = ?
329                  VALUES            });
330                 (NULL,}.                    
331                "$hostID,\"$share\",\"//$hostname$share\",NULL);";                        my @param = ($shareID,$path,$name,$date,$size);
332        $dbh->do($sql);          $sth->{file_in_db}->execute(@param);
333        return $dbh->func('last_insert_rowid');                    my $rows = $sth->{file_in_db}->rows;
334    }          print STDERR "## found_in_db ",( $rows ? '+' : '-' ), join(" ",@param), "\n" if ($debug >= 3);
335    
336            $beenThere->{$key}++;
337    
338            $sth->{'insert_files'}->execute(@data) unless ($rows);
339            return $rows;
340    }
341    
342  ####################################################  ####################################################
343  # recursing through filesystem structure and       #  # recursing through filesystem structure and       #
344  # and returning flattened files list               #  # and returning flattened files list               #
345  ####################################################  ####################################################
346  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 = "";  
347    
348            my ($bpc, $hostname, $files, $backupNum, $share, $dir, $shareID) = @_;
349    # first, add all the entries in current directory  
350    foreach $file_key (keys %{$filesInBackup})          print STDERR "\nrecurse($hostname,$backupNum,$share,$dir,$shareID)\n" if ($debug >= 1);
351    {  
352      push(@ret, {          my ($nr_files, $new_files, $nr_dirs, $new_dirs) = (0,0,0,0);
353                   'fileName' => $file_key,  
354                   'relPath'  => $filesInBackup->{$file_key}->{'relPath'},          { # scope
355                   'fullPath' => $filesInBackup->{$file_key}->{'fullPath'},                  my @stack;
356                   'sharePath'=> $filesInBackup->{$file_key}->{'sharePathM'},  
357                   'size'     => $filesInBackup->{$file_key}->{'size'},                  print STDERR "# dirAttrib($backupNum, $share, $dir)\n" if ($debug >= 2);
358                   'mtime'    => $filesInBackup->{$file_key}->{'mtime'},                  my $filesInBackup = $files->dirAttrib($backupNum, $share, $dir);
359                   'type'     => $filesInBackup->{$file_key}->{'type'}  
360                 });                    # first, add all the entries in current directory
361    }                  foreach my $path_key (keys %{$filesInBackup}) {
362                                my @data = (
363    # then, recurse thru subfolders                                  $shareID,
364    foreach my $fold (@ret)                                  $backupNum,
365    {                                  $path_key,
366     if ($fold->{'type'} == BPC_FTYPE_DIR &&                                  $filesInBackup->{$path_key}->{'relPath'},
367         haveBeenThere($fold->{'relPath'}) != 1                                  $filesInBackup->{$path_key}->{'fullPath'},
368        )          #                       $filesInBackup->{$path_key}->{'sharePathM'},
369      {                                  $filesInBackup->{$path_key}->{'mtime'},
370                                          $filesInBackup->{$path_key}->{'type'},
371        push(@ret,                                  $filesInBackup->{$path_key}->{'size'}
372             recurseDir($bpc, $hostname, $backups, $backupNo, $share, $fold->{'relPath'})                          );
373            );  
374      }                          my $key = join(" ", (
375    }                                  $shareID,
376    return @ret;                                  $dir,
377                                    $path_key,
378                                    $filesInBackup->{$path_key}->{'mtime'},
379                                    $filesInBackup->{$path_key}->{'size'}
380                            ));
381    
382    
383                            if (! defined($beenThere->{$key}) && ! found_in_db($key, @data)) {
384                                    print STDERR "# key: $key [", $beenThere->{$key},"]" if ($debug >= 2);
385    
386                                    if ($filesInBackup->{$path_key}->{'type'} == BPC_FTYPE_DIR) {
387                                            $new_dirs++;
388                                            print STDERR " dir\n" if ($debug >= 2);
389                                    } else {
390                                            $new_files++;
391                                            print STDERR " file\n" if ($debug >= 2);
392                                    }
393                            }
394    
395                            if ($filesInBackup->{$path_key}->{'type'} == BPC_FTYPE_DIR) {
396                                    $nr_dirs++;
397    
398                                    my $full_path = $dir . '/' . $path_key;
399                                    push @stack, $full_path;
400                                    print STDERR "### store to stack: $full_path\n" if ($debug >= 3);
401    
402    #                               my ($f,$nf,$d,$nd) = recurseDir($bpc, $hostname, $backups, $backupNum, $share, $path_key, $shareID) unless ($beenThere->{$key});
403    #
404    #                               $nr_files += $f;
405    #                               $new_files += $nf;
406    #                               $nr_dirs += $d;
407    #                               $new_dirs += $nd;
408    
409                            } else {
410                                    $nr_files++;
411                            }
412                    }
413    
414                    print STDERR "## STACK ",join(", ", @stack),"\n" if ($debug >= 2);
415    
416                    while ( my $dir = shift @stack ) {
417                            my ($f,$nf,$d,$nd) = recurseDir($bpc, $hostname, $files, $backupNum, $share, $dir, $shareID);
418                            print STDERR "# $dir f: $f nf: $nf d: $d nd: $nd\n" if ($debug >= 1);
419                            $nr_files += $f;
420                            $new_files += $nf;
421                            $nr_dirs += $d;
422                            $new_dirs += $nd;
423                    }
424            }
425    
426            return ($nr_files, $new_files, $nr_dirs, $new_dirs);
427  }  }
428    

Legend:
Removed from v.6  
changed lines
  Added in v.52

  ViewVC Help
Powered by ViewVC 1.1.26