Pausing anything that tails a file is problematic. What happens if the user goes away for lunch, a weekend, or vacation, and the log file rolls over more than once before they return?

A reliable solution would be to not pause. Rather, the wheel or application would buffer changes until output is resumed. Buffered data would need to be spooled to disk to avoid memory limits. And then there's the chance of running out of disk if the user's gone for a few weeks.

A compromise might be to provide a certain amount of scrollback, and let the user browse around until their data scrolls away. While the Tk text window is focused on historical information, it will track that position as it continues to scroll. The user would be forced to resume scrolling when their historical place reaches the end of the scrollback buffer.

The most reliable solution would be to stop whatever generates log output until the user is ready to resume. For example, pause could run system("apachectl stop"), and resume could run system("apachectl start"). That way you can be fairly certain the file won't change while the viewer isn't looking. :)

--
Rocco Caputo - [EMAIL PROTECTED]


On Oct 6, 2008, at 19:10, Larry Clapp wrote:

[ Top posting corrected ]

On Mon, Oct 06, 2008 at 04:24:40PM -0500, Votava, Craig M (Craig) wrote:
On Mon, Oct 06, 2008 at 10:11:42AM -0500, Votava, Craig M (Craig) wrote:
I wrote a simple perl application that uses
POE::Wheel::FollowTail to get entries out of a logfile, and puts
them up in a Tk Text window.

I want to add a pause/resume toggle button at the bottom of the
Text window, so that the user can stop and start the incoming
data whenever they want. When the input is paused, I would like
to have minimal impact on the CPU. If the pause lasts long
enough to where the file is reset, then the user would get the
data starting at the beginning of the current file once they
unpause. What is the best way to do this?

I wonder if it would make sense to add a pause method to this
module? If the general consensus is yes, I can volunteer to take
a stab at it. If there is a better/easier/faster way to do it
with the existing methods, please let me know.

I am new to POE, but it seems to me you could either

 - use tell() to get the current position
 - destroy the wheel
 - recreate it when you're ready and set the Seek to the previous
   position

 (There's actually an example of this in the
 POE::Wheel::FollowTail manpage under tell().)

or

 - Alter (or subclass) FollowTail so that you can change the
   PollInterval dynamically.

Neither would be very hard.

Thanks for the response! Either of your solutions could be best,
but I'm not sure about a couple of things:

1.) Say I save the current state then destroy the wheel. When I
start up a new wheel, how do I know whether to use the saved data
to index back to where I left off or (if the file has been reset)
to just start from the beginning?

That's a good question, and not one I thought of.  :)

I could think of a couple of strategies (check the inode?), but mostly
I think you'd want to dig into the wheel and either do what it does,
or figure out how to get it to *track* the file without actually
reading the data and sending it to you.

I guess if you go with that strategy, you really would need "pause"
functionality, as you initially started out asking for.

2.) If I change PollInterval, what value would I change it to, so
that it would never fire?

I'd probably go with 32e6 seconds, which is just over a year.  Or
there's always 2**32, which is ~136 years.

But as mentioned above, you probably really do want a "pause"
function.  Also, if you fake a "pause" by setting a long interval, as
I initially suggested, I realize now that a) you'd obviously need some
way to get the ball rolling again, and b) those year-later events
would hang around in the queue, and who wants that?

So I guess I'd recommend:

- dig into the wheel; add a flag that tells the read code to skip the
 actual "read the file" part of what it does, but it continues the
 polling at the normal cycle.
- add methods to the wheel to allow you to set or reset the flag

The wheel has a _define_timer_states function that defines how it
deals with files (as opposed to sockets, which is
_define_select_states).  That function looks kind of like this:

   sub _define_timer_states {
     # ... stuff ...
     $poe_kernel->state(
          $$state_read,
          sub {
            # check the inode, read the file, etc
          } );

     $poe_kernel->delay($$state_read, 0);
   }

I guess I'd try something vaguely similar to:

   my $running = 1;

   sub pause {
     $running = 0;
   }

   sub unpause {
     $running = 1;
   }

   sub _define_timer_states {
     # ... stuff ...
     $poe_kernel->state(
          $$state_read,
          sub {
            if (!$running) {
# ... requeue the $$state_read event for $interval seconds from now ...
              return;
            }

            # check the inode, read the file, etc
          } );

     $poe_kernel->delay($$state_read, 0);
   }

... except you'd put the $running flag into the wheel object, of
course, otherwise you've paused *all* the wheels in the system!  :)

This is obviously untested and may make demons fly out your nose.  But
I hope it helped anyway.  :)

-- Larry


Reply via email to