[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