2010-06-07 60 views
2

我正在尋找很好的perl實現。我遇到的情況是這樣的:我需要跟蹤許多文件的I/O活動,並且對於存在足夠時間的文件保持不動,將會對其執行刪除操作,因此高效的定時器實現對於應用程序 非常重要我現在參與其中。爲了避免重新創建輪子,請首先詢問你們的幫助。Perl中是否有很好的定時器實現?

+1

這是* nix? – Zaid 2010-06-07 08:21:16

+0

@Zaid:是的,* nix – 2010-06-07 08:28:41

+0

你有什麼理由不得不使用Perl?我認爲* nix命令應該足夠了。必要時與反引號集成。 – Zaid 2010-06-07 09:19:15

回答

6

Time::HiRes自帶perl。另外,你的應用程序聽起來好像可以從Linux::Inotify(注意Linux :: in front)中受益。爲某個文件設置定時器時,如果要在某段時間不活動後刪除該文件,請記住上次訪問。在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作爲文件描述符的非阻塞讀取。自the author is no longer interested以來,任何人都可以接管模塊的維護。

+0

有Linux :: Inotify2,它指出「它比Linux :: Inotify模塊具有許多優點:」 – 2010-06-07 21:20:13

+0

Adam:確實,我錯過了這一點。對我感到羞恥。另外,Marc Lehmann模塊(如Linux :: Inotify2)通常具有很高的質量! – tsee 2010-06-08 08:00:20

+1

['File :: ChangeNotify'跨平臺工作](http://stackoverflow.com/questions/1776745#1778606);也使用'Linux :: Inotify2'。 – daxim 2010-06-21 13:57:47

3

您的程序似乎清晰地事件驅動,您將受益於使用事件驅動的框架(如POE或AnyEvent)來實現它。這些都可以處理I/O事件和計時器事件。

相關問題