package logscan; BEGIN {} use Tie::File; sub scan { _scan(@_, sub {lognum($b) <=> lognum($a)}, sub { local ($fname, $apply) = @_; open(LOG, $fname) or die "Can't open $fname: $!";; while () { if (not &$apply($_)) { close(LOG); return 0; } } close(LOG); return 1; }); } sub scan_backwards { _scan(@_, sub {lognum($a) <=> lognum($b)}, sub { local ($fname, $apply) = @_; # This approach is slower but requires a fixed amount of memory # indepening of the size of the log file. # 2:02, up to 16Mb (logfiles size: 64Mb ) tie(@lines, "Tie::File", $fname, mode => 0) or die "Can't tie $fname: $!"; $max_lines = $#lines; for ($i = $max_lines; $i; $i--) { if (not &$apply($lines[$i])) { return 0; } } # This approach is faster but requires at least as much available # memory as the size of the log file. # 1:02, up to 150Mb (logfiles size: 64Mb ) # open(LOG, $fname) or die "Can't open $fname: $!";; # @lines = reverse ; # foreach $line (@lines) { # chomp $line; # if (not &$apply($line)) { # close(LOG); # return 0; # } # } # close(LOG); return 1; }); } sub _scan { local ($logname, $apply, $sort, $scan_file) = @_; opendir(DIRHANDLE, ".") || die "Cannot opendir: $!"; OUTER: foreach $fname (sort $sort readdir(DIRHANDLE)) { if ($fname =~ /^$logname\.log(.[0-9]+)?$/) { print "> $fname\n"; last OUTER if (not &$scan_file($fname, $apply)); } } closedir(DIRHANDLE); } sub lognum { local $fname = shift; if ($fname =~ /\.([0-9]+)$/) { return $1; } return 0; } return 1; END {}