/[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 66 - (show annotations)
Mon Aug 22 00:09:59 2005 UTC (18 years, 9 months ago) by dpavlin
File size: 10241 byte(s)
calculate size for each backup (this is more accurate than reading meta data
if you aren't staring from clean BackupPC installation).

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

Properties

Name Value
svn:executable *

  ViewVC Help
Powered by ViewVC 1.1.26