#!/usr/bin/perl use strict; use warnings; use DBI; use File::Find; use Data::Dumper; # Connect to DB my $dbh = connect_db("ofrs","localhost","ofrs","ofrs"); # Set time before import my $stime = time; # Sync a replication folder on the disk with the database checkFS($dbh,"/data/test1"); # Set time after import my $etime = time; my $endtime = ($etime - $stime); # Print needed time print "Needed $endtime seconds ...\n"; $dbh->disconnect(); ######################################################################## sub connect_db { my ($db,$host,$user,$pass)=@_; return DBI->connect( "DBI:mysql:$db:$host", $user, $pass, { RaiseError => 1, AutoCommit => 0 } ) or die($DBI::errstr); } # sync a replication folder on the disk with the database # Syntax: checkFS($repPath) # Return value: none sub checkFS { # Set & define variables my ($dbh, $base_path) = @_; # create the hash-tree for this path / replication folder my $fs_tree = makeFSTree($base_path); # insert missing files in the DB syncDBwithFS($dbh,$fs_tree,$base_path); # Create Tree from the DB my $db_tree = makeDBTree($dbh, $base_path); # compare FS and DB Trees my $diff_tree=compareTrees($db_tree,$fs_tree); # build the pathes from the hashes left in the hash-tree my $onlyDB = buildPathes($diff_tree); # print the pathes out print "OnlyDB-Pathes:\n"; print Dumper($onlyDB); } # Creates a hash tree for a replication folder using the pathes in the database # Syntax: makeDBTree($dbh, $repFolder) # Return Value: hash-tree (hash) sub makeDBTree { # Set & define the variables my ($dbh,$base_path)=@_; my $tree={}; # Run query my $sth = $dbh->prepare('SELECT path FROM dir WHERE path LIKE "?"'); $sth->execute($base_path.'%'); # Use the query results ... while (my @result = $sth->fetchrow_array) { # ... and add each path to the hash-tree addToTree($tree, $result[0], 'X'); } $sth->finish(); # return the hash-tree return $tree; } # Syntax: makeFSTree($repFolder) # Return Value: hash-tree (hash) sub makeFSTree { my $tree={}; find(sub{ return if($_=~/^\.{1,2}$/); my $path=$File::Find::name; my $end='X'; $end={} if(-d $path); addToTree($tree, $path, $end); }, @_); return $tree; } # insert missing files in the DB # Syntax: syncDBwithFS($dbh,$tree,$repFolder) # Return Value: none sub syncDBwithFS { my ($dbh,$fs_tree,$base_path)=@_; my $sth=$dbh->prepare('INSERT IGNORE INTO dir (path) VALUES ("?")'); __syncDBwithFS($sth,$fs_tree,$base_path); $sth->finish(); } # private ... sub __syncDBwithFS { my ($sth,$fs_tree,$base_path)=@_; while(my ($key,$val)=each(%$fs_tree)) { my $path="$base_path/$key"; if($val && ref($val) eq 'HASH') { __syncDBwithFS($sth,$val,$path); } else { $sth->execute($path); } } } # add a Path to the hash-tree # Syntax: addToTree($tree,$path) # Return value: none sub addToTree { # Set & define the variables my ($tree,$path,$end) = @_; # Split the path up to its parts my @parts = split('/',$path); # Delete the first (empty) part shift @parts; # Delete the trailing slash at the end of the path if exists my $file=1; unless($parts[-1]) { $file=0; pop(@parts); } # build the hash-tree for this path my $ref=\$tree; $ref=\$$ref->{$_} for(@parts); $$ref=$end; } # compare two trees # returns a tree of missing elemnts in second tree # Syntax: addToTree($tree,$tree) # Return value: $tree sub compareTrees { my ($tree_a,$tree_b)=@_; my $tree_diff={}; while(my ($key,$val)=each(%$tree_a)) { if(exists($tree_b->{$key})) { if(ref($tree_b->{$key}) eq 'HASH') { my $ret=compareTrees($val,$tree_b->{$key}); $tree_diff->{$key}=$ret if($ret && keys(%$ret)); } } else { $tree_diff->{$key}=$val; } } return $tree_diff; } # build the pathes from the hash-tree # Syntax: buildPathes($tree) # Return value: path-list (array-reference) sub buildPathes { # Set & define variables my $tree=shift; my $path=shift // ''; my @list; # walk through all levels and sort them for my $name (sort(keys(%$tree))) { my $elm=$tree->{$name}; if($elm && ref($elm) eq 'HASH') { # run the function recursive my $lst=buildPathes($elm,"$path/$name"); push(@list,@$lst); } else { push(@list,"$path/$name"); } } # return the list of pathes from the hash-tree return \@list; }