/[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 65 by dpavlin, Sun Aug 21 23:25:47 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),                          shareID integer         not null references shares(id),
99                      PRIMARY KEY(hostID, num)                          PRIMARY KEY(hostID, num, shareID)
100                  );                              );            
101            }          });
       );  
102    
103        $dbh->do(          #do_index('backups_hostid,num_unique');
104            q{  
105                create table dvds          $dbh->do(qq{
106                  ( ID         INTEGER            PRIMARY KEY,                  create table dvds (
107                      num      INTEGER            NOT NULL,                          ID      SERIAL          PRIMARY KEY,
108                      name             VARCHAR(255)       NOT NULL,                          num     INTEGER         NOT NULL,
109                      mjesto     VARCHAR(255)                          name    VARCHAR(255)    NOT NULL,
110                            mjesto  VARCHAR(255)
111                  );                  );
112            }          });
       );  
113    
114        $dbh->do(          $dbh->do(qq{    
115            q{                      create table files (
116                create table files                          ID      SERIAL          PRIMARY KEY,  
117                  (   ID         INTEGER          NOT NULL PRIMARY KEY,                            shareID INTEGER         NOT NULL references shares(id),
118                      shareID    INTEGER          NOT NULL,                          backupNum  INTEGER      NOT NULL,
119                      backupNum  INTEGER          NOT NULL,                          name       VARCHAR(255) NOT NULL,
120                      name       VARCHAR(255)     NOT NULL,                          path       VARCHAR(255) NOT NULL,
121                      path       VARCHAR(255)     NOT NULL,                          date       integer      NOT NULL,
122                      fullpath   VARCHAR(255)     NOT NULL,                          type       INTEGER      NOT NULL,
123                      date       TIMESTAMP        NOT NULL,                          size       INTEGER      NOT NULL,
124                      type       INTEGER          NOT NULL,                          dvdid      INTEGER      references dvds(id)    
                     size       INTEGER          NOT NULL,  
                     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_count} = $dbh->prepare(qq{
185        {  SELECT COUNT(*)
186            $hostID = $tmp->{'ID'};  FROM backups
187        }  WHERE hostID=? AND num=? AND shareid=?
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, shareid)
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, 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 (date: ",
245                            strftime($t_fmt,localtime($backup->{startTime})),
246                            " dur: ",
247                            fmt_time($backup->{endTime} - $backup->{startTime}),
248                            ")\n";
249    
250                    my $files = BackupPC::View->new($bpc, $hostname, \@backups, 1);
251                    foreach my $share ($files->shareList($backupNum)) {
252    
253                            my $t = time();
254    
255                            $shareID = getShareID($share, $hostID, $hostname);
256                    
257                            $sth->{backups_count}->execute($hostID, $backupNum, $shareID);
258                            my ($count) = $sth->{backups_count}->fetchrow_array();
259                            # skip if allready in database!
260                            next if ($count > 0);
261    
262                            # dump some log
263                            print strftime($t_fmt,localtime())," ", $share;
264    
265                            my ($f, $nf, $d, $nd) = recurseDir($bpc, $hostname, $files, $backupNum, $share, "", $shareID);
266    
267                            $sth->{insert_backups}->execute(
268                                    $hostID,
269                                    $backupNum,
270                                    $backup->{'endTime'},
271                                    $backup->{'type'},
272                                    $shareID
273                            );
274    
275                            print " commit";
276                            $dbh->commit();
277    
278                            my $dur = (time() - $t) || 1;
279                            printf(" %d/%d files %d/%d dirs [%.2f/s dur: %s]\n",
280                                    $nf, $f, $nd, $d,
281                                    ( ($f+$d) / $dur ),
282                                    fmt_time($dur)
283                            );
284                    }
285    
         
     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;  
               }  
286          }          }
         
     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";  
287  }  }
288    undef $sth;
289  $dbh->commit();  $dbh->commit();
290  $dbh->disconnect();  $dbh->disconnect();
291    
292    print "total duration: ",fmt_time(time() - $start_t),"\n";
293    
294  sub haveBeenThere  $pidfile->remove;
295  {  
296    my ($where) = @_;  sub getShareID() {
     
   foreach my $st (@beenThere)  
   {  
     if ($where eq $st)  
     {  
       return 1;  
     }  
   }  
     
   push(@beenThere, $where);  
   return 0;  
 }  
297    
298  sub clearBeenThereCache          my ($share, $hostID, $hostname) = @_;
299  {  
300    @beenThere = ();          $sth->{share_id} ||= $dbh->prepare(qq{
301                    SELECT ID FROM shares WHERE hostID=? AND name=?
302            });
303    
304            $sth->{share_id}->execute($hostID,$share);
305    
306            my ($id) = $sth->{share_id}->fetchrow_array();
307    
308            return $id if (defined($id));
309    
310            $sth->{insert_share} ||= $dbh->prepare(qq{
311                    INSERT INTO shares
312                            (hostID,name,share,localpath)
313                    VALUES (?,?,?,?)
314            });
315    
316            my $drop_down = $hostname . '/' . $share;
317            $drop_down =~ s#//+#/#g;
318    
319            $sth->{insert_share}->execute($hostID,$share, $drop_down ,undef);
320            return $dbh->last_insert_id(undef,undef,'shares',undef);
321  }  }
322    
323  sub getShareID()  sub found_in_db {
324    {  
325        my ($share, $hostID, $hostname) = @_;          my @data = @_;
326        my $tmp;          shift @data;
327          
328        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) = @_;
329        $st -> execute($hostID,$share);  
330        my $tmp = $st->fetchrow_hashref();          return $beenThere->{$key} if (defined($beenThere->{$key}));
331        $st->finish();  
332        if ($tmp)          $sth->{file_in_db} ||= $dbh->prepare(qq{
333          {                  SELECT 1 FROM files
334              return $tmp->{'ID'};                  WHERE shareID = ? and
335          }                          path = ? and
336        my $sql =                          name = ? and
337            q{                          date = ? and
338                INSERT INTO shares(ID,hostID,name,share,localpath)                          size = ?
339                  VALUES            });
340                 (NULL,}.                    
341                "$hostID,\"$share\",\"//$hostname$share\",NULL);";                        my @param = ($shareID,$path,$name,$date,$size);
342        $dbh->do($sql);          $sth->{file_in_db}->execute(@param);
343        return $dbh->func('last_insert_rowid');                    my $rows = $sth->{file_in_db}->rows;
344    }          print STDERR "## found_in_db ",( $rows ? '+' : '-' ), join(" ",@param), "\n" if ($debug >= 3);
345    
346            $beenThere->{$key}++;
347    
348            $sth->{'insert_files'}->execute(@data) unless ($rows);
349            return $rows;
350    }
351    
352  ####################################################  ####################################################
353  # recursing through filesystem structure and       #  # recursing through filesystem structure and       #
354  # and returning flattened files list               #  # and returning flattened files list               #
355  ####################################################  ####################################################
356  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 = "";  
357    
358            my ($bpc, $hostname, $files, $backupNum, $share, $dir, $shareID) = @_;
359    # first, add all the entries in current directory  
360    foreach $file_key (keys %{$filesInBackup})          print STDERR "\nrecurse($hostname,$backupNum,$share,$dir,$shareID)\n" if ($debug >= 1);
361    {  
362      push(@ret, {          my ($nr_files, $new_files, $nr_dirs, $new_dirs) = (0,0,0,0);
363                   'fileName' => $file_key,  
364                   'relPath'  => $filesInBackup->{$file_key}->{'relPath'},          { # scope
365                   'fullPath' => $filesInBackup->{$file_key}->{'fullPath'},                  my @stack;
366                   'sharePath'=> $filesInBackup->{$file_key}->{'sharePathM'},  
367                   'size'     => $filesInBackup->{$file_key}->{'size'},                  print STDERR "# dirAttrib($backupNum, $share, $dir)\n" if ($debug >= 2);
368                   'mtime'    => $filesInBackup->{$file_key}->{'mtime'},                  my $filesInBackup = $files->dirAttrib($backupNum, $share, $dir);
369                   'type'     => $filesInBackup->{$file_key}->{'type'}  
370                 });                    # first, add all the entries in current directory
371    }                  foreach my $path_key (keys %{$filesInBackup}) {
372                                my @data = (
373    # then, recurse thru subfolders                                  $shareID,
374    foreach my $fold (@ret)                                  $backupNum,
375    {                                  $path_key,
376     if ($fold->{'type'} == BPC_FTYPE_DIR &&                                  $filesInBackup->{$path_key}->{'relPath'},
377         haveBeenThere($fold->{'relPath'}) != 1                                  $filesInBackup->{$path_key}->{'mtime'},
378        )                                  $filesInBackup->{$path_key}->{'type'},
379      {                                  $filesInBackup->{$path_key}->{'size'}
380                                  );
381        push(@ret,  
382             recurseDir($bpc, $hostname, $backups, $backupNo, $share, $fold->{'relPath'})                          my $key = join(" ", (
383            );                                  $shareID,
384      }                                  $dir,
385    }                                  $path_key,
386    return @ret;                                  $filesInBackup->{$path_key}->{'mtime'},
387                                    $filesInBackup->{$path_key}->{'size'}
388                            ));
389    
390    
391                            if (! defined($beenThere->{$key}) && ! found_in_db($key, @data)) {
392                                    print STDERR "# key: $key [", $beenThere->{$key},"]" if ($debug >= 2);
393    
394                                    if ($filesInBackup->{$path_key}->{'type'} == BPC_FTYPE_DIR) {
395                                            $new_dirs++;
396                                            print STDERR " dir\n" if ($debug >= 2);
397                                    } else {
398                                            $new_files++;
399                                            print STDERR " file\n" if ($debug >= 2);
400                                    }
401                            }
402    
403                            if ($filesInBackup->{$path_key}->{'type'} == BPC_FTYPE_DIR) {
404                                    $nr_dirs++;
405    
406                                    my $full_path = $dir . '/' . $path_key;
407                                    push @stack, $full_path;
408                                    print STDERR "### store to stack: $full_path\n" if ($debug >= 3);
409    
410    #                               my ($f,$nf,$d,$nd) = recurseDir($bpc, $hostname, $backups, $backupNum, $share, $path_key, $shareID) unless ($beenThere->{$key});
411    #
412    #                               $nr_files += $f;
413    #                               $new_files += $nf;
414    #                               $nr_dirs += $d;
415    #                               $new_dirs += $nd;
416    
417                            } else {
418                                    $nr_files++;
419                            }
420                    }
421    
422                    print STDERR "## STACK ",join(", ", @stack),"\n" if ($debug >= 2);
423    
424                    while ( my $dir = shift @stack ) {
425                            my ($f,$nf,$d,$nd) = recurseDir($bpc, $hostname, $files, $backupNum, $share, $dir, $shareID);
426                            print STDERR "# $dir f: $f nf: $nf d: $d nd: $nd\n" if ($debug >= 1);
427                            $nr_files += $f;
428                            $new_files += $nf;
429                            $nr_dirs += $d;
430                            $new_dirs += $nd;
431                    }
432            }
433    
434            return ($nr_files, $new_files, $nr_dirs, $new_dirs);
435  }  }
436    

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

  ViewVC Help
Powered by ViewVC 1.1.26