[Melbourne-pm] IO::File with Capture for Quota

Scott Penrose scottp at dd.com.au
Wed Oct 15 21:04:57 PDT 2008


Howdy Paul.

----- "Paul Fenwick" <pjf at perltraining.com.au> wrote:
> G'day Scott,
> 
> Scott Penrose wrote:
> 
> > 1) Is there anyway of getting from a file handle:
> >     - That it is a file on disk, rather than Socket or Pipe
> 
> I imagine yes.  The stat() call returns the device number, inode
> number, and
> file mode.  For a network socket, I imagine the device and inode
> number will
> be set to funny values.  For a named pipe on the disk, I imagine the
> file
> mode will contain a hint.
> 
> >     - The filename of that file
> 
> As far as I know, no, at least not on Unix-flavoured systems.  After
> the
> file has been opened, the file can be renamed, or even deleted.  In
> fact,
> after you've opened it, you can't even rely upon a file of the same
> name
> referring to the same file; for example, when the file gets rotated
> and a
> new file dropped in its place.
> 
> Luckily, the stat() call will give you both size and inode number.  If
> the
> inode number has changed, you know that the file have been
> roated/moved/deleted/etc.  Of course, if you're passing filehandles to
> stat,
> you'll always be examining the correct file, even if the name has
> changed.

Hmm... I could get the size from the inode, assuming of course unix. I also found a hack where you can go to /proc/$$/fh/$fid to get the filename, but again linux only.

But if the reference count is 0 on the inode (e.g. temp file) it would be wrong.

Two ways I can think of at the moment to get around the problem.

1) Require a special call to IO::File (by special, that could just be the 3 parameter entries)
2) Regular expression over the input string (ahhhhhh)

> > 2) What else would you change - in functions, calls and purpose to
> make
> > this a useful CPAN module
> 
> I don't like the idea of a global callback, I'm much fonder of having
> per-object callbacks:
> 
> 	IO::File::Quota->new('>> /tmp/example', \&callback);

Yes I agree - not only does the above fix problems like threading it means you can have multiple callbacks depending on file open etc.

So I think combining 1&2 above I could do:

 my $fh = IO::File::Quota->new('/tmp/example', 'w+', \&callback); - or similar

Although therefore the open command is different, it means the rest of your code is just a file handle.

But one question - I think I have to use a hash (what ever method, inside out objects etc) as the $fh is just that - a file handle, so I can't store it in there. Which means of course that it is not thread safe - maybe that doesn't matter.

> If something doesn't have a callback (or even if it does), I'd change
> the
> returns of close to return the change in size in bytes, or "0 but
> true" or
> some equivalent value if the close was successful, but the file
> didn't
> change in length.  That allows for code like:
> 
> 	my $fh = IO::File::Quote->new('>> /tmp/example');
> 
> 	while (<STDIN>) {
> 		$fh->print($_);
> 	}
> 
> 	my $bytes_read = $fh->close or die "Uh oh!  $!";
> 
> I'd also add a '->count' method, so I can tell how many bytes have
> been
> added (or removed) to the file so far.  This can just be syntactic
> sugar for
> flushing the file and counting its size.
> 
> I'd also change the name.  If we're not trying to enforce a quota, we
> just
> want a change in size, then I'd consider IO::File::SizeDelta or
> similar as a
> name.

Yes I like that name.
 
> > 3) Is there already something like this you know of?
> 
> Nope, but I haven't looked.  I usually ask modules at perl.org such
> things.

I will finish off the working module now, but the question will remain open for a while if I should publish it - it may be too much of a local hack that would add confusion in the real world.

Thanks everyone

Scott


More information about the Melbourne-pm mailing list