$r->finfo()

geoff on 2003-11-25T15:09:35

until recently, $r->finfo() was missing from the mod_perl 2.0 API. while it had been on my list of things to do for a while, I finally managed to get around to it during ApacheCon.



$r->finfo() was a pretty cool, but little used feature in mod_perl 1.0. basically, when Apache ran the translation phase and determined the real file corresponding to the URI ($r->filename), it would stat the file and stuff that data into the finfo slot in the request_rec. mod_perl added some sugar, which allowed for some pretty interesting things, like

if (-r $r->finfo && -s _) {
  ...
}


behind the scenes, the call to finfo() populated the special filehandle _ with data from Apache's finfo struct and returns it, giving you two speedups: first using Apache's cache (finfo) then perl's cache (_), in both cases avoiding a direct stat to the file on disk (save the first one, that is). all in all, much more efficient than stat $r->filename. (oh, and take the time to look up _ if you don't know what it does - it's pretty cool)



well, in Apache 2.0 the finfo slot in the request_rec doesn't translate directly into the same thing perl stores in _, so the above trickery won't work anymore in mod_perl 2.0. here's how it looks now:
use APR::Finfo ();

use APR::Const -compile => qw(UREAD);

my $finfo = $r->finfo;

if ($finfo->protection & APR::UREAD && $finfo->size) { ... }


the thing to note is that now $r->finfo() returns an APR::Finfo object, through which file attributes are accessed. also note that the permissions are determined using APR specific constants, not the typical Fcntl ones (though I haven't actually checked to see if they are the same).



while it's not nearly as svelte as they way it was in mod_perl 1.0, at least now it's possible to use Apache's cache and avoid multiple stat calls to the filesystem. I suppose you could also do

stat $r->filename;

if (-r _ && -s _) { ... }


but with the new APR::Finfo stuff you can avoid that initial trip back to disk.


Faster?

Matts on 2003-11-26T09:00:30

It would be interesting to know if this is actually faster than a stat call. Is the perl method call overhead actually going to eat away at the time it might take to just do the stat in perl anyway?

Re:Faster?

geoff on 2003-11-26T13:34:38

when I was implementing it I said to myself, "well, there is the overhead of the method call, but that has to be faster than going to disk." my gut tells me it's true, but I have no real evidence.



I suspect that what really makes the difference is not having _ automatically populated when you need to make multiple stat calls - in that case, you might be better off using perl's stat on $r->filename and the special filehandle. I really don't know.



but at least now people have different approaches they can benchmark, where they didn't before :)