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

Contents of /trunk/bin/BackupPC_updatedb

Parent Directory Parent Directory | Revision Log Revision Log


Revision 104 - (show annotations)
Wed Aug 31 11:05:26 2005 UTC (18 years, 8 months ago) by dpavlin
File size: 13856 byte(s)
fix parametars to execute

1 #!/usr/local/bin/perl -w
2
3 use strict;
4 use lib "__INSTALLDIR__/lib";
5
6 use DBI;
7 use BackupPC::Lib;
8 use BackupPC::View;
9 use Data::Dumper;
10 use Getopt::Std;
11 use Time::HiRes qw/time/;
12 use File::Pid;
13 use POSIX qw/strftime/;
14
15 use constant BPC_FTYPE_DIR => 5;
16 use constant EST_CHUNK => 100000;
17
18 my $debug = 0;
19 $|=1;
20
21 my $start_t = time();
22
23 my $pidfile = new File::Pid;
24
25 if (my $pid = $pidfile->running ) {
26 die "$0 already running: $pid\n";
27 } elsif ($pidfile->pid ne $$) {
28 $pidfile->remove;
29 $pidfile = new File::Pid;
30 }
31 $pidfile->write;
32 print STDERR "$0 using pid ",$pidfile->pid," file ",$pidfile->file,"\n";
33
34 my $t_fmt = '%Y-%m-%d %H:%M:%S';
35
36 my $hosts;
37 my $bpc = BackupPC::Lib->new || die;
38 my %Conf = $bpc->Conf();
39 my $TopDir = $bpc->TopDir();
40 my $beenThere = {};
41
42 my $dsn = $Conf{SearchDSN} || die "Need SearchDSN in config.pl\n";
43 my $user = $Conf{SearchUser} || '';
44 my $index_path = $Conf{HyperEstraierIndex};
45 $index_path = $TopDir . '/' . $index_path;
46 $index_path =~ s#//#/#g;
47 if ($index_path) {
48 use HyperEstraier;
49 }
50
51
52 my $dbh = DBI->connect($dsn, $user, "", { RaiseError => 1, AutoCommit => 0 });
53
54 my %opt;
55
56 if ( !getopts("cdm:v:i", \%opt ) ) {
57 print STDERR <<EOF;
58 usage: $0 [-c|-d] [-m num] [-v|-v level] [-i]
59
60 Options:
61 -c create database on first use
62 -d delete database before import
63 -m num import just num increments for one host
64 -v num set verbosity (debug) level (default $debug)
65 -i update HyperEstraier full text index
66 EOF
67 exit 1;
68 }
69
70 if ($opt{v}) {
71 print "Debug level at $opt{v}\n";
72 $debug = $opt{v};
73 }
74
75 #---- subs ----
76
77 sub fmt_time {
78 my $t = shift || return;
79 my $out = "";
80 my ($ss,$mm,$hh) = gmtime($t);
81 $out .= "${hh}h" if ($hh);
82 $out .= sprintf("%02d:%02d", $mm,$ss);
83 return $out;
84 }
85
86 sub curr_time {
87 return strftime($t_fmt,localtime());
88 }
89
90 my $hest_db;
91
92 sub signal {
93 my($sig) = @_;
94 if ($hest_db) {
95 print "\nCaught a SIG$sig--syncing database and shutting down\n";
96 $hest_db->sync();
97 $hest_db->close();
98 }
99 exit(0);
100 }
101
102 $SIG{'INT'} = \&signal;
103 $SIG{'QUIT'} = \&signal;
104
105 sub hest_update {
106
107 my ($host_id, $share_id, $num) = @_;
108
109 print curr_time," updating HyperEstraier:";
110
111 my $t = time();
112
113 my $offset = 0;
114 my $added = 0;
115
116 print " opening index $index_path";
117 $hest_db = HyperEstraier::Database->new();
118 $hest_db->open($index_path, $HyperEstraier::Database::DBWRITER | $HyperEstraier::Database::DBCREAT);
119
120 print " increment is " . EST_CHUNK . " files";
121
122 my $results = 0;
123
124 do {
125
126 my $where = '';
127 my @data;
128 if ($host_id && $share_id && $num) {
129 $where = qq{
130 WHERE
131 hosts.id = ? AND
132 shares.id = ? AND
133 files.backupnum = ?
134 };
135 @data = ( $host_id, $share_id, $num );
136 }
137
138 my $limit = sprintf('LIMIT '.EST_CHUNK.' OFFSET %d', $offset);
139
140 my $sth = $dbh->prepare(qq{
141 SELECT
142 files.id AS fid,
143 hosts.name AS hname,
144 shares.name AS sname,
145 -- shares.share AS sharename,
146 files.backupnum AS backupnum,
147 -- files.name AS filename,
148 files.path AS filepath,
149 files.date AS date,
150 files.type AS type,
151 files.size AS size,
152 files.shareid AS shareid,
153 backups.date AS backup_date
154 FROM files
155 INNER JOIN shares ON files.shareID=shares.ID
156 INNER JOIN hosts ON hosts.ID = shares.hostID
157 INNER JOIN backups ON backups.num = files.backupNum and backups.hostID = hosts.ID AND backups.shareID = shares.ID
158 $where
159 $limit
160 });
161
162 $sth->execute(@data);
163 $results = $sth->rows;
164
165 if ($results == 0) {
166 print " - no more files\n";
167 last;
168 }
169
170 sub fmt_date {
171 my $t = shift || return;
172 my $iso = BackupPC::Lib::timeStamp($t);
173 $iso =~ s/\s/T/;
174 return $iso;
175 }
176
177 while (my $row = $sth->fetchrow_hashref()) {
178
179 my $fid = $row->{'fid'} || die "no fid?";
180 my $uri = 'file:///' . $fid;
181
182 my $id = $hest_db->uri_to_id($uri);
183 next unless ($id == -1);
184
185 # create a document object
186 my $doc = HyperEstraier::Document->new;
187
188 # add attributes to the document object
189 $doc->add_attr('@uri', $uri);
190
191 foreach my $c (@{ $sth->{NAME} }) {
192 $doc->add_attr($c, $row->{$c}) if ($row->{$c});
193 }
194
195 #$doc->add_attr('@cdate', fmt_date($row->{'date'}));
196
197 # add the body text to the document object
198 my $path = $row->{'filepath'};
199 $doc->add_text($path);
200 $path =~ s/(.)/$1 /g;
201 $doc->add_hidden_text($path);
202
203 print STDERR $doc->dump_draft,"\n" if ($debug > 1);
204
205 # register the document object to the database
206 $hest_db->put_doc($doc, $HyperEstraier::Database::PDCLEAN);
207 $added++;
208 }
209
210 print " $added";
211 $hest_db->sync();
212
213 $offset += EST_CHUNK;
214
215 } while ($results == EST_CHUNK);
216
217 print ", close";
218 $hest_db->close();
219
220 my $dur = (time() - $t) || 1;
221 printf(" [%.2f/s dur: %s]\n",
222 ( $added / $dur ),
223 fmt_time($dur)
224 );
225 }
226
227 #---- /subs ----
228
229
230 ## update index ##
231 if (($opt{i} || ($index_path && ! -e $index_path)) && !$opt{c}) {
232 # update all
233 print "force update of HyperEstraier index ";
234 print "importing existing data" unless (-e $index_path);
235 print "by -i flag" if ($opt{i});
236 print "\n";
237 hest_update();
238 }
239
240 ## create tables ##
241 if ($opt{c}) {
242 sub do_index {
243 my $index = shift || return;
244 my ($table,$col,$unique) = split(/_/, $index);
245 $unique ||= '';
246 $index =~ s/,/_/g;
247 $dbh->do(qq{ create $unique index $index on $table($col) });
248 }
249
250 print "creating tables...\n";
251
252 $dbh->do(qq{
253 create table hosts (
254 ID SERIAL PRIMARY KEY,
255 name VARCHAR(30) NOT NULL,
256 IP VARCHAR(15)
257 );
258 });
259
260 $dbh->do(qq{
261 create table shares (
262 ID SERIAL PRIMARY KEY,
263 hostID INTEGER NOT NULL references hosts(id),
264 name VARCHAR(30) NOT NULL,
265 share VARCHAR(200) NOT NULL,
266 localpath VARCHAR(200)
267 );
268 });
269
270 $dbh->do(qq{
271 create table backups (
272 hostID INTEGER NOT NULL references hosts(id),
273 num INTEGER NOT NULL,
274 date integer NOT NULL,
275 type CHAR(4) not null,
276 shareID integer not null references shares(id),
277 size integer not null,
278 PRIMARY KEY(hostID, num, shareID)
279 );
280 });
281
282 #do_index('backups_hostid,num_unique');
283
284 $dbh->do(qq{
285 create table dvds (
286 ID SERIAL PRIMARY KEY,
287 num INTEGER NOT NULL,
288 name VARCHAR(255) NOT NULL,
289 mjesto VARCHAR(255)
290 );
291 });
292
293 $dbh->do(qq{
294 create table files (
295 ID SERIAL PRIMARY KEY,
296 shareID INTEGER NOT NULL references shares(id),
297 backupNum INTEGER NOT NULL,
298 name VARCHAR(255) NOT NULL,
299 path VARCHAR(255) NOT NULL,
300 date integer NOT NULL,
301 type INTEGER NOT NULL,
302 size INTEGER NOT NULL,
303 dvdid INTEGER references dvds(id)
304 );
305 });
306
307 print "creating indexes:";
308
309 foreach my $index (qw(
310 hosts_name
311 backups_hostID
312 backups_num
313 shares_hostID
314 shares_name
315 files_shareID
316 files_path
317 files_name
318 files_date
319 files_size
320 )) {
321 print " $index";
322 do_index($index);
323 }
324 print "...\n";
325
326 $dbh->commit;
327
328 }
329
330 ## delete data before inseting ##
331 if ($opt{d}) {
332 print "deleting ";
333 foreach my $table (qw(files dvds backups shares hosts)) {
334 print "$table ";
335 $dbh->do(qq{ DELETE FROM $table });
336 }
337 print " done...\n";
338
339 $dbh->commit;
340 }
341
342 ## insert new values ##
343
344 # get hosts
345 $hosts = $bpc->HostInfoRead();
346 my $hostID;
347 my $shareID;
348
349 my $sth;
350
351 $sth->{insert_hosts} = $dbh->prepare(qq{
352 INSERT INTO hosts (name, IP) VALUES (?,?)
353 });
354
355 $sth->{hosts_by_name} = $dbh->prepare(qq{
356 SELECT ID FROM hosts WHERE name=?
357 });
358
359 $sth->{backups_count} = $dbh->prepare(qq{
360 SELECT COUNT(*)
361 FROM backups
362 WHERE hostID=? AND num=? AND shareid=?
363 });
364
365 $sth->{insert_backups} = $dbh->prepare(qq{
366 INSERT INTO backups (hostID, num, date, type, shareid, size)
367 VALUES (?,?,?,?,?,?)
368 });
369
370 $sth->{insert_files} = $dbh->prepare(qq{
371 INSERT INTO files
372 (shareID, backupNum, name, path, date, type, size)
373 VALUES (?,?,?,?,?,?,?)
374 });
375
376 foreach my $host_key (keys %{$hosts}) {
377
378 my $hostname = $hosts->{$host_key}->{'host'} || die "can't find host for $host_key";
379
380 $sth->{hosts_by_name}->execute($hosts->{$host_key}->{'host'});
381
382 unless (($hostID) = $sth->{hosts_by_name}->fetchrow_array()) {
383 $sth->{insert_hosts}->execute(
384 $hosts->{$host_key}->{'host'},
385 $hosts->{$host_key}->{'ip'}
386 );
387
388 $hostID = $dbh->last_insert_id(undef,undef,'hosts',undef);
389 }
390
391 print "host ".$hosts->{$host_key}->{'host'}.": ";
392
393 # get backups for a host
394 my @backups = $bpc->BackupInfoRead($hostname);
395 my $incs = scalar @backups;
396 print "$incs increments\n";
397
398 my $inc_nr = 0;
399 $beenThere = {};
400
401 foreach my $backup (@backups) {
402
403 $inc_nr++;
404 last if ($opt{m} && $inc_nr > $opt{m});
405
406 my $backupNum = $backup->{'num'};
407 my @backupShares = ();
408
409 printf("%-10s %2d/%-2d #%-2d %s %5s/%5s files (date: %s dur: %s)\n",
410 $hosts->{$host_key}->{'host'},
411 $inc_nr, $incs, $backupNum,
412 $backup->{type} || '?',
413 $backup->{nFilesNew} || '?', $backup->{nFiles} || '?',
414 strftime($t_fmt,localtime($backup->{startTime})),
415 fmt_time($backup->{endTime} - $backup->{startTime})
416 );
417
418 my $files = BackupPC::View->new($bpc, $hostname, \@backups, 1);
419 foreach my $share ($files->shareList($backupNum)) {
420
421 my $t = time();
422
423 $shareID = getShareID($share, $hostID, $hostname);
424
425 $sth->{backups_count}->execute($hostID, $backupNum, $shareID);
426 my ($count) = $sth->{backups_count}->fetchrow_array();
427 # skip if allready in database!
428 next if ($count > 0);
429
430 # dump some log
431 print curr_time," ", $share;
432
433 my ($f, $nf, $d, $nd, $size) = recurseDir($bpc, $hostname, $files, $backupNum, $share, "", $shareID);
434
435 $sth->{insert_backups}->execute(
436 $hostID,
437 $backupNum,
438 $backup->{'endTime'},
439 $backup->{'type'},
440 $shareID,
441 $size,
442 );
443
444 print " commit";
445 $dbh->commit();
446
447 my $dur = (time() - $t) || 1;
448 printf(" %d/%d files %d/%d dirs %0.2f MB [%.2f/s dur: %s]\n",
449 $nf, $f, $nd, $d,
450 ($size / 1024 / 1024),
451 ( ($f+$d) / $dur ),
452 fmt_time($dur)
453 );
454
455 hest_update($hostID, $shareID, $backupNum);
456 }
457
458 }
459 }
460 undef $sth;
461 $dbh->commit();
462 $dbh->disconnect();
463
464 print "total duration: ",fmt_time(time() - $start_t),"\n";
465
466 $pidfile->remove;
467
468 sub getShareID() {
469
470 my ($share, $hostID, $hostname) = @_;
471
472 $sth->{share_id} ||= $dbh->prepare(qq{
473 SELECT ID FROM shares WHERE hostID=? AND name=?
474 });
475
476 $sth->{share_id}->execute($hostID,$share);
477
478 my ($id) = $sth->{share_id}->fetchrow_array();
479
480 return $id if (defined($id));
481
482 $sth->{insert_share} ||= $dbh->prepare(qq{
483 INSERT INTO shares
484 (hostID,name,share,localpath)
485 VALUES (?,?,?,?)
486 });
487
488 my $drop_down = $hostname . '/' . $share;
489 $drop_down =~ s#//+#/#g;
490
491 $sth->{insert_share}->execute($hostID,$share, $drop_down ,undef);
492 return $dbh->last_insert_id(undef,undef,'shares',undef);
493 }
494
495 sub found_in_db {
496
497 my @data = @_;
498 shift @data;
499
500 my ($key, $shareID,undef,$name,$path,$date,undef,$size) = @_;
501
502 return $beenThere->{$key} if (defined($beenThere->{$key}));
503
504 $sth->{file_in_db} ||= $dbh->prepare(qq{
505 SELECT 1 FROM files
506 WHERE shareID = ? and
507 path = ? and
508 date = ? and
509 size = ?
510 LIMIT 1
511 });
512
513 my @param = ($shareID,$path,$date,$size);
514 $sth->{file_in_db}->execute(@param);
515 my $rows = $sth->{file_in_db}->rows;
516 print STDERR "## found_in_db($shareID,$path,$date,$size) ",( $rows ? '+' : '-' ), join(" ",@param), "\n" if ($debug >= 3);
517
518 $beenThere->{$key}++;
519
520 $sth->{'insert_files'}->execute(@data) unless ($rows);
521 return $rows;
522 }
523
524 ####################################################
525 # recursing through filesystem structure and #
526 # and returning flattened files list #
527 ####################################################
528 sub recurseDir($$$$$$$$) {
529
530 my ($bpc, $hostname, $files, $backupNum, $share, $dir, $shareID) = @_;
531
532 print STDERR "\nrecurse($hostname,$backupNum,$share,$dir,$shareID)\n" if ($debug >= 1);
533
534 my ($nr_files, $new_files, $nr_dirs, $new_dirs, $size) = (0,0,0,0,0);
535
536 { # scope
537 my @stack;
538
539 print STDERR "# dirAttrib($backupNum, $share, $dir)\n" if ($debug >= 2);
540 my $filesInBackup = $files->dirAttrib($backupNum, $share, $dir);
541
542 # first, add all the entries in current directory
543 foreach my $path_key (keys %{$filesInBackup}) {
544 print STDERR "# file ",Dumper($filesInBackup->{$path_key}),"\n" if ($debug >= 3);
545 my @data = (
546 $shareID,
547 $backupNum,
548 $path_key,
549 $filesInBackup->{$path_key}->{'relPath'},
550 $filesInBackup->{$path_key}->{'mtime'},
551 $filesInBackup->{$path_key}->{'type'},
552 $filesInBackup->{$path_key}->{'size'}
553 );
554
555 my $key = join(" ", (
556 $shareID,
557 $dir,
558 $path_key,
559 $filesInBackup->{$path_key}->{'mtime'},
560 $filesInBackup->{$path_key}->{'size'}
561 ));
562
563 my $found;
564 if (! defined($beenThere->{$key}) && ! ($found = found_in_db($key, @data)) ) {
565 print STDERR "# key: $key [", $beenThere->{$key},"]" if ($debug >= 2);
566
567 if ($filesInBackup->{$path_key}->{'type'} == BPC_FTYPE_DIR) {
568 $new_dirs++ unless ($found);
569 print STDERR " dir\n" if ($debug >= 2);
570 } else {
571 $new_files++ unless ($found);
572 print STDERR " file\n" if ($debug >= 2);
573 }
574 $size += $filesInBackup->{$path_key}->{'size'} || 0;
575 }
576
577 if ($filesInBackup->{$path_key}->{'type'} == BPC_FTYPE_DIR) {
578 $nr_dirs++;
579
580 my $full_path = $dir . '/' . $path_key;
581 push @stack, $full_path;
582 print STDERR "### store to stack: $full_path\n" if ($debug >= 3);
583
584 # my ($f,$nf,$d,$nd) = recurseDir($bpc, $hostname, $backups, $backupNum, $share, $path_key, $shareID) unless ($beenThere->{$key});
585 #
586 # $nr_files += $f;
587 # $new_files += $nf;
588 # $nr_dirs += $d;
589 # $new_dirs += $nd;
590
591 } else {
592 $nr_files++;
593 }
594 }
595
596 print STDERR "## STACK ",join(", ", @stack),"\n" if ($debug >= 2);
597
598 while ( my $dir = shift @stack ) {
599 my ($f,$nf,$d,$nd, $s) = recurseDir($bpc, $hostname, $files, $backupNum, $share, $dir, $shareID);
600 print STDERR "# $dir f: $f nf: $nf d: $d nd: $nd\n" if ($debug >= 1);
601 $nr_files += $f;
602 $new_files += $nf;
603 $nr_dirs += $d;
604 $new_dirs += $nd;
605 $size += $s;
606 }
607 }
608
609 return ($nr_files, $new_files, $nr_dirs, $new_dirs, $size);
610 }
611

Properties

Name Value
svn:executable *

  ViewVC Help
Powered by ViewVC 1.1.26