/[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 67 by dpavlin, Mon Aug 22 08:58:59 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)                          size    integer         not null,
100                            PRIMARY KEY(hostID, num, shareID)
101                  );                              );            
102            }          });
103        );  
104            #do_index('backups_hostid,num_unique');
105    
106        $dbh->do(          $dbh->do(qq{
107            q{                  create table dvds (
108                create table dvds                          ID      SERIAL          PRIMARY KEY,
109                  ( ID         INTEGER            PRIMARY KEY,                          num     INTEGER         NOT NULL,
110                      num      INTEGER            NOT NULL,                          name    VARCHAR(255)    NOT NULL,
111                      name             VARCHAR(255)       NOT NULL,                          mjesto  VARCHAR(255)
                     mjesto     VARCHAR(255)  
112                  );                  );
113            }          });
       );  
114    
115        $dbh->do(          $dbh->do(qq{    
116            q{                      create table files (
117                create table files                          ID      SERIAL          PRIMARY KEY,  
118                  (   ID         INTEGER          NOT NULL PRIMARY KEY,                            shareID INTEGER         NOT NULL references shares(id),
119                      shareID    INTEGER          NOT NULL,                          backupNum  INTEGER      NOT NULL,
120                      backupNum  INTEGER          NOT NULL,                          name       VARCHAR(255) NOT NULL,
121                      name       VARCHAR(255)     NOT NULL,                          path       VARCHAR(255) NOT NULL,
122                      path       VARCHAR(255)     NOT NULL,                          date       integer      NOT NULL,
123                      fullpath   VARCHAR(255)     NOT NULL,                          type       INTEGER      NOT NULL,
124                      date       TIMESTAMP        NOT NULL,                          size       INTEGER      NOT NULL,
125                      type       INTEGER          NOT NULL,                          dvdid      INTEGER      references dvds(id)    
                     size       INTEGER          NOT NULL,  
                     dvdid      INTEGER            
126                  );                  );
127            }          });
128        );  
129        print "done\n";          print "creating indexes:";
130    }  
131            foreach my $index (qw(
132  if ($opt{d})                  hosts_name
133    {                  backups_hostID
134        print("deleting db first...\n");                  backups_num
135                          shares_hostID
136        $dbh->do(                  shares_name
137            q{ DELETE FROM hosts; }                  files_shareID
138            );                  files_path
139        $dbh->do(                  files_name
140            q{ DELETE FROM shares; }                  files_date
141            );                  files_size
142        $dbh->do(          )) {
143            q{ DELETE FROM files;}                  print " $index";
144            );                  do_index($index);
145        $dbh->do(          }
146            q{ DELETE FROM dvds;}          print "...\n";
147            );  
148        $dbh->do(          $dbh->commit;
149            q{ DELETE FROM backups; }  
150            );  }
151    }  
152    if ($opt{d}) {
153            print "deleting ";
154            foreach my $table (qw(files dvds backups shares hosts)) {
155                    print "$table ";
156                    $dbh->do(qq{ DELETE FROM $table });
157            }
158            print " done...\n";
159    
160            $dbh->commit;
161    }
162    
163    if ($opt{v}) {
164            print "Debug level at $opt{v}\n";
165            $debug = $opt{v};
166    }
167    
168  #################################INSERT VALUES#############################  #################################INSERT VALUES#############################
169    
170  # get hosts  # get hosts
171  $hosts = $bpc->HostInfoRead("localhost");  $hosts = $bpc->HostInfoRead();
 my $host_key;  
172  my $hostID;  my $hostID;
173  my $shareID;  my $shareID;
174  foreach $host_key (keys %{$hosts})  
175  {  my $sth;
176    my $hostname = $hosts->{$host_key}->{'host'};  
177    my $backups;  $sth->{insert_hosts} = $dbh->prepare(qq{
178    my $sql;  INSERT INTO hosts (name, IP) VALUES (?,?)
179    });
180    $sql = q{ SELECT ID FROM hosts WHERE name=? };  
181    my $st = $dbh->prepare($sql);  $sth->{hosts_by_name} = $dbh->prepare(qq{
182    $st->bind_param(1,$hosts->{$host_key}->{'host'});  SELECT ID FROM hosts WHERE name=?
183    $st->execute();  });
184    my $tmp = $st->fetchrow_hashref();  
185    if ($tmp->{'ID'} ne "")  $sth->{backups_count} = $dbh->prepare(qq{
186        {  SELECT COUNT(*)
187            $hostID = $tmp->{'ID'};  FROM backups
188        }  WHERE hostID=? AND num=? AND shareid=?
189      else  });
190        {  
191            $sql = q{ INSERT INTO hosts ( ID, name, IP) VALUES (NULL,"}.  $sth->{insert_backups} = $dbh->prepare(qq{
192                      $hosts->{$host_key}->{'host'}."\", \"".  INSERT INTO backups (hostID, num, date, type, shareid, size)
193                     $hosts->{$host_key}->{'ip'}."\");";  VALUES (?,?,?,?,?,?)
194    });
195            $dbh->do($sql);  
196            $hostID = $dbh->func('last_insert_rowid');  $sth->{insert_files} = $dbh->prepare(qq{
197    INSERT INTO files
198        }          (shareID, backupNum, name, path, date, type, size)
199    $st->finish();          VALUES (?,?,?,?,?,?,?)
200    print("processing host ".$hosts->{$host_key}->{'host'}.":\n");  });
201    
202    sub fmt_time {
203            my $t = shift || return;
204            my $out = "";
205            my ($ss,$mm,$hh) = gmtime($t);
206            $out .= "${hh}h" if ($hh);
207            $out .= sprintf("%02d:%02d", $mm,$ss);
208            return $out;
209    }
210    
211    foreach my $host_key (keys %{$hosts}) {
212    
213            my $hostname = $hosts->{$host_key}->{'host'} || die "can't find host for $host_key";
214    
215            $sth->{hosts_by_name}->execute($hosts->{$host_key}->{'host'});
216    
217            unless (($hostID) = $sth->{hosts_by_name}->fetchrow_array()) {
218                    $sth->{insert_hosts}->execute(
219                            $hosts->{$host_key}->{'host'},
220                            $hosts->{$host_key}->{'ip'}
221                    );
222    
223                    $hostID = $dbh->last_insert_id(undef,undef,'hosts',undef);
224            }
225    
226            print "host ".$hosts->{$host_key}->{'host'}.": ";
227    
228    # get backups for a host          # get backups for a host
229    my @backups = $bpc->BackupInfoRead($hostname);          my @backups = $bpc->BackupInfoRead($hostname);
230    foreach my $backup (@backups)          my $incs = scalar @backups;
231    {          print  "$incs increments\n";
232      my $backupNum = $backup->{'num'};  
233      my @backupShares = ();          my $inc_nr = 0;
234            $beenThere = {};
235    
236            foreach my $backup (@backups) {
237    
238                    $inc_nr++;
239                    last if ($opt{m} && $inc_nr > $opt{m});
240    
241                    my $backupNum = $backup->{'num'};
242                    my @backupShares = ();
243    
244                    printf("%-10s %2d/%-2d #%-2d %s %5s/%5s files (date: %s dur: %s)\n",
245                            $hosts->{$host_key}->{'host'},
246                            $inc_nr, $incs, $backupNum,
247                            $backup->{type} || '?',
248                            $backup->{nFilesNew} || '?', $backup->{nFiles} || '?',
249                            strftime($t_fmt,localtime($backup->{startTime})),
250                            fmt_time($backup->{endTime} - $backup->{startTime})
251                    );
252    
253                    my $files = BackupPC::View->new($bpc, $hostname, \@backups, 1);
254                    foreach my $share ($files->shareList($backupNum)) {
255    
256                            my $t = time();
257    
258                            $shareID = getShareID($share, $hostID, $hostname);
259                    
260                            $sth->{backups_count}->execute($hostID, $backupNum, $shareID);
261                            my ($count) = $sth->{backups_count}->fetchrow_array();
262                            # skip if allready in database!
263                            next if ($count > 0);
264    
265                            # dump some log
266                            print strftime($t_fmt,localtime())," ", $share;
267    
268                            my ($f, $nf, $d, $nd, $size) = recurseDir($bpc, $hostname, $files, $backupNum, $share, "", $shareID);
269    
270                            $sth->{insert_backups}->execute(
271                                    $hostID,
272                                    $backupNum,
273                                    $backup->{'endTime'},
274                                    $backup->{'type'},
275                                    $shareID,
276                                    $size,
277                            );
278    
279                            print " commit";
280                            $dbh->commit();
281    
282                            my $dur = (time() - $t) || 1;
283                            printf(" %d/%d files %d/%d dirs %0.2f MB [%.2f/s dur: %s]\n",
284                                    $nf, $f, $nd, $d,
285                                    ($size / 1024 / 1024),
286                                    ( ($f+$d) / $dur ),
287                                    fmt_time($dur)
288                            );
289                    }
290    
         
     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;  
               }  
291          }          }
         
     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";  
292  }  }
293    undef $sth;
294  $dbh->commit();  $dbh->commit();
295  $dbh->disconnect();  $dbh->disconnect();
296    
297    print "total duration: ",fmt_time(time() - $start_t),"\n";
298    
299  sub haveBeenThere  $pidfile->remove;
300  {  
301    my ($where) = @_;  sub getShareID() {
302      
303    foreach my $st (@beenThere)          my ($share, $hostID, $hostname) = @_;
304    {  
305      if ($where eq $st)          $sth->{share_id} ||= $dbh->prepare(qq{
306      {                  SELECT ID FROM shares WHERE hostID=? AND name=?
307        return 1;          });
308      }  
309    }          $sth->{share_id}->execute($hostID,$share);
310      
311    push(@beenThere, $where);          my ($id) = $sth->{share_id}->fetchrow_array();
312    return 0;  
313  }          return $id if (defined($id));
314    
315            $sth->{insert_share} ||= $dbh->prepare(qq{
316                    INSERT INTO shares
317                            (hostID,name,share,localpath)
318                    VALUES (?,?,?,?)
319            });
320    
321            my $drop_down = $hostname . '/' . $share;
322            $drop_down =~ s#//+#/#g;
323    
324  sub clearBeenThereCache          $sth->{insert_share}->execute($hostID,$share, $drop_down ,undef);
325  {          return $dbh->last_insert_id(undef,undef,'shares',undef);
   @beenThere = ();  
326  }  }
327    
328  sub getShareID()  sub found_in_db {
329    {  
330        my ($share, $hostID, $hostname) = @_;          my @data = @_;
331        my $tmp;          shift @data;
332          
333        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) = @_;
334        $st -> execute($hostID,$share);  
335        my $tmp = $st->fetchrow_hashref();          return $beenThere->{$key} if (defined($beenThere->{$key}));
336        $st->finish();  
337        if ($tmp)          $sth->{file_in_db} ||= $dbh->prepare(qq{
338          {                  SELECT 1 FROM files
339              return $tmp->{'ID'};                  WHERE shareID = ? and
340          }                          path = ? and
341        my $sql =                          date = ? and
342            q{                          size = ?
343                INSERT INTO shares(ID,hostID,name,share,localpath)          });
344                  VALUES    
345                 (NULL,}.                            my @param = ($shareID,$path,$date,$size);
346                "$hostID,\"$share\",\"//$hostname$share\",NULL);";                        $sth->{file_in_db}->execute(@param);
347        $dbh->do($sql);          my $rows = $sth->{file_in_db}->rows;
348        return $dbh->func('last_insert_rowid');                    print STDERR "## found_in_db ",( $rows ? '+' : '-' ), join(" ",@param), "\n" if ($debug >= 3);
349    }  
350            $beenThere->{$key}++;
351    
352            $sth->{'insert_files'}->execute(@data) unless ($rows);
353            return $rows;
354    }
355    
356  ####################################################  ####################################################
357  # recursing through filesystem structure and       #  # recursing through filesystem structure and       #
358  # and returning flattened files list               #  # and returning flattened files list               #
359  ####################################################  ####################################################
360  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 = "";  
361    
362            my ($bpc, $hostname, $files, $backupNum, $share, $dir, $shareID) = @_;
363    # first, add all the entries in current directory  
364    foreach $file_key (keys %{$filesInBackup})          print STDERR "\nrecurse($hostname,$backupNum,$share,$dir,$shareID)\n" if ($debug >= 1);
365    {  
366      push(@ret, {          my ($nr_files, $new_files, $nr_dirs, $new_dirs, $size) = (0,0,0,0,0);
367                   'fileName' => $file_key,  
368                   'relPath'  => $filesInBackup->{$file_key}->{'relPath'},          { # scope
369                   'fullPath' => $filesInBackup->{$file_key}->{'fullPath'},                  my @stack;
370                   'sharePath'=> $filesInBackup->{$file_key}->{'sharePathM'},  
371                   'size'     => $filesInBackup->{$file_key}->{'size'},                  print STDERR "# dirAttrib($backupNum, $share, $dir)\n" if ($debug >= 2);
372                   'mtime'    => $filesInBackup->{$file_key}->{'mtime'},                  my $filesInBackup = $files->dirAttrib($backupNum, $share, $dir);
373                   'type'     => $filesInBackup->{$file_key}->{'type'}  
374                 });                    # first, add all the entries in current directory
375    }                  foreach my $path_key (keys %{$filesInBackup}) {
376                                print STDERR "# file ",Dumper($filesInBackup->{$path_key}),"\n" if ($debug >= 3);
377    # then, recurse thru subfolders                          my @data = (
378    foreach my $fold (@ret)                                  $shareID,
379    {                                  $backupNum,
380     if ($fold->{'type'} == BPC_FTYPE_DIR &&                                  $path_key,
381         haveBeenThere($fold->{'relPath'}) != 1                                  $filesInBackup->{$path_key}->{'relPath'},
382        )                                  $filesInBackup->{$path_key}->{'mtime'},
383      {                                  $filesInBackup->{$path_key}->{'type'},
384                                          $filesInBackup->{$path_key}->{'size'}
385        push(@ret,                          );
386             recurseDir($bpc, $hostname, $backups, $backupNo, $share, $fold->{'relPath'})  
387            );                          my $key = join(" ", (
388      }                                  $shareID,
389    }                                  $dir,
390    return @ret;                                  $path_key,
391                                    $filesInBackup->{$path_key}->{'mtime'},
392                                    $filesInBackup->{$path_key}->{'size'}
393                            ));
394    
395    
396                            if (! defined($beenThere->{$key}) && ! found_in_db($key, @data)) {
397                                    print STDERR "# key: $key [", $beenThere->{$key},"]" if ($debug >= 2);
398    
399                                    if ($filesInBackup->{$path_key}->{'type'} == BPC_FTYPE_DIR) {
400                                            $new_dirs++;
401                                            print STDERR " dir\n" if ($debug >= 2);
402                                    } else {
403                                            $new_files++;
404                                            print STDERR " file\n" if ($debug >= 2);
405                                    }
406                                    $size += $filesInBackup->{$path_key}->{'size'} || 0;
407                            }
408    
409                            if ($filesInBackup->{$path_key}->{'type'} == BPC_FTYPE_DIR) {
410                                    $nr_dirs++;
411    
412                                    my $full_path = $dir . '/' . $path_key;
413                                    push @stack, $full_path;
414                                    print STDERR "### store to stack: $full_path\n" if ($debug >= 3);
415    
416    #                               my ($f,$nf,$d,$nd) = recurseDir($bpc, $hostname, $backups, $backupNum, $share, $path_key, $shareID) unless ($beenThere->{$key});
417    #
418    #                               $nr_files += $f;
419    #                               $new_files += $nf;
420    #                               $nr_dirs += $d;
421    #                               $new_dirs += $nd;
422    
423                            } else {
424                                    $nr_files++;
425                            }
426                    }
427    
428                    print STDERR "## STACK ",join(", ", @stack),"\n" if ($debug >= 2);
429    
430                    while ( my $dir = shift @stack ) {
431                            my ($f,$nf,$d,$nd, $s) = recurseDir($bpc, $hostname, $files, $backupNum, $share, $dir, $shareID);
432                            print STDERR "# $dir f: $f nf: $nf d: $d nd: $nd\n" if ($debug >= 1);
433                            $nr_files += $f;
434                            $new_files += $nf;
435                            $nr_dirs += $d;
436                            $new_dirs += $nd;
437                            $size += $s;
438                    }
439            }
440    
441            return ($nr_files, $new_files, $nr_dirs, $new_dirs, $size);
442  }  }
443    

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

  ViewVC Help
Powered by ViewVC 1.1.26