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

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

  ViewVC Help
Powered by ViewVC 1.1.26