in reply to Adding flexibility to Watching_Logs example in POE Cookbook

There may be other ways, here is mine (unified diff, you need to patch your program):

--- 504441.pl 2005-11-01 10:19:54.000000000 +0200 +++ 504441.pl-new 2005-11-01 10:19:36.000000000 +0200 @@ -64,11 +64,25 @@ # Handle log resets and errors the same way for each file.^M log_reset => \&generic_log_reset,^M log_error => \&generic_log_error,^M + alarm_reset => \&alarm_reset,^M }^M );^M ^M +sub alarm_reset{^M + print "ALARM!\n";^M + my ($kernel, $heap) = @_[KERNEL, HEAP];^M + if ( exists( $heap->{'alarm'} ) ){^M + delete $heap->{'services'};^M + delete $heap->{'watchers'};^M + $kernel->delay_add( "alarm_reset", 10 );^M + $kernel->yield('_start');^M + }else{^M + $kernel->delay( "alarm_reset", 10 );^M + }^M +}^M +^M sub begin_watchers {^M - my $heap = $_[HEAP];^M + my ($kernel, $heap) = @_[KERNEL, HEAP];^M ^M while ( my ( $service, $log_file ) = each %logs_to_watch ) {^M my $log_watcher = POE::Wheel::FollowTail->new^M @@ -81,6 +95,7 @@ $heap->{services}->{ $log_watcher->ID } = $service;^M $heap->{watchers}->{ $log_watcher->ID } = $log_watcher;^M }^M + $kernel->yield('alarm_reset');^M }^M ^M # Handle log resets the same way for each file. Simply recognize tha +t^M @@ -171,6 +186,8 @@ __DATA__^M # fullpath filter^M # ------------------------ ---------^M +/var/log/everything/current msg^M +/var/log/mail/current mail^M /var/log/cron cron^M /var/log/maillog mail^M /var/log/ppp.log ppp^M

Basically you need to receive an event when config file changes. You can setup an alarm to check this periodically, or any other means to be immediately notified.

Then, re-read your configuration file (you need to get rid of _DATA_ and use a procedure that returns you the hash), get the new files, delete your old FollowTail wheels, and create brand-new ones using begin_watchers.

I get advantage of the fact that you use %logs_to_watch like a "global", but I'd advise you to store all your "globals" to the HEAP.

Oh and a final note: the program doesn't change the log files, just shows you how to renew your wheels. And it isn't tested ;-)

Dodge This!

Replies are listed 'Best First'.
Re^2: Adding flexibility to Watching_Logs example in POE Cookbook
by shockers (Acolyte) on Nov 02, 2005 at 06:07 UTC
    Thanks. Your advice helped some. I put the stuff in __DATA__ to a file called "watchlist". I put the code to read the watchlist into a subroutine. When the program starts or I detect the watchlist changed, I call the subroutine to read the watchlist. The method I used to detect a change to the watchlist was to add "configfile.log" into the watchlist. When I append date/time to "configfile.log", it calls the routine to read the watchlist.

    In your code, I see how you delete the heap's 'services' and 'watchers' in alarm_reset. Should I call that in my routine that re-reads the watchlist? When the attached code runs, alarm_reset gets run every 10 seconds, so it seems the 'services' and 'watchers' are not getting cleared out.

    I confirmed I can reread the watchlist, but it seems to me that for the "new" watchlist to take effect (wiping out any prior watchlist entries that are no longer in the new watchlist), I feel the original $poe_kernel->run() should somehow be stopped, the original POE::Session->create needs to be destroyed, another POE::Session->create should be run, and then a new $poe_kernel->run() be started.

    Is this a false assumption? Or is your alarm_reset deleting entries in the heap and I should somehow dynamically enter replacement entries without stopping the poe_kernel and re-creating the poe session?

      Interesting approach, tailing configfile.log

      The example with the alarm was just an example trigger, to show you how you can re-read the configuration. You can get rid of it now, as you have a trigger (configfile.log)

      Say you have four files to watch, namely file A, ... file D. You create for each one of them a Wheel, that you store in $_HEAP->{'watchers'}. I'd suggest you keep the wheels like: $_HEAP->{'watchers'}->{'A'} .. $_HEAP->{'watchers'}->{'D'} etc.

      This way, when you send the event that the configuration file has changed, a subroutine checks the new file names to tail. Say you need to watch now file A, file B, file E and file Z. The subroutine will keep the wheels stored in $_[HEAP]->{'watchers'}->{'A'} and $_[HEAP]->{'watchers'}->{'B'}, deletes the wheels watching files C and D, and creates new wheels for files E and Z

      The whole point is that you are keeping the Wheels alive, by having a reference to them in the $_[HEAP]. As soon as you delete a reference to one wheel from $_[HEAP], $poe_kernel will do the clean-up for you (in case there are no more events for it to be delivered or there is no other reference to them).

      There are other methods too to keep sessions alive, Here's another example

      In short, you don't need to restart the $poe_kernel. It's main purpose is to live forever ;-) But you may "restart" wheels by deleting, recreating them as needed.

      Dodge This!