1 #!/usr/local/bin/perl -w
5 use lib "__INSTALLDIR__/lib";
10 use Time::HiRes qw/time/;
11 use POSIX qw/strftime/;
12 use constant BPC_FTYPE_DIR => 5;
17 my $t_fmt = '%Y-%m-%d %H:%M:%S';
20 my $bpc = BackupPC::Lib->new || die;
21 my %Conf = $bpc->Conf();
22 my $TopDir = $bpc->TopDir();
25 my $dsn = "dbi:SQLite:dbname=$TopDir/$Conf{SearchDB}";
27 my $dbh = DBI->connect($dsn, "", "", { RaiseError => 1, AutoCommit => 0 });
31 if ( !getopts("cdm:v", \%opt ) ) {
33 usage: $0 [-c|-d] [-m num]
36 -c create database on first use
37 -d delete database before import
38 -m num import just num increments for one host
43 ###################################create tables############################3
46 print "creating tables...\n";
50 ID INTEGER PRIMARY KEY,
51 name VARCHAR(30) NOT NULL,
58 ID INTEGER PRIMARY KEY,
59 hostID INTEGER NOT NULL references hosts(id),
60 name VARCHAR(30) NOT NULL,
61 share VARCHAR(200) NOT NULL,
62 localpath VARCHAR(200)
67 create table backups (
68 hostID INTEGER NOT NULL references hosts(id),
72 PRIMARY KEY(hostID, num)
78 ID INTEGER PRIMARY KEY,
80 name VARCHAR(255) NOT NULL,
87 ID INTEGER NOT NULL PRIMARY KEY,
88 shareID INTEGER NOT NULL references shares(id),
89 backupNum INTEGER NOT NULL references backups(num),
90 name VARCHAR(255) NOT NULL,
91 path VARCHAR(255) NOT NULL,
92 fullpath VARCHAR(255) NOT NULL,
93 date TIMESTAMP NOT NULL,
94 type INTEGER NOT NULL,
95 size INTEGER NOT NULL,
96 dvdid INTEGER references dvds(id)
100 print "creating indexes...\n";
102 foreach my $index (qw(
114 my ($table,$col) = split(/_/, $index);
115 $dbh->do(qq{ create index $index on $table($col) });
123 foreach my $table (qw(hosts shares files dvds backups)) {
125 $dbh->do(qq{ DELETE FROM $table });
131 print "Debug level at $opt{v}\n";
135 #################################INSERT VALUES#############################
138 $hosts = $bpc->HostInfoRead();
144 $sth->{insert_hosts} = $dbh->prepare(qq{
145 INSERT INTO hosts (name, IP) VALUES (?,?)
148 $sth->{hosts_by_name} = $dbh->prepare(qq{
149 SELECT ID FROM hosts WHERE name=?
152 $sth->{backups_broj} = $dbh->prepare(qq{
155 WHERE hostID=? AND num=?
158 $sth->{insert_backups} = $dbh->prepare(qq{
159 INSERT INTO backups (hostID, num, date, type)
163 $sth->{insert_files} = $dbh->prepare(qq{
165 (shareID, backupNum, name, path, fullpath, date, type, size)
166 VALUES (?,?,?,?,?,?,?,?)
169 foreach my $host_key (keys %{$hosts}) {
171 my $hostname = $hosts->{$host_key}->{'host'} || die "can't find host for $host_key";
173 $sth->{hosts_by_name}->execute($hosts->{$host_key}->{'host'});
175 unless (($hostID) = $sth->{hosts_by_name}->fetchrow_array()) {
176 $sth->{insert_hosts}->execute(
177 $hosts->{$host_key}->{'host'},
178 $hosts->{$host_key}->{'ip'}
181 $hostID = $dbh->func('last_insert_rowid');
184 print("host ".$hosts->{$host_key}->{'host'}.": ");
186 # get backups for a host
187 my @backups = $bpc->BackupInfoRead($hostname);
188 print scalar @backups, " increments\n";
192 foreach my $backup (@backups) {
194 last if ($opt{m} && $inc_nr > $opt{m});
196 my $backupNum = $backup->{'num'};
197 my @backupShares = ();
199 print $hosts->{$host_key}->{'host'}, "\t#$backupNum\n";
201 $sth->{backups_broj}->execute($hostID, $backupNum);
202 my ($broj) = $sth->{backups_broj}->fetchrow_array();
205 my $files = BackupPC::View->new($bpc, $hostname, \@backups, 1);
206 foreach my $share ($files->shareList($backupNum)) {
210 print strftime($t_fmt,localtime())," ", $share;
211 $shareID = getShareID($share, $hostID, $hostname);
213 my ($f, $nf, $d, $nd) = recurseDir($bpc, $hostname, $files, $backupNum, $share, "", $shareID);
214 printf(" %d/%d files %d/%d dirs [%.2f/s]\n",
216 ( ($f+$d) / ((time() - $t) || 1) )
221 $sth->{insert_backups}->execute(
224 $backup->{'endTime'},
237 my ($share, $hostID, $hostname) = @_;
239 $sth->{share_id} ||= $dbh->prepare(qq{
240 SELECT ID FROM shares WHERE hostID=? AND name=?
243 $sth->{share_id}->execute($hostID,$share);
245 my ($id) = $sth->{share_id}->fetchrow_array();
247 return $id if (defined($id));
249 $sth->{insert_share} ||= $dbh->prepare(qq{
251 (hostID,name,share,localpath)
255 my $drop_down = $hostname . '/' . $share;
256 $drop_down =~ s#//+#/#g;
258 $sth->{insert_share}->execute($hostID,$share, $drop_down ,undef);
259 return $dbh->func('last_insert_rowid');
264 my ($shareID,undef,$name,$path,undef,$date,undef,$size) = @_;
266 $sth->{file_in_db} ||= $dbh->prepare(qq{
267 SELECT count(*) FROM files
268 WHERE shareID = ? and
275 my @param = ($shareID,$path,$name,$date,$size);
276 $sth->{file_in_db}->execute(@param);
277 my ($rows) = $sth->{file_in_db}->fetchrow_array();
278 # print STDERR ( $rows ? '+' : '-' ), join(" ",@param), "\n";
282 ####################################################
283 # recursing through filesystem structure and #
284 # and returning flattened files list #
285 ####################################################
286 sub recurseDir($$$$$$$$) {
288 my ($bpc, $hostname, $files, $backupNum, $share, $dir, $shareID) = @_;
290 print STDERR "recurse($hostname,$backupNum,$share,$dir,$shareID)\n" if ($debug >= 1);
292 my ($nr_files, $new_files, $nr_dirs, $new_dirs) = (0,0,0,0);
297 my $filesInBackup = $files->dirAttrib($backupNum, $share, $dir);
299 # first, add all the entries in current directory
300 foreach my $path_key (keys %{$filesInBackup}) {
305 $filesInBackup->{$path_key}->{'relPath'},
306 $filesInBackup->{$path_key}->{'fullPath'},
307 # $filesInBackup->{$path_key}->{'sharePathM'},
308 $filesInBackup->{$path_key}->{'mtime'},
309 $filesInBackup->{$path_key}->{'type'},
310 $filesInBackup->{$path_key}->{'size'}
313 my $key = join(" ", (
317 $filesInBackup->{$path_key}->{'mtime'},
318 $filesInBackup->{$path_key}->{'size'}
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) {
327 print STDERR " dir\n" if ($debug >= 2);
330 print STDERR " file\n" if ($debug >= 2);
333 $beenThere->{$key}++;
335 if ($filesInBackup->{$path_key}->{'type'} == BPC_FTYPE_DIR) {
338 my $full_path = $dir . '/' . $path_key;
339 push @stack, $full_path;
340 print STDERR "### store to stack: $full_path\n" if ($debug >= 3);
342 # my ($f,$nf,$d,$nd) = recurseDir($bpc, $hostname, $backups, $backupNum, $share, $path_key, $shareID) unless ($beenThere->{$key});
354 print STDERR "## STACK ",join(", ", @stack),"\n" if ($debug >= 2);
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);
366 return ($nr_files, $new_files, $nr_dirs, $new_dirs);