/[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 250 - (hide annotations)
Sun Dec 11 14:27:45 2005 UTC (18 years, 5 months ago) by dpavlin
File size: 17577 byte(s)
create pid file from full path (to enable multiple instances to run in
parallel), update backup in eval, and rollback if needed (for partial
backups mostly)

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 118 use BackupPC::SearchLib;
15 dpavlin 250 use Cwd qw/abs_path/;
16 dpavlin 48
17 dpavlin 6 use constant BPC_FTYPE_DIR => 5;
18 dpavlin 99 use constant EST_CHUNK => 100000;
19 dpavlin 6
20 dpavlin 246 # daylight saving time change offset for 1h
21     my $dst_offset = 60 * 60;
22    
23 dpavlin 30 my $debug = 0;
24 dpavlin 14 $|=1;
25 dpavlin 6
26 dpavlin 51 my $start_t = time();
27    
28 dpavlin 250 my $pid_path = abs_path($0);
29     $pid_path =~ s/\W+/_/g;
30 dpavlin 38
31 dpavlin 250 my $pidfile = new File::Pid({
32     file => "/tmp/$pid_path",
33     });
34    
35 dpavlin 38 if (my $pid = $pidfile->running ) {
36     die "$0 already running: $pid\n";
37     } elsif ($pidfile->pid ne $$) {
38     $pidfile->remove;
39     $pidfile = new File::Pid;
40     }
41 dpavlin 250 print STDERR "$0 using pid ",$pidfile->pid," file ",$pidfile->file,"\n";
42 dpavlin 39 $pidfile->write;
43 dpavlin 38
44 dpavlin 37 my $t_fmt = '%Y-%m-%d %H:%M:%S';
45    
46 dpavlin 6 my $hosts;
47     my $bpc = BackupPC::Lib->new || die;
48     my %Conf = $bpc->Conf();
49     my $TopDir = $bpc->TopDir();
50 dpavlin 14 my $beenThere = {};
51 dpavlin 6
52 dpavlin 51 my $dsn = $Conf{SearchDSN} || die "Need SearchDSN in config.pl\n";
53     my $user = $Conf{SearchUser} || '';
54 dpavlin 116
55     my $use_hest = $Conf{HyperEstraierIndex};
56 dpavlin 118 my ($index_path, $index_node_url) = BackupPC::SearchLib::getHyperEstraier_url($use_hest);
57 dpavlin 6
58 dpavlin 49 my $dbh = DBI->connect($dsn, $user, "", { RaiseError => 1, AutoCommit => 0 });
59    
60 dpavlin 6 my %opt;
61    
62 dpavlin 246 if ( !getopts("cdm:v:ijf", \%opt ) ) {
63 dpavlin 6 print STDERR <<EOF;
64 dpavlin 246 usage: $0 [-c|-d] [-m num] [-v|-v level] [-i|-j|-f]
65 dpavlin 6
66     Options:
67 dpavlin 14 -c create database on first use
68     -d delete database before import
69     -m num import just num increments for one host
70 dpavlin 44 -v num set verbosity (debug) level (default $debug)
71 dpavlin 131 -i update Hyper Estraier full text index
72     -j update full text, don't check existing files
73 dpavlin 246 -f don't do anything with full text index
74 dpavlin 131
75     Option -j is variation on -i. It will allow faster initial creation
76     of full-text index from existing database.
77    
78 dpavlin 246 Option -f will create database which is out of sync with full text index. You
79     will have to re-run $0 with -i to fix it.
80    
81 dpavlin 6 EOF
82     exit 1;
83     }
84    
85 dpavlin 81 if ($opt{v}) {
86     print "Debug level at $opt{v}\n";
87     $debug = $opt{v};
88 dpavlin 246 } elsif ($opt{f}) {
89     print "WARNING: disabling full-text index update. You need to re-run $0 -j !\n";
90     ($use_hest, $index_path, $index_node_url) = (undef, undef, undef);
91 dpavlin 81 }
92    
93 dpavlin 86 #---- subs ----
94    
95     sub fmt_time {
96     my $t = shift || return;
97     my $out = "";
98     my ($ss,$mm,$hh) = gmtime($t);
99     $out .= "${hh}h" if ($hh);
100     $out .= sprintf("%02d:%02d", $mm,$ss);
101     return $out;
102     }
103    
104     sub curr_time {
105     return strftime($t_fmt,localtime());
106     }
107    
108 dpavlin 89 my $hest_db;
109 dpavlin 116 my $hest_node;
110 dpavlin 86
111 dpavlin 97 sub signal {
112     my($sig) = @_;
113     if ($hest_db) {
114     print "\nCaught a SIG$sig--syncing database and shutting down\n";
115     $hest_db->sync();
116     $hest_db->close();
117     }
118     exit(0);
119     }
120    
121     $SIG{'INT'} = \&signal;
122     $SIG{'QUIT'} = \&signal;
123    
124 dpavlin 89 sub hest_update {
125 dpavlin 81
126 dpavlin 89 my ($host_id, $share_id, $num) = @_;
127    
128 dpavlin 131 my $skip_check = $opt{j} && print STDERR "Skipping check for existing files -- this should be used only with initital import\n";
129    
130 dpavlin 248 unless (defined($use_hest)) {
131 dpavlin 116 print STDERR "HyperEstraier support not enabled in configuration\n";
132 dpavlin 248 $use_hest = 0;
133 dpavlin 116 return;
134     }
135    
136 dpavlin 249 return unless($use_hest);
137    
138 dpavlin 98 print curr_time," updating HyperEstraier:";
139 dpavlin 86
140     my $t = time();
141 dpavlin 89
142 dpavlin 98 my $offset = 0;
143     my $added = 0;
144 dpavlin 89
145 dpavlin 130 print " opening index $use_hest";
146 dpavlin 116 if ($index_path) {
147     $hest_db = HyperEstraier::Database->new();
148 dpavlin 118 $hest_db->open($TopDir . $index_path, $HyperEstraier::Database::DBWRITER | $HyperEstraier::Database::DBCREAT);
149 dpavlin 130 print " directly";
150 dpavlin 116 } elsif ($index_node_url) {
151     $hest_node ||= HyperEstraier::Node->new($index_node_url);
152     $hest_node->set_auth('admin', 'admin');
153 dpavlin 130 print " via node URL";
154 dpavlin 116 } else {
155     die "don't know how to use HyperEstraier Index $use_hest";
156     }
157 dpavlin 107 print " increment is " . EST_CHUNK . " files:";
158 dpavlin 99
159 dpavlin 98 my $results = 0;
160 dpavlin 81
161 dpavlin 98 do {
162 dpavlin 81
163 dpavlin 98 my $where = '';
164 dpavlin 104 my @data;
165 dpavlin 190 if (defined($host_id) && defined($share_id) && defined($num)) {
166 dpavlin 98 $where = qq{
167     WHERE
168     hosts.id = ? AND
169     shares.id = ? AND
170     files.backupnum = ?
171     };
172 dpavlin 104 @data = ( $host_id, $share_id, $num );
173 dpavlin 98 }
174 dpavlin 89
175 dpavlin 98 my $limit = sprintf('LIMIT '.EST_CHUNK.' OFFSET %d', $offset);
176 dpavlin 81
177 dpavlin 98 my $sth = $dbh->prepare(qq{
178     SELECT
179     files.id AS fid,
180     hosts.name AS hname,
181     shares.name AS sname,
182     -- shares.share AS sharename,
183     files.backupnum AS backupnum,
184     -- files.name AS filename,
185     files.path AS filepath,
186     files.date AS date,
187     files.type AS type,
188     files.size AS size,
189     files.shareid AS shareid,
190     backups.date AS backup_date
191     FROM files
192     INNER JOIN shares ON files.shareID=shares.ID
193     INNER JOIN hosts ON hosts.ID = shares.hostID
194     INNER JOIN backups ON backups.num = files.backupNum and backups.hostID = hosts.ID AND backups.shareID = shares.ID
195     $where
196     $limit
197     });
198 dpavlin 81
199 dpavlin 104 $sth->execute(@data);
200 dpavlin 98 $results = $sth->rows;
201 dpavlin 81
202 dpavlin 98 if ($results == 0) {
203 dpavlin 107 print " - no new files\n";
204 dpavlin 98 last;
205     }
206 dpavlin 89
207 dpavlin 98 sub fmt_date {
208     my $t = shift || return;
209     my $iso = BackupPC::Lib::timeStamp($t);
210     $iso =~ s/\s/T/;
211     return $iso;
212     }
213 dpavlin 89
214 dpavlin 98 while (my $row = $sth->fetchrow_hashref()) {
215 dpavlin 89
216 dpavlin 98 my $fid = $row->{'fid'} || die "no fid?";
217     my $uri = 'file:///' . $fid;
218 dpavlin 82
219 dpavlin 131 unless ($skip_check) {
220     my $id = ($hest_db || $hest_node)->uri_to_id($uri);
221     next unless ($id == -1);
222     }
223 dpavlin 82
224 dpavlin 98 # create a document object
225     my $doc = HyperEstraier::Document->new;
226 dpavlin 81
227 dpavlin 98 # add attributes to the document object
228     $doc->add_attr('@uri', $uri);
229 dpavlin 89
230 dpavlin 98 foreach my $c (@{ $sth->{NAME} }) {
231 dpavlin 241 $doc->add_attr($c, $row->{$c}) if (defined($row->{$c}));
232 dpavlin 98 }
233 dpavlin 89
234 dpavlin 98 #$doc->add_attr('@cdate', fmt_date($row->{'date'}));
235 dpavlin 81
236 dpavlin 98 # add the body text to the document object
237     my $path = $row->{'filepath'};
238     $doc->add_text($path);
239     $path =~ s/(.)/$1 /g;
240     $doc->add_hidden_text($path);
241 dpavlin 81
242 dpavlin 98 print STDERR $doc->dump_draft,"\n" if ($debug > 1);
243    
244     # register the document object to the database
245 dpavlin 116 if ($hest_db) {
246     $hest_db->put_doc($doc, $HyperEstraier::Database::PDCLEAN);
247     } elsif ($hest_node) {
248     $hest_node->put_doc($doc);
249     } else {
250     die "not supported";
251     }
252 dpavlin 98 $added++;
253 dpavlin 81 }
254    
255 dpavlin 98 print " $added";
256 dpavlin 116 $hest_db->sync() if ($index_path);
257 dpavlin 81
258 dpavlin 98 $offset += EST_CHUNK;
259 dpavlin 81
260 dpavlin 98 } while ($results == EST_CHUNK);
261 dpavlin 81
262 dpavlin 116 if ($index_path) {
263     print ", close";
264     $hest_db->close();
265     }
266 dpavlin 81
267 dpavlin 86 my $dur = (time() - $t) || 1;
268 dpavlin 98 printf(" [%.2f/s dur: %s]\n",
269 dpavlin 89 ( $added / $dur ),
270 dpavlin 86 fmt_time($dur)
271     );
272 dpavlin 89 }
273 dpavlin 86
274 dpavlin 89 #---- /subs ----
275    
276    
277     ## update index ##
278 dpavlin 239 if (($opt{i} || $opt{j} || ($index_path && ! -e $TopDir . $index_path)) && !$opt{c}) {
279 dpavlin 89 # update all
280     print "force update of HyperEstraier index ";
281 dpavlin 239 print "importing existing data" unless (-e $TopDir . $index_path);
282 dpavlin 89 print "by -i flag" if ($opt{i});
283 dpavlin 131 print "by -j flag" if ($opt{j});
284 dpavlin 89 print "\n";
285     hest_update();
286 dpavlin 81 }
287    
288 dpavlin 89 ## create tables ##
289 dpavlin 14 if ($opt{c}) {
290 dpavlin 49 sub do_index {
291     my $index = shift || return;
292 dpavlin 152 my ($table,$col,$unique) = split(/:/, $index);
293 dpavlin 49 $unique ||= '';
294 dpavlin 152 $index =~ s/\W+/_/g;
295     print "$index on $table($col)" . ( $unique ? "u" : "" ) . " ";
296 dpavlin 49 $dbh->do(qq{ create $unique index $index on $table($col) });
297     }
298    
299 dpavlin 14 print "creating tables...\n";
300 dpavlin 183
301     $dbh->do( qq{
302 dpavlin 14 create table hosts (
303 dpavlin 49 ID SERIAL PRIMARY KEY,
304 dpavlin 14 name VARCHAR(30) NOT NULL,
305     IP VARCHAR(15)
306 dpavlin 6 );
307 dpavlin 183
308 dpavlin 14 create table shares (
309 dpavlin 49 ID SERIAL PRIMARY KEY,
310 dpavlin 14 hostID INTEGER NOT NULL references hosts(id),
311     name VARCHAR(30) NOT NULL,
312 dpavlin 152 share VARCHAR(200) NOT NULL
313 dpavlin 6 );
314 dpavlin 130
315     create table dvds (
316     ID SERIAL PRIMARY KEY,
317     num INTEGER NOT NULL,
318     name VARCHAR(255) NOT NULL,
319     mjesto VARCHAR(255)
320     );
321 dpavlin 183
322 dpavlin 14 create table backups (
323 dpavlin 152 id serial,
324 dpavlin 14 hostID INTEGER NOT NULL references hosts(id),
325     num INTEGER NOT NULL,
326 dpavlin 49 date integer NOT NULL,
327     type CHAR(4) not null,
328 dpavlin 65 shareID integer not null references shares(id),
329 dpavlin 136 size bigint not null,
330 dpavlin 152 inc_size bigint not null default -1,
331     inc_deleted boolean default false,
332 dpavlin 196 parts integer not null default 1,
333 dpavlin 152 PRIMARY KEY(id)
334 dpavlin 6 );
335    
336 dpavlin 14 create table files (
337 dpavlin 152 ID SERIAL,
338     shareID INTEGER NOT NULL references shares(id),
339     backupNum INTEGER NOT NULL,
340     name VARCHAR(255) NOT NULL,
341     path VARCHAR(255) NOT NULL,
342     date integer NOT NULL,
343     type INTEGER NOT NULL,
344     size bigint NOT NULL,
345     primary key(id)
346 dpavlin 6 );
347    
348 dpavlin 152 create table archive (
349     id serial,
350 dpavlin 130 dvd_nr int not null,
351 dpavlin 152 total_size bigint default -1,
352 dpavlin 130 note text,
353     username varchar(20) not null,
354 dpavlin 152 date timestamp default now(),
355 dpavlin 130 primary key(id)
356     );
357    
358 dpavlin 183 create table archive_backup (
359 dpavlin 160 archive_id int not null references archive(id) on delete cascade,
360 dpavlin 152 backup_id int not null references backups(id),
361 dpavlin 130 primary key(archive_id, backup_id)
362     );
363 dpavlin 183
364     create table archive_burned (
365 dpavlin 199 archive_id int references archive(id),
366 dpavlin 202 date timestamp default now(),
367 dpavlin 199 part int not null default 1,
368 dpavlin 202 copy int not null default 1,
369 dpavlin 196 iso_size bigint default -1
370 dpavlin 183 );
371    
372 dpavlin 235 create table backup_parts (
373     id serial,
374     backup_id int references backups(id),
375     part_nr int not null check (part_nr > 0),
376     tar_size bigint not null check (tar_size > 0),
377     size bigint not null check (size > 0),
378     md5 text not null,
379     items int not null check (items > 0),
380     date timestamp default now(),
381     primary key(id)
382     );
383 dpavlin 130 });
384    
385 dpavlin 153 print "creating indexes: ";
386 dpavlin 6
387 dpavlin 14 foreach my $index (qw(
388 dpavlin 152 hosts:name
389     backups:hostID
390     backups:num
391     backups:shareID
392     shares:hostID
393     shares:name
394     files:shareID
395     files:path
396     files:name
397     files:date
398     files:size
399     archive:dvd_nr
400 dpavlin 183 archive_burned:archive_id
401 dpavlin 235 backup_parts:backup_id,part_nr
402 dpavlin 14 )) {
403 dpavlin 49 do_index($index);
404 dpavlin 14 }
405 dpavlin 153
406     print " creating sequence: ";
407     foreach my $seq (qw/dvd_nr/) {
408     print "$seq ";
409     $dbh->do( qq{ CREATE SEQUENCE $seq } );
410     }
411    
412    
413 dpavlin 49 print "...\n";
414 dpavlin 14
415 dpavlin 49 $dbh->commit;
416 dpavlin 14
417     }
418    
419 dpavlin 89 ## delete data before inseting ##
420 dpavlin 14 if ($opt{d}) {
421     print "deleting ";
422 dpavlin 49 foreach my $table (qw(files dvds backups shares hosts)) {
423 dpavlin 14 print "$table ";
424     $dbh->do(qq{ DELETE FROM $table });
425     }
426     print " done...\n";
427 dpavlin 49
428 dpavlin 51 $dbh->commit;
429 dpavlin 14 }
430    
431 dpavlin 89 ## insert new values ##
432 dpavlin 6
433     # get hosts
434 dpavlin 8 $hosts = $bpc->HostInfoRead();
435 dpavlin 6 my $hostID;
436     my $shareID;
437    
438 dpavlin 14 my $sth;
439 dpavlin 6
440 dpavlin 14 $sth->{insert_hosts} = $dbh->prepare(qq{
441     INSERT INTO hosts (name, IP) VALUES (?,?)
442     });
443 dpavlin 6
444 dpavlin 14 $sth->{hosts_by_name} = $dbh->prepare(qq{
445     SELECT ID FROM hosts WHERE name=?
446     });
447    
448 dpavlin 65 $sth->{backups_count} = $dbh->prepare(qq{
449 dpavlin 14 SELECT COUNT(*)
450     FROM backups
451 dpavlin 65 WHERE hostID=? AND num=? AND shareid=?
452 dpavlin 14 });
453    
454     $sth->{insert_backups} = $dbh->prepare(qq{
455 dpavlin 66 INSERT INTO backups (hostID, num, date, type, shareid, size)
456 dpavlin 242 VALUES (?,?,?,?,?,-1)
457 dpavlin 14 });
458    
459 dpavlin 242 $sth->{update_backups_size} = $dbh->prepare(qq{
460     UPDATE backups SET size = ?
461     WHERE hostID = ? and num = ? and date = ? and type =? and shareid = ?
462     });
463    
464 dpavlin 14 $sth->{insert_files} = $dbh->prepare(qq{
465     INSERT INTO files
466 dpavlin 62 (shareID, backupNum, name, path, date, type, size)
467     VALUES (?,?,?,?,?,?,?)
468 dpavlin 14 });
469    
470 dpavlin 248 my @hosts = keys %{$hosts};
471     my $host_nr = 0;
472 dpavlin 14
473 dpavlin 248 foreach my $host_key (@hosts) {
474    
475 dpavlin 14 my $hostname = $hosts->{$host_key}->{'host'} || die "can't find host for $host_key";
476    
477     $sth->{hosts_by_name}->execute($hosts->{$host_key}->{'host'});
478    
479     unless (($hostID) = $sth->{hosts_by_name}->fetchrow_array()) {
480     $sth->{insert_hosts}->execute(
481     $hosts->{$host_key}->{'host'},
482     $hosts->{$host_key}->{'ip'}
483     );
484    
485 dpavlin 49 $hostID = $dbh->last_insert_id(undef,undef,'hosts',undef);
486 dpavlin 14 }
487    
488 dpavlin 248 $host_nr++;
489     print "host ", $hosts->{$host_key}->{'host'}, " [",
490     $host_nr, "/", ($#hosts + 1), "]: ";
491 dpavlin 6
492 dpavlin 14 # get backups for a host
493     my @backups = $bpc->BackupInfoRead($hostname);
494 dpavlin 67 my $incs = scalar @backups;
495     print "$incs increments\n";
496 dpavlin 6
497 dpavlin 14 my $inc_nr = 0;
498 dpavlin 67 $beenThere = {};
499 dpavlin 14
500     foreach my $backup (@backups) {
501 dpavlin 40
502 dpavlin 14 $inc_nr++;
503     last if ($opt{m} && $inc_nr > $opt{m});
504    
505     my $backupNum = $backup->{'num'};
506     my @backupShares = ();
507    
508 dpavlin 67 printf("%-10s %2d/%-2d #%-2d %s %5s/%5s files (date: %s dur: %s)\n",
509     $hosts->{$host_key}->{'host'},
510     $inc_nr, $incs, $backupNum,
511     $backup->{type} || '?',
512     $backup->{nFilesNew} || '?', $backup->{nFiles} || '?',
513 dpavlin 57 strftime($t_fmt,localtime($backup->{startTime})),
514 dpavlin 67 fmt_time($backup->{endTime} - $backup->{startTime})
515     );
516 dpavlin 14
517 dpavlin 34 my $files = BackupPC::View->new($bpc, $hostname, \@backups, 1);
518 dpavlin 14 foreach my $share ($files->shareList($backupNum)) {
519    
520 dpavlin 37 my $t = time();
521    
522 dpavlin 14 $shareID = getShareID($share, $hostID, $hostname);
523    
524 dpavlin 65 $sth->{backups_count}->execute($hostID, $backupNum, $shareID);
525     my ($count) = $sth->{backups_count}->fetchrow_array();
526     # skip if allready in database!
527     next if ($count > 0);
528    
529     # dump some log
530 dpavlin 86 print curr_time," ", $share;
531 dpavlin 65
532 dpavlin 242 $sth->{insert_backups}->execute(
533     $hostID,
534     $backupNum,
535     $backup->{'endTime'},
536     substr($backup->{'type'},0,4),
537     $shareID,
538     );
539    
540 dpavlin 66 my ($f, $nf, $d, $nd, $size) = recurseDir($bpc, $hostname, $files, $backupNum, $share, "", $shareID);
541 dpavlin 65
542 dpavlin 250 eval {
543     $sth->{update_backups_size}->execute(
544     $size,
545     $hostID,
546     $backupNum,
547     $backup->{'endTime'},
548     substr($backup->{'type'},0,4),
549     $shareID,
550     );
551     print " commit";
552     $dbh->commit();
553     };
554     if ($@) {
555     print " rollback";
556     $dbh->rollback();
557     }
558 dpavlin 65
559 dpavlin 50 my $dur = (time() - $t) || 1;
560 dpavlin 66 printf(" %d/%d files %d/%d dirs %0.2f MB [%.2f/s dur: %s]\n",
561 dpavlin 37 $nf, $f, $nd, $d,
562 dpavlin 66 ($size / 1024 / 1024),
563 dpavlin 50 ( ($f+$d) / $dur ),
564     fmt_time($dur)
565 dpavlin 37 );
566 dpavlin 89
567 dpavlin 107 hest_update($hostID, $shareID, $backupNum) if ($nf + $nd > 0);
568 dpavlin 14 }
569 dpavlin 29
570 dpavlin 6 }
571     }
572 dpavlin 14 undef $sth;
573 dpavlin 6 $dbh->commit();
574     $dbh->disconnect();
575    
576 dpavlin 51 print "total duration: ",fmt_time(time() - $start_t),"\n";
577    
578 dpavlin 38 $pidfile->remove;
579    
580 dpavlin 14 sub getShareID() {
581 dpavlin 6
582 dpavlin 14 my ($share, $hostID, $hostname) = @_;
583    
584     $sth->{share_id} ||= $dbh->prepare(qq{
585     SELECT ID FROM shares WHERE hostID=? AND name=?
586     });
587    
588     $sth->{share_id}->execute($hostID,$share);
589    
590     my ($id) = $sth->{share_id}->fetchrow_array();
591    
592     return $id if (defined($id));
593    
594     $sth->{insert_share} ||= $dbh->prepare(qq{
595     INSERT INTO shares
596 dpavlin 152 (hostID,name,share)
597     VALUES (?,?,?)
598 dpavlin 14 });
599    
600 dpavlin 25 my $drop_down = $hostname . '/' . $share;
601     $drop_down =~ s#//+#/#g;
602    
603 dpavlin 152 $sth->{insert_share}->execute($hostID,$share, $drop_down);
604 dpavlin 49 return $dbh->last_insert_id(undef,undef,'shares',undef);
605 dpavlin 6 }
606    
607 dpavlin 14 sub found_in_db {
608    
609 dpavlin 48 my @data = @_;
610     shift @data;
611 dpavlin 14
612 dpavlin 74 my ($key, $shareID,undef,$name,$path,$date,undef,$size) = @_;
613 dpavlin 48
614     return $beenThere->{$key} if (defined($beenThere->{$key}));
615    
616 dpavlin 14 $sth->{file_in_db} ||= $dbh->prepare(qq{
617 dpavlin 48 SELECT 1 FROM files
618 dpavlin 14 WHERE shareID = ? and
619     path = ? and
620 dpavlin 246 size = ? and
621     ( date = ? or date = ? or date = ? )
622 dpavlin 74 LIMIT 1
623 dpavlin 14 });
624    
625 dpavlin 246 my @param = ($shareID,$path,$size,$date, $date-$dst_offset, $date+$dst_offset);
626 dpavlin 14 $sth->{file_in_db}->execute(@param);
627 dpavlin 48 my $rows = $sth->{file_in_db}->rows;
628 dpavlin 74 print STDERR "## found_in_db($shareID,$path,$date,$size) ",( $rows ? '+' : '-' ), join(" ",@param), "\n" if ($debug >= 3);
629 dpavlin 48
630     $beenThere->{$key}++;
631    
632     $sth->{'insert_files'}->execute(@data) unless ($rows);
633 dpavlin 14 return $rows;
634 dpavlin 6 }
635    
636     ####################################################
637     # recursing through filesystem structure and #
638     # and returning flattened files list #
639     ####################################################
640 dpavlin 14 sub recurseDir($$$$$$$$) {
641 dpavlin 6
642 dpavlin 35 my ($bpc, $hostname, $files, $backupNum, $share, $dir, $shareID) = @_;
643 dpavlin 14
644 dpavlin 44 print STDERR "\nrecurse($hostname,$backupNum,$share,$dir,$shareID)\n" if ($debug >= 1);
645 dpavlin 29
646 dpavlin 66 my ($nr_files, $new_files, $nr_dirs, $new_dirs, $size) = (0,0,0,0,0);
647 dpavlin 14
648 dpavlin 27 { # scope
649 dpavlin 29 my @stack;
650 dpavlin 14
651 dpavlin 45 print STDERR "# dirAttrib($backupNum, $share, $dir)\n" if ($debug >= 2);
652 dpavlin 27 my $filesInBackup = $files->dirAttrib($backupNum, $share, $dir);
653 dpavlin 14
654 dpavlin 27 # first, add all the entries in current directory
655     foreach my $path_key (keys %{$filesInBackup}) {
656 dpavlin 66 print STDERR "# file ",Dumper($filesInBackup->{$path_key}),"\n" if ($debug >= 3);
657 dpavlin 27 my @data = (
658     $shareID,
659     $backupNum,
660     $path_key,
661     $filesInBackup->{$path_key}->{'relPath'},
662     $filesInBackup->{$path_key}->{'mtime'},
663     $filesInBackup->{$path_key}->{'type'},
664     $filesInBackup->{$path_key}->{'size'}
665     );
666    
667     my $key = join(" ", (
668     $shareID,
669     $dir,
670     $path_key,
671     $filesInBackup->{$path_key}->{'mtime'},
672     $filesInBackup->{$path_key}->{'size'}
673     ));
674    
675 dpavlin 242 my $key_dst_prev = join(" ", (
676 dpavlin 240 $shareID,
677     $dir,
678     $path_key,
679     $filesInBackup->{$path_key}->{'mtime'} - $dst_offset,
680     $filesInBackup->{$path_key}->{'size'}
681     ));
682    
683 dpavlin 242 my $key_dst_next = join(" ", (
684 dpavlin 240 $shareID,
685     $dir,
686     $path_key,
687     $filesInBackup->{$path_key}->{'mtime'} + $dst_offset,
688     $filesInBackup->{$path_key}->{'size'}
689     ));
690    
691 dpavlin 70 my $found;
692 dpavlin 240 if (
693     ! defined($beenThere->{$key}) &&
694 dpavlin 242 ! defined($beenThere->{$key_dst_prev}) &&
695     ! defined($beenThere->{$key_dst_next}) &&
696 dpavlin 240 ! ($found = found_in_db($key, @data))
697     ) {
698 dpavlin 30 print STDERR "# key: $key [", $beenThere->{$key},"]" if ($debug >= 2);
699 dpavlin 48
700 dpavlin 27 if ($filesInBackup->{$path_key}->{'type'} == BPC_FTYPE_DIR) {
701 dpavlin 70 $new_dirs++ unless ($found);
702 dpavlin 30 print STDERR " dir\n" if ($debug >= 2);
703 dpavlin 27 } else {
704 dpavlin 70 $new_files++ unless ($found);
705 dpavlin 30 print STDERR " file\n" if ($debug >= 2);
706 dpavlin 27 }
707 dpavlin 66 $size += $filesInBackup->{$path_key}->{'size'} || 0;
708 dpavlin 27 }
709    
710 dpavlin 14 if ($filesInBackup->{$path_key}->{'type'} == BPC_FTYPE_DIR) {
711 dpavlin 27 $nr_dirs++;
712    
713 dpavlin 29 my $full_path = $dir . '/' . $path_key;
714     push @stack, $full_path;
715 dpavlin 30 print STDERR "### store to stack: $full_path\n" if ($debug >= 3);
716 dpavlin 29
717 dpavlin 27 # my ($f,$nf,$d,$nd) = recurseDir($bpc, $hostname, $backups, $backupNum, $share, $path_key, $shareID) unless ($beenThere->{$key});
718     #
719     # $nr_files += $f;
720     # $new_files += $nf;
721     # $nr_dirs += $d;
722     # $new_dirs += $nd;
723    
724 dpavlin 14 } else {
725 dpavlin 27 $nr_files++;
726 dpavlin 14 }
727     }
728    
729 dpavlin 30 print STDERR "## STACK ",join(", ", @stack),"\n" if ($debug >= 2);
730 dpavlin 14
731 dpavlin 29 while ( my $dir = shift @stack ) {
732 dpavlin 66 my ($f,$nf,$d,$nd, $s) = recurseDir($bpc, $hostname, $files, $backupNum, $share, $dir, $shareID);
733 dpavlin 30 print STDERR "# $dir f: $f nf: $nf d: $d nd: $nd\n" if ($debug >= 1);
734 dpavlin 29 $nr_files += $f;
735     $new_files += $nf;
736     $nr_dirs += $d;
737     $new_dirs += $nd;
738 dpavlin 66 $size += $s;
739 dpavlin 29 }
740 dpavlin 14 }
741    
742 dpavlin 66 return ($nr_files, $new_files, $nr_dirs, $new_dirs, $size);
743 dpavlin 6 }
744    

Properties

Name Value
svn:executable *

  ViewVC Help
Powered by ViewVC 1.1.26