Time :: HiRes поставляется с perl.
Более того, ваше приложение звучит так, как будто оно может извлечь пользу из Linux :: Inotify (обратите внимание на Linux :: inфронт).При настройке таймера для файла, который вы хотите удалить после определенного времени бездействия, запомните последний доступ.В ловушке события inotify обновите это время до текущего времени.Затем вы можете периодически проверять, истек ли срок жизни файла, не делая статистики для всех файлов, которые вы отслеживаете.По истечении срока вы можете добавить окончательную проверку, чтобы убедиться, что ничего не пошло не так, конечно.
Если у вас есть огромное количество файлов в полете, вы можете сохранить список файлов, отсортированных по времени истечения.Это делает периодическую проверку истечения срока действия тривиальной.
Обновление: я только что немного поэкспериментировал с Linux :: Inotify.С таким подходом все не так просто, как я думал.Во-первых, вот частично работающий код, который я не успел завершить.
#!/usr/bin/env perl
use strict;
use warnings;
use List::Util qw/min max/;
use Time::HiRes qw/time sleep/;
use Data::Dumper;
use Linux::Inotify;
# [s], but handles subsecond granularity, too
use constant CLEANUP_INTERVAL => 1.;
use constant FILE_ACCESS_TIMEOUT => 5.;
# for fast and readable struct access
use constant FILENAME => 0;
use constant ACCESSTIME => 1;
use constant WATCHER => 2;
my $notifier = Linux::Inotify->new;
my @tracked_files = populate_tracked_files(\@ARGV, $notifier);
warn Dumper \@tracked_files;
while (1) {
# update the tracked files according to inotify events
my @events = $notifier->read;
my %files_seen_this_round;
foreach my $event (@events) {
$event->print();
my $ev_filename = $event->{name}; # part of the API, apparently
# we mave have multiple events per file.
next if $files_seen_this_round{$ev_filename}++;
# find and update the right tracked file
# TODO: this could be optimized to O(1) with a hash at
# the cost of more bookkeeping
foreach my $tfile (@tracked_files) {
if ($tfile->[FILENAME] eq $ev_filename) {
my $atime = $^T + 60*60*24 * -A $ev_filename; # update access time
$tfile->[ACCESSTIME] = $atime;
# a partial bubble sort would be hugely more efficient here!
# => O(n) from O(n*log(n))
@tracked_files = sort {$a->[ACCESSTIME] <=> $b->[ACCESSTIME]}
@tracked_files;
last;
}
} # end foreach tracked file
} # end foreach event
cleanup_files(\@tracked_files);
sleep(CLEANUP_INTERVAL);
last if not @tracked_files;
} # end while(1)
$notifier->close;
sub cleanup_files {
my $files = shift;
my $now = time();
for (my $fileno = 0; $fileno < $#{$files}; ++$fileno) {
my $file = $files->[$fileno];
if ($now - $file->[ACCESSTIME] > FILE_ACCESS_TIMEOUT) {
warn "File '" . $file->[FILENAME] . "' timed out";
# remove this file from the watch list
# (and delete in your scenario)
$file->[WATCHER]->remove;
splice @$files, $fileno, 1;
$fileno--;
}
}
}
sub populate_tracked_files {
my $files = shift;
my $notifier = shift;
my @tracked_files;
foreach my $file (@$files) {
die "Not a file: '$file'" if not -f $file;
my $watch = $notifier->add_watch($file, Linux::Inotify::ALL_EVENTS);
push @tracked_files, [$file, $^T + 60*60*24*-A $file, $watch];
}
@tracked_files = sort {$a->[ACCESSTIME] <=> $b->[ACCESSTIME]}
@tracked_files;
return @tracked_files;
}
В логике проверки времени все еще есть какая-то ошибка.Но главная проблема в том, что $notifier->read()
будет блокироваться до нового события.Принимая во внимание, что мы действительно просто хотим увидеть, есть ли новое событие, а затем приступить к очистке.Это должно быть добавлено в Linux :: Inotify как неблокирующее чтение дескриптора файла.Любой может взять на себя обслуживание модуля, так как автор больше не заинтересован .