On Wed, 2002-07-31 at 22:50, James F.Hranicky wrote:
> On Wed, 31 Jul 2002 21:02:04 +0900
> Florian Frank <flori / eavesdrop.ping.de> wrote:
> 
> > I could try to document a little more in the best english I'm capable
> > of. That is, it will probably be quite awful. ;)
> 
> A couple of suggestions:
> 
> 	- Check for rotation by checking for changes in the inode number

Good idea. This should handle the rotation-by-moving case much faster.
I have implemented this. 

BTW: If the filesize suddenly shrinks, copy and truncate could have
happened. I'm not sure what has to be done in this case. Rewinding to
the top of the file would perhaps be reasonable, because it doesn't make
much sense for a logfile to be truncated to any other filesize but 0. 

> 	- Allow tailing from arbitrary points in the file by lines, e.g
> 
> 		log.wind(10)    # skip 10 lines from the beginning, print
> 				# the rest of the file, then tail -f
> 		log.rewind(-10) # print last 10 lines, then tail -f

In my implementation the latter is done by log.last(10).

> Something like this:
> 
>     def wind(lines)
> 
>         seek(0, IO::SEEK_SET)
> 
>         numlines = 0
>         0.upto(stat.size) { |filepos|
>             seek(filepos, IO::SEEK_SET)
>             return if (numlines == lines)
>             i = getc
>             c = sprintf("%c", i)
>             numlines += 1 if (c == "\n")
>         }
> 
>     end

Maybe I am missing somtehing, but couldn't this be done much simpler
like this:

def wind(lines)

	@fileh.seek(0, IO::SEEK_SET) # just to be sure

	until @fileh.eof? or lines <= 0
		@fileh.readline
		lines -= 1
	end
end

>     def rewind(lines)
> 
>         seek(0, IO::SEEK_END)
> 
>         lines = lines.abs
>         numlines = 0
>         size = stat.size - 1
> 
>         size.downto(0) { |filepos|
>             next if (size == filepos)
>             seek(filepos, IO::SEEK_SET)
>             i = getc
>             c = sprintf("%c", i)
>             numlines += 1 if (c == "\n")
>             return if (numlines == lines)
>         }
>     end

My approach is much more complicated because I use a buffer of an
arbitrary size, to spare some seek-calls and to have fewer
explicit iterations. Perhaps it doesn't make much of a difference and I
could use this simpler method. I should probably benchmark both methods
to find this out.