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

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

  ViewVC Help
Powered by ViewVC 1.1.26