/[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 66 by dpavlin, Mon Aug 22 00:09:59 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 $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  my $dbh = DBI->connect("dbi:SQLite:dbname=$TopDir/$Conf{SearchDB}", "", "", { RaiseError => 1, AutoCommit => 0 });  my $dsn = $Conf{SearchDSN} || die "Need SearchDSN in config.pl\n";
42    my $user = $Conf{SearchUser} || '';
43    
44    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();  $hosts = $bpc->HostInfoRead();
 print Dumper($hosts);  
172  my $hostID;  my $hostID;
173  my $shareID;  my $shareID;
174  foreach my $host_key (keys %{$hosts})  
175  {  my $sth;
176    my $hostname = $hosts->{$host_key}->{'host'} || die "can't find host for $host_key";  
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    if (my $tmp = $st->fetchrow_hashref())  
185        {  $sth->{backups_count} = $dbh->prepare(qq{
186            $hostID = $tmp->{'ID'};  SELECT COUNT(*)
187        }  FROM backups
188      else  WHERE hostID=? AND num=? AND shareid=?
189        {  });
190            $sql = q{ INSERT INTO hosts ( ID, name, IP) VALUES (NULL,"}.  
191                      $hosts->{$host_key}->{'host'}."\", \"".  $sth->{insert_backups} = $dbh->prepare(qq{
192                     $hosts->{$host_key}->{'ip'}."\");";  INSERT INTO backups (hostID, num, date, type, shareid, size)
193    VALUES (?,?,?,?,?,?)
194            $dbh->do($sql);  });
195            $hostID = $dbh->func('last_insert_rowid');  
196    $sth->{insert_files} = $dbh->prepare(qq{
197        }  INSERT INTO files
198    $st->finish();          (shareID, backupNum, name, path, date, type, size)
199    print("processing host ".$hosts->{$host_key}->{'host'}.":\n");          VALUES (?,?,?,?,?,?,?)
200    });
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)          print scalar @backups, " increments\n";
231    {  
232      my $backupNum = $backup->{'num'};          my $inc_nr = 0;
233      my @backupShares = ();  
234            foreach my $backup (@backups) {
235    
236                    $inc_nr++;
237                    last if ($opt{m} && $inc_nr > $opt{m});
238    
239                    my $backupNum = $backup->{'num'};
240                    my @backupShares = ();
241    
242                    print $hosts->{$host_key}->{'host'},
243                            "\t#$backupNum\t", $backup->{type} || '?', " ",
244                            $backup->{nFilesNew} || '?', "/", $backup->{nFiles} || '?',
245                            " files (date: ",
246                            strftime($t_fmt,localtime($backup->{startTime})),
247                            " dur: ",
248                            fmt_time($backup->{endTime} - $backup->{startTime}),
249                            ")\n";
250    
251                    my $files = BackupPC::View->new($bpc, $hostname, \@backups, 1);
252                    foreach my $share ($files->shareList($backupNum)) {
253    
254                            my $t = time();
255    
256                            $shareID = getShareID($share, $hostID, $hostname);
257                    
258                            $sth->{backups_count}->execute($hostID, $backupNum, $shareID);
259                            my ($count) = $sth->{backups_count}->fetchrow_array();
260                            # skip if allready in database!
261                            next if ($count > 0);
262    
263                            # dump some log
264                            print strftime($t_fmt,localtime())," ", $share;
265    
266                            my ($f, $nf, $d, $nd, $size) = recurseDir($bpc, $hostname, $files, $backupNum, $share, "", $shareID);
267    
268                            $sth->{insert_backups}->execute(
269                                    $hostID,
270                                    $backupNum,
271                                    $backup->{'endTime'},
272                                    $backup->{'type'},
273                                    $shareID,
274                                    $size,
275                            );
276    
277                            print " commit";
278                            $dbh->commit();
279    
280                            my $dur = (time() - $t) || 1;
281                            printf(" %d/%d files %d/%d dirs %0.2f MB [%.2f/s dur: %s]\n",
282                                    $nf, $f, $nd, $d,
283                                    ($size / 1024 / 1024),
284                                    ( ($f+$d) / $dur ),
285                                    fmt_time($dur)
286                            );
287                    }
288    
         
     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;  
               }  
289          }          }
         
     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";  
290  }  }
291    undef $sth;
292  $dbh->commit();  $dbh->commit();
293  $dbh->disconnect();  $dbh->disconnect();
294    
295    print "total duration: ",fmt_time(time() - $start_t),"\n";
296    
297  sub haveBeenThere  $pidfile->remove;
298  {  
299    my ($where) = @_;  sub getShareID() {
     
   foreach my $st (@beenThere)  
   {  
     if ($where eq $st)  
     {  
       return 1;  
     }  
   }  
     
   push(@beenThere, $where);  
   return 0;  
 }  
300    
301  sub clearBeenThereCache          my ($share, $hostID, $hostname) = @_;
302  {  
303    @beenThere = ();          $sth->{share_id} ||= $dbh->prepare(qq{
304                    SELECT ID FROM shares WHERE hostID=? AND name=?
305            });
306    
307            $sth->{share_id}->execute($hostID,$share);
308    
309            my ($id) = $sth->{share_id}->fetchrow_array();
310    
311            return $id if (defined($id));
312    
313            $sth->{insert_share} ||= $dbh->prepare(qq{
314                    INSERT INTO shares
315                            (hostID,name,share,localpath)
316                    VALUES (?,?,?,?)
317            });
318    
319            my $drop_down = $hostname . '/' . $share;
320            $drop_down =~ s#//+#/#g;
321    
322            $sth->{insert_share}->execute($hostID,$share, $drop_down ,undef);
323            return $dbh->last_insert_id(undef,undef,'shares',undef);
324  }  }
325    
326  sub getShareID()  sub found_in_db {
327    {  
328        my ($share, $hostID, $hostname) = @_;          my @data = @_;
329        my $tmp;          shift @data;
330          
331        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) = @_;
332        $st -> execute($hostID,$share);  
333        my $tmp = $st->fetchrow_hashref();          return $beenThere->{$key} if (defined($beenThere->{$key}));
334        $st->finish();  
335        if ($tmp)          $sth->{file_in_db} ||= $dbh->prepare(qq{
336          {                  SELECT 1 FROM files
337              return $tmp->{'ID'};                  WHERE shareID = ? and
338          }                          path = ? and
339        my $sql =                          name = ? and
340            q{                          date = ? and
341                INSERT INTO shares(ID,hostID,name,share,localpath)                          size = ?
342                  VALUES            });
343                 (NULL,}.                    
344                "$hostID,\"$share\",\"//$hostname$share\",NULL);";                        my @param = ($shareID,$path,$name,$date,$size);
345        $dbh->do($sql);          $sth->{file_in_db}->execute(@param);
346        return $dbh->func('last_insert_rowid');                    my $rows = $sth->{file_in_db}->rows;
347    }          print STDERR "## found_in_db ",( $rows ? '+' : '-' ), join(" ",@param), "\n" if ($debug >= 3);
348    
349            $beenThere->{$key}++;
350    
351            $sth->{'insert_files'}->execute(@data) unless ($rows);
352            return $rows;
353    }
354    
355  ####################################################  ####################################################
356  # recursing through filesystem structure and       #  # recursing through filesystem structure and       #
357  # and returning flattened files list               #  # and returning flattened files list               #
358  ####################################################  ####################################################
359  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 = "";  
360    
361            my ($bpc, $hostname, $files, $backupNum, $share, $dir, $shareID) = @_;
362    # first, add all the entries in current directory  
363    foreach $file_key (keys %{$filesInBackup})          print STDERR "\nrecurse($hostname,$backupNum,$share,$dir,$shareID)\n" if ($debug >= 1);
364    {  
365      push(@ret, {          my ($nr_files, $new_files, $nr_dirs, $new_dirs, $size) = (0,0,0,0,0);
366                   'fileName' => $file_key,  
367                   'relPath'  => $filesInBackup->{$file_key}->{'relPath'},          { # scope
368                   'fullPath' => $filesInBackup->{$file_key}->{'fullPath'},                  my @stack;
369                   'sharePath'=> $filesInBackup->{$file_key}->{'sharePathM'},  
370                   'size'     => $filesInBackup->{$file_key}->{'size'},                  print STDERR "# dirAttrib($backupNum, $share, $dir)\n" if ($debug >= 2);
371                   'mtime'    => $filesInBackup->{$file_key}->{'mtime'},                  my $filesInBackup = $files->dirAttrib($backupNum, $share, $dir);
372                   'type'     => $filesInBackup->{$file_key}->{'type'}  
373                 });                    # first, add all the entries in current directory
374    }                  foreach my $path_key (keys %{$filesInBackup}) {
375                                print STDERR "# file ",Dumper($filesInBackup->{$path_key}),"\n" if ($debug >= 3);
376    # then, recurse thru subfolders                          my @data = (
377    foreach my $fold (@ret)                                  $shareID,
378    {                                  $backupNum,
379     if ($fold->{'type'} == BPC_FTYPE_DIR &&                                  $path_key,
380         haveBeenThere($fold->{'relPath'}) != 1                                  $filesInBackup->{$path_key}->{'relPath'},
381        )                                  $filesInBackup->{$path_key}->{'mtime'},
382      {                                  $filesInBackup->{$path_key}->{'type'},
383                                          $filesInBackup->{$path_key}->{'size'}
384        push(@ret,                          );
385             recurseDir($bpc, $hostname, $backups, $backupNo, $share, $fold->{'relPath'})  
386            );                          my $key = join(" ", (
387      }                                  $shareID,
388    }                                  $dir,
389    return @ret;                                  $path_key,
390                                    $filesInBackup->{$path_key}->{'mtime'},
391                                    $filesInBackup->{$path_key}->{'size'}
392                            ));
393    
394    
395                            if (! defined($beenThere->{$key}) && ! found_in_db($key, @data)) {
396                                    print STDERR "# key: $key [", $beenThere->{$key},"]" if ($debug >= 2);
397    
398                                    if ($filesInBackup->{$path_key}->{'type'} == BPC_FTYPE_DIR) {
399                                            $new_dirs++;
400                                            print STDERR " dir\n" if ($debug >= 2);
401                                    } else {
402                                            $new_files++;
403                                            print STDERR " file\n" if ($debug >= 2);
404                                    }
405                                    $size += $filesInBackup->{$path_key}->{'size'} || 0;
406                            }
407    
408                            if ($filesInBackup->{$path_key}->{'type'} == BPC_FTYPE_DIR) {
409                                    $nr_dirs++;
410    
411                                    my $full_path = $dir . '/' . $path_key;
412                                    push @stack, $full_path;
413                                    print STDERR "### store to stack: $full_path\n" if ($debug >= 3);
414    
415    #                               my ($f,$nf,$d,$nd) = recurseDir($bpc, $hostname, $backups, $backupNum, $share, $path_key, $shareID) unless ($beenThere->{$key});
416    #
417    #                               $nr_files += $f;
418    #                               $new_files += $nf;
419    #                               $nr_dirs += $d;
420    #                               $new_dirs += $nd;
421    
422                            } else {
423                                    $nr_files++;
424                            }
425                    }
426    
427                    print STDERR "## STACK ",join(", ", @stack),"\n" if ($debug >= 2);
428    
429                    while ( my $dir = shift @stack ) {
430                            my ($f,$nf,$d,$nd, $s) = recurseDir($bpc, $hostname, $files, $backupNum, $share, $dir, $shareID);
431                            print STDERR "# $dir f: $f nf: $nf d: $d nd: $nd\n" if ($debug >= 1);
432                            $nr_files += $f;
433                            $new_files += $nf;
434                            $nr_dirs += $d;
435                            $new_dirs += $nd;
436                            $size += $s;
437                    }
438            }
439    
440            return ($nr_files, $new_files, $nr_dirs, $new_dirs, $size);
441  }  }
442    

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

  ViewVC Help
Powered by ViewVC 1.1.26