/[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

Annotation of /trunk/bin/BackupPC_updatedb

Parent Directory Parent Directory | Revision Log Revision Log


Revision 49 - (hide annotations)
Sat Aug 20 15:01:48 2005 UTC (18 years, 9 months ago) by dpavlin
File size: 9537 byte(s)
changes to make it work on PostgreSQL (and add general DBD independence), added
unique indexes, fixed schema, converted primary keys to serial.

This change breaks search for sure, but PostgreSQL is faster than SQLite on
my laptop:

User+System Time
SQLite		24.96514 
PostgreSQL	11.08451


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

Properties

Name Value
svn:executable *

  ViewVC Help
Powered by ViewVC 1.1.26