Re: Pausing POE::Wheel::FollowTail?

Larry Clapp <[email protected]>
Newsgroups gmane.comp.lang.perl.poe
Message-ID <[email protected]>
[ 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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.