/[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 8 by dpavlin, Thu Jun 23 12:22:21 2005 UTC revision 49 by dpavlin, Sat Aug 20 15:01:48 2005 UTC
# Line 1  Line 1 
1  #!/usr/local/bin/perl  #!/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 $pidfile = new File::Pid;
21    
22    if (my $pid = $pidfile->running ) {
23            die "$0 already running: $pid\n";
24    } elsif ($pidfile->pid ne $$) {
25            $pidfile->remove;
26            $pidfile = new File::Pid;
27    }
28    $pidfile->write;
29    print STDERR "$0 using pid ",$pidfile->pid," file ",$pidfile->file,"\n";
30    
31    my $t_fmt = '%Y-%m-%d %H:%M:%S';
32    
33  my $hosts;  my $hosts;
34  my $bpc = BackupPC::Lib->new || die;  my $bpc = BackupPC::Lib->new || die;
35  my %Conf = $bpc->Conf();  my %Conf = $bpc->Conf();
36  my $TopDir = $bpc->TopDir();  my $TopDir = $bpc->TopDir();
37  my @beenThere = ();  my $beenThere = {};
38    
39  my $dbh = DBI->connect("dbi:SQLite:dbname=$TopDir/$Conf{SearchDB}", "", "", { RaiseError => 1, AutoCommit => 0 });  my $dsn = "dbi:SQLite:dbname=$TopDir/$Conf{SearchDB}";
40    my $user = '';
41    
42    # DEBUG option!
43    ($dsn,$user) = qw/dbi:Pg:dbname=backuppc dpavlin/;
44    
45    my $dbh = DBI->connect($dsn, $user, "", { RaiseError => 1, AutoCommit => 0 });
46    
47  my %opt;  my %opt;
48    
49  if ( !getopts("cdu", \%opt ) ) {  if ( !getopts("cdm:v:", \%opt ) ) {
50          print STDERR <<EOF;          print STDERR <<EOF;
51  usage: $0 (-c|-df|-u)  usage: $0 [-c|-d] [-m num] [-v|-v level]
52    
53  Options:  Options:
54          -c      Create database on first use          -c      create database on first use
55          -d      Delete database before import          -d      delete database before import
56          -u      Update database (import new revisions)          -m num  import just num increments for one host
57            -v num  set verbosity (debug) level (default $debug)
58  EOF  EOF
59          exit 1;          exit 1;
60  }  }
61    
62  ###################################create tables############################3  ###################################create tables############################3
63    
64  if ($opt{c})  if ($opt{c}) {
65      {          sub do_index {
66        print "creating database...";                  my $index = shift || return;
67                    my ($table,$col,$unique) = split(/_/, $index);
68                    $unique ||= '';
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        $dbh->do(          do_index('backups_num_unique');
103            q{  
104                create table dvds          $dbh->do(qq{
105                  ( ID         INTEGER            PRIMARY KEY,                  create table dvds (
106                      num      INTEGER            NOT NULL,                          ID      SERIAL          PRIMARY KEY,
107                      name             VARCHAR(255)       NOT NULL,                          num     INTEGER         NOT NULL,
108                      mjesto     VARCHAR(255)                          name    VARCHAR(255)    NOT NULL,
109                            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 references backups(num),
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            eval { $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();  $hosts = $bpc->HostInfoRead();
 print Dumper($hosts);  
171  my $hostID;  my $hostID;
172  my $shareID;  my $shareID;
173  foreach my $host_key (keys %{$hosts})  
174  {  my $sth;
175    my $hostname = $hosts->{$host_key}->{'host'} || die "can't find host for $host_key";  
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    if (my $tmp = $st->fetchrow_hashref())  
184        {  $sth->{backups_broj} = $dbh->prepare(qq{
185            $hostID = $tmp->{'ID'};  SELECT COUNT(*)
186        }  FROM backups
187      else  WHERE hostID=? AND num=?
188        {  });
189            $sql = q{ INSERT INTO hosts ( ID, name, IP) VALUES (NULL,"}.  
190                      $hosts->{$host_key}->{'host'}."\", \"".  $sth->{insert_backups} = $dbh->prepare(qq{
191                     $hosts->{$host_key}->{'ip'}."\");";  INSERT INTO backups (hostID, num, date, type)
192    VALUES (?,?,?,?)
193            $dbh->do($sql);  });
194            $hostID = $dbh->func('last_insert_rowid');  
195    $sth->{insert_files} = $dbh->prepare(qq{
196        }  INSERT INTO files
197    $st->finish();          (shareID, backupNum, name, path, fullpath, date, type, size)
198    print("processing host ".$hosts->{$host_key}->{'host'}.":\n");          VALUES (?,?,?,?,?,?,?,?)
199    });
200    
201    foreach my $host_key (keys %{$hosts}) {
202    
203            my $hostname = $hosts->{$host_key}->{'host'} || die "can't find host for $host_key";
204    
205            $sth->{hosts_by_name}->execute($hosts->{$host_key}->{'host'});
206    
207            unless (($hostID) = $sth->{hosts_by_name}->fetchrow_array()) {
208                    $sth->{insert_hosts}->execute(
209                            $hosts->{$host_key}->{'host'},
210                            $hosts->{$host_key}->{'ip'}
211                    );
212    
213                    $hostID = $dbh->last_insert_id(undef,undef,'hosts',undef);
214            }
215    
216            print("host ".$hosts->{$host_key}->{'host'}.": ");
217    
218    # get backups for a host          # get backups for a host
219    my @backups = $bpc->BackupInfoRead($hostname);          my @backups = $bpc->BackupInfoRead($hostname);
220    foreach my $backup (@backups)          print scalar @backups, " increments\n";
221    {  
222      my $backupNum = $backup->{'num'};          my $inc_nr = 0;
223      my @backupShares = ();  
224            foreach my $backup (@backups) {
225    
226                    $inc_nr++;
227                    last if ($opt{m} && $inc_nr > $opt{m});
228    
229                    my $backupNum = $backup->{'num'};
230                    my @backupShares = ();
231    
232                    print $hosts->{$host_key}->{'host'},
233                            "\t#$backupNum\t", $backup->{type} || '?', " ",
234                            $backup->{nFilesNew} || '?', "/", $backup->{nFiles} || '?',
235                            " files\n";
236    
237                    $sth->{backups_broj}->execute($hostID, $backupNum);
238                    my ($broj) = $sth->{backups_broj}->fetchrow_array();
239                    next if ($broj > 0);
240    
241                    $sth->{insert_backups}->execute(
242                            $hostID,
243                            $backupNum,
244                            $backup->{'endTime'},
245                            $backup->{'type'}
246                    );
247                    $dbh->commit();
248    
249                    my $files = BackupPC::View->new($bpc, $hostname, \@backups, 1);
250                    foreach my $share ($files->shareList($backupNum)) {
251    
252                            my $t = time();
253    
254                            print strftime($t_fmt,localtime())," ", $share;
255                            $shareID = getShareID($share, $hostID, $hostname);
256                    
257                            my ($f, $nf, $d, $nd) = recurseDir($bpc, $hostname, $files, $backupNum, $share, "", $shareID);
258                            printf(" %d/%d files %d/%d dirs [%.2f/s]\n",
259                                    $nf, $f, $nd, $d,
260                                    ( ($f+$d) / ((time() - $t) || 1) )
261                            );
262                            $dbh->commit();
263                    }
264    
         
     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;  
               }  
265          }          }
         
     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";  
266  }  }
267    undef $sth;
268  $dbh->commit();  $dbh->commit();
269  $dbh->disconnect();  $dbh->disconnect();
270    
271    $pidfile->remove;
272    
273  sub haveBeenThere  sub getShareID() {
 {  
   my ($where) = @_;  
     
   foreach my $st (@beenThere)  
   {  
     if ($where eq $st)  
     {  
       return 1;  
     }  
   }  
     
   push(@beenThere, $where);  
   return 0;  
 }  
274    
275  sub clearBeenThereCache          my ($share, $hostID, $hostname) = @_;
276  {  
277    @beenThere = ();          $sth->{share_id} ||= $dbh->prepare(qq{
278                    SELECT ID FROM shares WHERE hostID=? AND name=?
279            });
280    
281            $sth->{share_id}->execute($hostID,$share);
282    
283            my ($id) = $sth->{share_id}->fetchrow_array();
284    
285            return $id if (defined($id));
286    
287            $sth->{insert_share} ||= $dbh->prepare(qq{
288                    INSERT INTO shares
289                            (hostID,name,share,localpath)
290                    VALUES (?,?,?,?)
291            });
292    
293            my $drop_down = $hostname . '/' . $share;
294            $drop_down =~ s#//+#/#g;
295    
296            $sth->{insert_share}->execute($hostID,$share, $drop_down ,undef);
297            return $dbh->last_insert_id(undef,undef,'shares',undef);
298  }  }
299    
300  sub getShareID()  sub found_in_db {
301    {  
302        my ($share, $hostID, $hostname) = @_;          my @data = @_;
303        my $tmp;          shift @data;
304          
305        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) = @_;
306        $st -> execute($hostID,$share);  
307        my $tmp = $st->fetchrow_hashref();          return $beenThere->{$key} if (defined($beenThere->{$key}));
308        $st->finish();  
309        if ($tmp)          $sth->{file_in_db} ||= $dbh->prepare(qq{
310          {                  SELECT 1 FROM files
311              return $tmp->{'ID'};                  WHERE shareID = ? and
312          }                          path = ? and
313        my $sql =                          name = ? and
314            q{                          date = ? and
315                INSERT INTO shares(ID,hostID,name,share,localpath)                          size = ?
316                  VALUES            });
317                 (NULL,}.                    
318                "$hostID,\"$share\",\"//$hostname$share\",NULL);";                        my @param = ($shareID,$path,$name,$date,$size);
319        $dbh->do($sql);          $sth->{file_in_db}->execute(@param);
320        return $dbh->func('last_insert_rowid');                    my $rows = $sth->{file_in_db}->rows;
321    }          print STDERR "## found_in_db ",( $rows ? '+' : '-' ), join(" ",@param), "\n" if ($debug >= 3);
322    
323            $beenThere->{$key}++;
324    
325            $sth->{'insert_files'}->execute(@data) unless ($rows);
326            return $rows;
327    }
328    
329  ####################################################  ####################################################
330  # recursing through filesystem structure and       #  # recursing through filesystem structure and       #
331  # and returning flattened files list               #  # and returning flattened files list               #
332  ####################################################  ####################################################
333  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 = "";  
334    
335            my ($bpc, $hostname, $files, $backupNum, $share, $dir, $shareID) = @_;
336    # first, add all the entries in current directory  
337    foreach $file_key (keys %{$filesInBackup})          print STDERR "\nrecurse($hostname,$backupNum,$share,$dir,$shareID)\n" if ($debug >= 1);
338    {  
339      push(@ret, {          my ($nr_files, $new_files, $nr_dirs, $new_dirs) = (0,0,0,0);
340                   'fileName' => $file_key,  
341                   'relPath'  => $filesInBackup->{$file_key}->{'relPath'},          { # scope
342                   'fullPath' => $filesInBackup->{$file_key}->{'fullPath'},                  my @stack;
343                   'sharePath'=> $filesInBackup->{$file_key}->{'sharePathM'},  
344                   'size'     => $filesInBackup->{$file_key}->{'size'},                  print STDERR "# dirAttrib($backupNum, $share, $dir)\n" if ($debug >= 2);
345                   'mtime'    => $filesInBackup->{$file_key}->{'mtime'},                  my $filesInBackup = $files->dirAttrib($backupNum, $share, $dir);
346                   'type'     => $filesInBackup->{$file_key}->{'type'}  
347                 });                    # first, add all the entries in current directory
348    }                  foreach my $path_key (keys %{$filesInBackup}) {
349                                my @data = (
350    # then, recurse thru subfolders                                  $shareID,
351    foreach my $fold (@ret)                                  $backupNum,
352    {                                  $path_key,
353     if ($fold->{'type'} == BPC_FTYPE_DIR &&                                  $filesInBackup->{$path_key}->{'relPath'},
354         haveBeenThere($fold->{'relPath'}) != 1                                  $filesInBackup->{$path_key}->{'fullPath'},
355        )          #                       $filesInBackup->{$path_key}->{'sharePathM'},
356      {                                  $filesInBackup->{$path_key}->{'mtime'},
357                                          $filesInBackup->{$path_key}->{'type'},
358        push(@ret,                                  $filesInBackup->{$path_key}->{'size'}
359             recurseDir($bpc, $hostname, $backups, $backupNo, $share, $fold->{'relPath'})                          );
360            );  
361      }                          my $key = join(" ", (
362    }                                  $shareID,
363    return @ret;                                  $dir,
364                                    $path_key,
365                                    $filesInBackup->{$path_key}->{'mtime'},
366                                    $filesInBackup->{$path_key}->{'size'}
367                            ));
368    
369    
370                            if (! defined($beenThere->{$key}) && ! found_in_db($key, @data)) {
371                                    print STDERR "# key: $key [", $beenThere->{$key},"]" if ($debug >= 2);
372    
373                                    if ($filesInBackup->{$path_key}->{'type'} == BPC_FTYPE_DIR) {
374                                            $new_dirs++;
375                                            print STDERR " dir\n" if ($debug >= 2);
376                                    } else {
377                                            $new_files++;
378                                            print STDERR " file\n" if ($debug >= 2);
379                                    }
380                            }
381    
382                            if ($filesInBackup->{$path_key}->{'type'} == BPC_FTYPE_DIR) {
383                                    $nr_dirs++;
384    
385                                    my $full_path = $dir . '/' . $path_key;
386                                    push @stack, $full_path;
387                                    print STDERR "### store to stack: $full_path\n" if ($debug >= 3);
388    
389    #                               my ($f,$nf,$d,$nd) = recurseDir($bpc, $hostname, $backups, $backupNum, $share, $path_key, $shareID) unless ($beenThere->{$key});
390    #
391    #                               $nr_files += $f;
392    #                               $new_files += $nf;
393    #                               $nr_dirs += $d;
394    #                               $new_dirs += $nd;
395    
396                            } else {
397                                    $nr_files++;
398                            }
399                    }
400    
401                    print STDERR "## STACK ",join(", ", @stack),"\n" if ($debug >= 2);
402    
403                    while ( my $dir = shift @stack ) {
404                            my ($f,$nf,$d,$nd) = recurseDir($bpc, $hostname, $files, $backupNum, $share, $dir, $shareID);
405                            print STDERR "# $dir f: $f nf: $nf d: $d nd: $nd\n" if ($debug >= 1);
406                            $nr_files += $f;
407                            $new_files += $nf;
408                            $nr_dirs += $d;
409                            $new_dirs += $nd;
410                    }
411            }
412    
413            return ($nr_files, $new_files, $nr_dirs, $new_dirs);
414  }  }
415    

Legend:
Removed from v.8  
changed lines
  Added in v.49

  ViewVC Help
Powered by ViewVC 1.1.26