1 #!/usr/local/bin/perl -w
5 use lib "__INSTALLDIR__/lib";
10 use Time::HiRes qw/time/;
12 use POSIX qw/strftime/;
13 use constant BPC_FTYPE_DIR => 5;
18 my $pidfile = new File::Pid;
20 if (my $pid = $pidfile->running ) {
21 die "$0 already running: $pid\n";
22 } elsif ($pidfile->pid ne $$) {
24 $pidfile = new File::Pid;
27 print STDERR "$0 using pid ",$pidfile->pid," file ",$pidfile->file,"\n";
29 my $t_fmt = '%Y-%m-%d %H:%M:%S';
32 my $bpc = BackupPC::Lib->new || die;
33 my %Conf = $bpc->Conf();
34 my $TopDir = $bpc->TopDir();
37 my $dsn = "dbi:SQLite:dbname=$TopDir/$Conf{SearchDB}";
39 my $dbh = DBI->connect($dsn, "", "", { RaiseError => 1, AutoCommit => 0 });
43 if ( !getopts("cdm:v", \%opt ) ) {
45 usage: $0 [-c|-d] [-m num]
48 -c create database on first use
49 -d delete database before import
50 -m num import just num increments for one host
55 ###################################create tables############################3
58 print "creating tables...\n";
62 ID INTEGER PRIMARY KEY,
63 name VARCHAR(30) NOT NULL,
70 ID INTEGER PRIMARY KEY,
71 hostID INTEGER NOT NULL references hosts(id),
72 name VARCHAR(30) NOT NULL,
73 share VARCHAR(200) NOT NULL,
74 localpath VARCHAR(200)
79 create table backups (
80 hostID INTEGER NOT NULL references hosts(id),
84 PRIMARY KEY(hostID, num)
90 ID INTEGER PRIMARY KEY,
92 name VARCHAR(255) NOT NULL,
99 ID INTEGER NOT NULL PRIMARY KEY,
100 shareID INTEGER NOT NULL references shares(id),
101 backupNum INTEGER NOT NULL references backups(num),
102 name VARCHAR(255) NOT NULL,
103 path VARCHAR(255) NOT NULL,
104 fullpath VARCHAR(255) NOT NULL,
105 date TIMESTAMP NOT NULL,
106 type INTEGER NOT NULL,
107 size INTEGER NOT NULL,
108 dvdid INTEGER references dvds(id)
112 print "creating indexes...\n";
114 foreach my $index (qw(
126 my ($table,$col) = split(/_/, $index);
127 $dbh->do(qq{ create index $index on $table($col) });
135 foreach my $table (qw(hosts shares files dvds backups)) {
137 $dbh->do(qq{ DELETE FROM $table });
143 print "Debug level at $opt{v}\n";
147 #################################INSERT VALUES#############################
150 $hosts = $bpc->HostInfoRead();
156 $sth->{insert_hosts} = $dbh->prepare(qq{
157 INSERT INTO hosts (name, IP) VALUES (?,?)
160 $sth->{hosts_by_name} = $dbh->prepare(qq{
161 SELECT ID FROM hosts WHERE name=?
164 $sth->{backups_broj} = $dbh->prepare(qq{
167 WHERE hostID=? AND num=?
170 $sth->{insert_backups} = $dbh->prepare(qq{
171 INSERT INTO backups (hostID, num, date, type)
175 $sth->{insert_files} = $dbh->prepare(qq{
177 (shareID, backupNum, name, path, fullpath, date, type, size)
178 VALUES (?,?,?,?,?,?,?,?)
181 foreach my $host_key (keys %{$hosts}) {
183 my $hostname = $hosts->{$host_key}->{'host'} || die "can't find host for $host_key";
185 $sth->{hosts_by_name}->execute($hosts->{$host_key}->{'host'});
187 unless (($hostID) = $sth->{hosts_by_name}->fetchrow_array()) {
188 $sth->{insert_hosts}->execute(
189 $hosts->{$host_key}->{'host'},
190 $hosts->{$host_key}->{'ip'}
193 $hostID = $dbh->func('last_insert_rowid');
196 print("host ".$hosts->{$host_key}->{'host'}.": ");
198 # get backups for a host
199 my @backups = $bpc->BackupInfoRead($hostname);
200 print scalar @backups, " increments\n";
204 foreach my $backup (@backups) {
207 last if ($opt{m} && $inc_nr > $opt{m});
209 my $backupNum = $backup->{'num'};
210 my @backupShares = ();
212 print $hosts->{$host_key}->{'host'},
214 $backup->{nFilesNew} || '?', "/", $backup->{nFiles} || '?',
217 $sth->{backups_broj}->execute($hostID, $backupNum);
218 my ($broj) = $sth->{backups_broj}->fetchrow_array();
221 my $files = BackupPC::View->new($bpc, $hostname, \@backups, 1);
222 foreach my $share ($files->shareList($backupNum)) {
226 print strftime($t_fmt,localtime())," ", $share;
227 $shareID = getShareID($share, $hostID, $hostname);
229 my ($f, $nf, $d, $nd) = recurseDir($bpc, $hostname, $files, $backupNum, $share, "", $shareID);
230 printf(" %d/%d files %d/%d dirs [%.2f/s]\n",
232 ( ($f+$d) / ((time() - $t) || 1) )
237 $sth->{insert_backups}->execute(
240 $backup->{'endTime'},
255 my ($share, $hostID, $hostname) = @_;
257 $sth->{share_id} ||= $dbh->prepare(qq{
258 SELECT ID FROM shares WHERE hostID=? AND name=?
261 $sth->{share_id}->execute($hostID,$share);
263 my ($id) = $sth->{share_id}->fetchrow_array();
265 return $id if (defined($id));
267 $sth->{insert_share} ||= $dbh->prepare(qq{
269 (hostID,name,share,localpath)
273 my $drop_down = $hostname . '/' . $share;
274 $drop_down =~ s#//+#/#g;
276 $sth->{insert_share}->execute($hostID,$share, $drop_down ,undef);
277 return $dbh->func('last_insert_rowid');
282 my ($shareID,undef,$name,$path,undef,$date,undef,$size) = @_;
284 $sth->{file_in_db} ||= $dbh->prepare(qq{
285 SELECT count(*) FROM files
286 WHERE shareID = ? and
293 my @param = ($shareID,$path,$name,$date,$size);
294 $sth->{file_in_db}->execute(@param);
295 my ($rows) = $sth->{file_in_db}->fetchrow_array();
296 # print STDERR ( $rows ? '+' : '-' ), join(" ",@param), "\n";
300 ####################################################
301 # recursing through filesystem structure and #
302 # and returning flattened files list #
303 ####################################################
304 sub recurseDir($$$$$$$$) {
306 my ($bpc, $hostname, $files, $backupNum, $share, $dir, $shareID) = @_;
308 print STDERR "recurse($hostname,$backupNum,$share,$dir,$shareID)\n" if ($debug >= 1);
310 my ($nr_files, $new_files, $nr_dirs, $new_dirs) = (0,0,0,0);
315 my $filesInBackup = $files->dirAttrib($backupNum, $share, $dir);
317 # first, add all the entries in current directory
318 foreach my $path_key (keys %{$filesInBackup}) {
323 $filesInBackup->{$path_key}->{'relPath'},
324 $filesInBackup->{$path_key}->{'fullPath'},
325 # $filesInBackup->{$path_key}->{'sharePathM'},
326 $filesInBackup->{$path_key}->{'mtime'},
327 $filesInBackup->{$path_key}->{'type'},
328 $filesInBackup->{$path_key}->{'size'}
331 my $key = join(" ", (
335 $filesInBackup->{$path_key}->{'mtime'},
336 $filesInBackup->{$path_key}->{'size'}
340 if (! $beenThere->{$key} && ! found_in_db(@data)) {
341 print STDERR "# key: $key [", $beenThere->{$key},"]" if ($debug >= 2);
342 $sth->{'insert_files'}->execute(@data);
343 if ($filesInBackup->{$path_key}->{'type'} == BPC_FTYPE_DIR) {
345 print STDERR " dir\n" if ($debug >= 2);
348 print STDERR " file\n" if ($debug >= 2);
351 $beenThere->{$key}++;
353 if ($filesInBackup->{$path_key}->{'type'} == BPC_FTYPE_DIR) {
356 my $full_path = $dir . '/' . $path_key;
357 push @stack, $full_path;
358 print STDERR "### store to stack: $full_path\n" if ($debug >= 3);
360 # my ($f,$nf,$d,$nd) = recurseDir($bpc, $hostname, $backups, $backupNum, $share, $path_key, $shareID) unless ($beenThere->{$key});
372 print STDERR "## STACK ",join(", ", @stack),"\n" if ($debug >= 2);
374 while ( my $dir = shift @stack ) {
375 my ($f,$nf,$d,$nd) = recurseDir($bpc, $hostname, $files, $backupNum, $share, $dir, $shareID);
376 print STDERR "# $dir f: $f nf: $nf d: $d nd: $nd\n" if ($debug >= 1);
384 return ($nr_files, $new_files, $nr_dirs, $new_dirs);