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

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

  ViewVC Help
Powered by ViewVC 1.1.26