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

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

  ViewVC Help
Powered by ViewVC 1.1.26