Re[2]: each considered harmful?

2003-06-16 Thread Mike P. Mikhailov
Hello Marcin Kasperski,

Tuesday, June 17, 2003, 3:13:23 AM, you wrote:

>> > sub handler {
>> 
>> > my $r = shift;
>> > my $uri = $r->uri;
>> > ... detecting dynamic handlers ...
>> > while( my($url, $dirs) = each %STATIC_FILES ) {
>> > if( $uri =~ m{$url/(.*)$} ) {
>> > foreach my $d (@$dirs) {
>> > my $file = "$d/$1";
>> > if( -f $file ) {
>> >$r->filename($file);
>> >return OK;
>> > }
>> > }
>> > }
>> > }
>> > }
>> 
>> ah, a real-world example. Just what we need. Care to write a short pod
>> section using this example, explaining the problem and the solution?
>> plain text or pod will do. we will add it to the coding chapter.

MK> Hmm, let's use my english-like language...

MK> The problem:
MK> - the application static files are installed in /myapp/img,
MK>   /myapp/css, ...
MK> - local site customization can be made by installing customized files
MK>   in /custom/img, /custom/css...
MK> - in both cases they are accessed via /img/..., /css/... urls

MK> The solution - we use custom transhandler to check whether the
MK> customized version exists and use it if so.


In our setup we use mod_rewrite for things like that. It checks for
static resources in the few places and if there is no custom version
finally looks in the some standard location (images, css, javascripts,
any static resources etc ...). In the dual frontend/backend setup I
think this approach is better -- requests for static resources
may still be served by light frontend server.


-- 
WBR, Mike P. Mikhailov

mailto: [EMAIL PROTECTED]
ICQ:280990142

Who is "General Failure", and what is he doing reading my hard disk ?



Re: each considered harmful?

2003-06-16 Thread Stas Bekman
Marcin Kasperski wrote:
sub handler {

   my $r = shift;
   my $uri = $r->uri;
   ... detecting dynamic handlers ...
   while( my($url, $dirs) = each %STATIC_FILES ) {
   if( $uri =~ m{$url/(.*)$} ) {
   foreach my $d (@$dirs) {
   my $file = "$d/$1";
   if( -f $file ) {
  $r->filename($file);
  return OK;
   }
   }
   }
   }
}
ah, a real-world example. Just what we need. Care to write a short pod
section using this example, explaining the problem and the solution?
plain text or pod will do. we will add it to the coding chapter.


Hmm, let's use my english-like language...

The problem:
- the application static files are installed in /myapp/img,
  /myapp/css, ...
- local site customization can be made by installing customized files
  in /custom/img, /custom/css...
- in both cases they are accessed via /img/..., /css/... urls
The solution - we use custom transhandler to check whether the
customized version exists and use it if so.
Yes, but can you write a section to be added to the documentation, explaining 
the problem, providing an example and a solution. Something that you'd have 
loved to find in the docs, when you first discovered it? Of course digesting 
all the helpful comments from others in this thread.

Good docs don't grow on the trees, someone has to put them together.

__
Stas BekmanJAm_pH --> Just Another mod_perl Hacker
http://stason.org/ mod_perl Guide ---> http://perl.apache.org
mailto:[EMAIL PROTECTED] http://use.perl.org http://apacheweek.com
http://modperlbook.org http://apache.org   http://ticketmaster.com


Re: each considered harmful?

2003-06-16 Thread Marcin Kasperski
> > sub handler {
> 
> > my $r = shift;
> > my $uri = $r->uri;
> > ... detecting dynamic handlers ...
> > while( my($url, $dirs) = each %STATIC_FILES ) {
> > if( $uri =~ m{$url/(.*)$} ) {
> > foreach my $d (@$dirs) {
> > my $file = "$d/$1";
> > if( -f $file ) {
> >$r->filename($file);
> >return OK;
> > }
> > }
> > }
> > }
> > }
> 
> ah, a real-world example. Just what we need. Care to write a short pod
> section using this example, explaining the problem and the solution?
> plain text or pod will do. we will add it to the coding chapter.

Hmm, let's use my english-like language...

The problem:
- the application static files are installed in /myapp/img,
  /myapp/css, ...
- local site customization can be made by installing customized files
  in /custom/img, /custom/css...
- in both cases they are accessed via /img/..., /css/... urls

The solution - we use custom transhandler to check whether the
customized version exists and use it if so.


-- 
( Marcin Kasperski   | Working overtime sucks the spirit and motivation  )
( http://www.mk.w.pl |   out of a team. (Wells)  )
()
( O CVS i zarządzaniu wersjami: http://www.mk.w.pl/narzedzia/narzedzia_cvs   )


Re: each considered harmful?

2003-06-16 Thread Randal L. Schwartz
> "Randal" == Randal L Schwartz <[EMAIL PROTECTED]> writes:

Randal> our @STATIC_FILES = (
Randal>   [ qr{^/img/(.*)$} => [ qw(/alternative/img /myapp/install/img) ],
Randal>   [ qr{^/css/(.*)$} => [ qw(/alternative/css /myapp/install/css) ],

Argh.  extra left bracket snuck in.

   [ qr{^/img/(.*)$} => qw(/alternative/img /myapp/install/img) ],
   [ qr{^/css/(.*)$} => qw(/alternative/css /myapp/install/css) ],

Randal>   ...
Randal> );

Randal> sub handler {
Randal>   my $r = shift;
Randal>   my $uri = $r->uri;
Randal>   for (@STATIC_FILES) {
Randal> my ($pat, @dirs) = @$_;
Randal> if ($uri =~ $pat) {
Randal>   my $tail = $1;
Randal>   foreach my $dir (@dirs) {
Randal> my $file = "$dir/$tail";
Randal> if (-f $file) {
Randal>   $r->filename($file);
Randal>   return OK;
Randal> }
Randal>   }
Randal> }
Randal>   }
Randal>   return DECLINED;
Randal> }

Randal> -- 
Randal> Randal L. Schwartz - Stonehenge Consulting Services, Inc. - +1 503 777 0095
Randal> <[EMAIL PROTECTED]> http://www.stonehenge.com/merlyn/>
Randal> Perl/Unix/security consulting, Technical writing, Comedy, etc. etc.
Randal> See PerlTraining.Stonehenge.com for onsite and open-enrollment Perl training!

-- 
Randal L. Schwartz - Stonehenge Consulting Services, Inc. - +1 503 777 0095
<[EMAIL PROTECTED]> http://www.stonehenge.com/merlyn/>
Perl/Unix/security consulting, Technical writing, Comedy, etc. etc.
See PerlTraining.Stonehenge.com for onsite and open-enrollment Perl training!


Re: each considered harmful?

2003-06-16 Thread Randal L. Schwartz
> "Marcin" == Marcin Kasperski <[EMAIL PROTECTED]> writes:

Marcin> Maybe it could be of some interest where I happened to get this
Marcin> problem. I got it in my custom TransHandler implemented to reduce stat
Marcin> calls and to obtain 'select from multiple directories' effect.

Marcin> ... (config file) 

Marcin> our %STATIC_FILES = (
Marcin> '/img' = [ '/alternative/img', '/myapp/install/img' ],
Marcin> '/css' = [ '/alternative/css', '/myapp/install/css' ],
Marcin> ...
Marcin> )

Marcin> ... (transhandler file, simplified of course) ...

Marcin> sub handler {
Marcin> my $r = shift;
Marcin> my $uri = $r->uri;
Marcin> ... detecting dynamic handlers ...
Marcin> while( my($url, $dirs) = each %STATIC_FILES ) {
Marcin> if( $uri =~ m{$url/(.*)$} ) {
Marcin> foreach my $d (@$dirs) {
Marcin> my $file = "$d/$1";
Marcin> if( -f $file ) {
Marcin>$r->filename($file);
Marcin>return OK;
Marcin> }
Marcin> }
Marcin> }
Marcin> }
Marcin> }

That's actually the wrong data structure then.  What you want
if you're only ever accessing it as a list, is a list!

And, you're needlessly recompiling the regex each time.  Here's
a much better way to do that...

our @STATIC_FILES = (
  [ qr{^/img/(.*)$} => [ qw(/alternative/img /myapp/install/img) ],
  [ qr{^/css/(.*)$} => [ qw(/alternative/css /myapp/install/css) ],
  ...
);

sub handler {
  my $r = shift;
  my $uri = $r->uri;
  for (@STATIC_FILES) {
my ($pat, @dirs) = @$_;
if ($uri =~ $pat) {
  my $tail = $1;
  foreach my $dir (@dirs) {
my $file = "$dir/$tail";
if (-f $file) {
  $r->filename($file);
  return OK;
}
  }
}
  }
  return DECLINED;
}

-- 
Randal L. Schwartz - Stonehenge Consulting Services, Inc. - +1 503 777 0095
<[EMAIL PROTECTED]> http://www.stonehenge.com/merlyn/>
Perl/Unix/security consulting, Technical writing, Comedy, etc. etc.
See PerlTraining.Stonehenge.com for onsite and open-enrollment Perl training!


Re: each considered harmful?

2003-06-16 Thread Stas Bekman
Ged Haywood wrote:
[...]
Most people when iterating over a hash will say something like

  foreach $scalar_name ( keys %hash_name ) { ... }

which automatically resets the iterator and is safe in a perisitent
Perl environment like mod_perl.  I hope.
That's a good point, Ged. Marcin, please include this preferred solution in 
the possible solutions section (assuming that you are going to write it ;).

__
Stas BekmanJAm_pH --> Just Another mod_perl Hacker
http://stason.org/ mod_perl Guide ---> http://perl.apache.org
mailto:[EMAIL PROTECTED] http://use.perl.org http://apacheweek.com
http://modperlbook.org http://apache.org   http://ticketmaster.com


Re: each considered harmful?

2003-06-16 Thread Ged Haywood
Hi guys,

On Mon, 16 Jun 2003, Stas Bekman wrote:

[snip,snip]
> keys %hash;
> 
> does the trick
> 
> interesting that I don't remember this issue being reported earlier.

Probably because we all read the Camel Book, section 5.4.3, the bit
about FIRSTKEY.  All except Randal that is... :)

Most people when iterating over a hash will say something like

  foreach $scalar_name ( keys %hash_name ) { ... }

which automatically resets the iterator and is safe in a perisitent
Perl environment like mod_perl.  I hope.

73,
Ged.



Re: each considered harmful?

2003-06-16 Thread Stas Bekman
Marcin Kasperski wrote:
Calling keys() (or values()) in void context is quite efficient.


Nice to now. So it seems the correct idiom for using each is:

   keys %hash;
   while( my($k,$v) = each %hash ) {
...
   }
Looks like it. probably with a comment so you (or other readers) won't forget 
why you did that.

p.s. I've shown an example, so we can have this issue documented
together with other mod_perl gotchas. It's interesting that I don't
remember this issue being reported earlier.


Maybe it could be of some interest where I happened to get this
problem. I got it in my custom TransHandler implemented to reduce stat
calls and to obtain 'select from multiple directories' effect.
... (config file) 

our %STATIC_FILES = (
'/img' = [ '/alternative/img', '/myapp/install/img' ],
'/css' = [ '/alternative/css', '/myapp/install/css' ],
...
)
... (transhandler file, simplified of course) ...

sub handler {
my $r = shift;
my $uri = $r->uri;
... detecting dynamic handlers ...
while( my($url, $dirs) = each %STATIC_FILES ) {
if( $uri =~ m{$url/(.*)$} ) {
foreach my $d (@$dirs) {
my $file = "$d/$1";
if( -f $file ) {
   $r->filename($file);
   return OK;
}
}
}
}
}
ah, a real-world example. Just what we need. Care to write a short pod section 
using this example, explaining the problem and the solution? plain text or pod 
will do. we will add it to the coding chapter.

Thanks.

__
Stas BekmanJAm_pH --> Just Another mod_perl Hacker
http://stason.org/ mod_perl Guide ---> http://perl.apache.org
mailto:[EMAIL PROTECTED] http://use.perl.org http://apacheweek.com
http://modperlbook.org http://apache.org   http://ticketmaster.com


Re: each considered harmful?

2003-06-16 Thread Marcin Kasperski
> Calling keys() (or values()) in void context is quite efficient.

Nice to now. So it seems the correct idiom for using each is:

   keys %hash;
   while( my($k,$v) = each %hash ) {
...
   }

> p.s. I've shown an example, so we can have this issue documented
> together with other mod_perl gotchas. It's interesting that I don't
> remember this issue being reported earlier.

Maybe it could be of some interest where I happened to get this
problem. I got it in my custom TransHandler implemented to reduce stat
calls and to obtain 'select from multiple directories' effect.

... (config file) 

our %STATIC_FILES = (
'/img' = [ '/alternative/img', '/myapp/install/img' ],
'/css' = [ '/alternative/css', '/myapp/install/css' ],
...
)

... (transhandler file, simplified of course) ...

sub handler {
my $r = shift;
my $uri = $r->uri;
... detecting dynamic handlers ...
while( my($url, $dirs) = each %STATIC_FILES ) {
if( $uri =~ m{$url/(.*)$} ) {
foreach my $d (@$dirs) {
my $file = "$d/$1";
if( -f $file ) {
   $r->filename($file);
   return OK;
}
}
}
}
}


Re: each considered harmful?

2003-06-15 Thread Stas Bekman
Paul Johnson wrote:
On Sun, Jun 15, 2003 at 09:35:38PM +0200, Marcin Kasperski wrote:

Does there exist some way to protect before this problem (some kind of
auto-destructor, finally, whatever which would automatically rewind
the hash internal iterator while leaving the context)?
Not really a mod_perl problem, but you can read about the solution in
the docs for each.
   There is a single iterator for each hash, shared by all "each",
   "keys", and "values" function calls in the program; it can be reset
   by reading all the elements from the hash, or by evaluating "keys
   HASH" or "values HASH".
I found this note before asking, believe me... 
But it seems to me that this solution is not satisfactory - calling
'keys' or 'values' is inefficient and destroys most gains from
iterating over the hash using each...


Calling keys() (or values()) in void context is quite efficient.

Whether or not you appreciate the aesthetics is perhaps quite another
matter.
I think the point that Marcin is trying to make is that under normal 
circumstances (a script is run once) this problem doesn't occur. However under 
mod_perl the code persists and therefore doesn't DWIM, till you start thinking 
in mod_perl terms and not one-time run script terms.

The problem can be classified into "the global variables usage under mod_perl" 
category.

Consider:

#!/usr/bin/perl -T

our %hash;
%hash = map {$_ => 1 } 'a'..'c' unless %hash;
print "Content-type: text/plain\n\n";

for (my ($k, $v) = each %hash) {
print "$k $v\n";
last;
}
that script prints different values on the first 3 invocations and prints 
nothing on the 4th, and then repeats the loop. (when you run with httpd -X). 
there are 3 hash key/value pairs in that example.

As Paul has suggested you need to reset the iterator as documented for the 
operator each(). So adding:

keys %has;

does the trick for the above example.

p.s. I've shown an example, so we can have this issue documented together with 
other mod_perl gotchas. It's interesting that I don't remember this issue 
being reported earlier.

__
Stas BekmanJAm_pH --> Just Another mod_perl Hacker
http://stason.org/ mod_perl Guide ---> http://perl.apache.org
mailto:[EMAIL PROTECTED] http://use.perl.org http://apacheweek.com
http://modperlbook.org http://apache.org   http://ticketmaster.com


Re: each considered harmful?

2003-06-15 Thread Paul Johnson
On Sun, Jun 15, 2003 at 09:35:38PM +0200, Marcin Kasperski wrote:
> > > Does there exist some way to protect before this problem (some kind of
> > > auto-destructor, finally, whatever which would automatically rewind
> > > the hash internal iterator while leaving the context)?
> > 
> > Not really a mod_perl problem, but you can read about the solution in
> > the docs for each.
> > 
> > There is a single iterator for each hash, shared by all "each",
> > "keys", and "values" function calls in the program; it can be reset
> > by reading all the elements from the hash, or by evaluating "keys
> > HASH" or "values HASH".
> 
> I found this note before asking, believe me... 
> But it seems to me that this solution is not satisfactory - calling
> 'keys' or 'values' is inefficient and destroys most gains from
> iterating over the hash using each...

Calling keys() (or values()) in void context is quite efficient.

Whether or not you appreciate the aesthetics is perhaps quite another
matter.

-- 
Paul Johnson - [EMAIL PROTECTED]
http://www.pjcj.net


Re: each considered harmful?

2003-06-15 Thread Marcin Kasperski
> > Does there exist some way to protect before this problem (some kind of
> > auto-destructor, finally, whatever which would automatically rewind
> > the hash internal iterator while leaving the context)?
> 
> Not really a mod_perl problem, but you can read about the solution in
> the docs for each.
> 
> There is a single iterator for each hash, shared by all "each",
> "keys", and "values" function calls in the program; it can be reset
> by reading all the elements from the hash, or by evaluating "keys
> HASH" or "values HASH".

I found this note before asking, believe me... 
But it seems to me that this solution is not satisfactory - calling
'keys' or 'values' is inefficient and destroys most gains from
iterating over the hash using each...

-- 
( Marcin Kasperski   | Communication takes place between people, documents   )
( http://www.mk.w.pl |are secondary. (Booch) )
()
( Porady dla twórców serwisów WWW: http://www.mk.w.pl/porady/porady_www  )


Re: each considered harmful?

2003-06-15 Thread Randal L. Schwartz
> "Marcin" == Marcin Kasperski <[EMAIL PROTECTED]> writes:

Marcin> You probably see the problem - when this code is re-executed (next
Marcin> request), the loop iterates just over 'the rest' of the hash.

This is similar to the problem that shows up when you use glob in a
scalar context... it also has lexically-attached state.

And now that I think about it, so does the flip-flop scalar dot-dot
operator.

These are all examples of where it is non-trivial to take a CGI-based
script and just "drop it in" as Apache::Registry.  There's really
nothing A::R can do about it.  You must still use your Branes.
-- 
Randal L. Schwartz - Stonehenge Consulting Services, Inc. - +1 503 777 0095
<[EMAIL PROTECTED]> http://www.stonehenge.com/merlyn/>
Perl/Unix/security consulting, Technical writing, Comedy, etc. etc.
See PerlTraining.Stonehenge.com for onsite and open-enrollment Perl training!


Re: each considered harmful?

2003-06-14 Thread Paul Johnson
On Sat, Jun 14, 2003 at 11:33:17PM +0200, Marcin Kasperski wrote:
> Hmm, probably well known but ... I have not met any direct warning of
> this problem so far.
> 
>  our %SOME_CONFIG = (
> a => 1,
> b => 2,
> c => 3,
>  );  
> 
> ...
>  while (my($k,$v) = each %SOME_CONFIG) {
>  if( ... ) {
>   return; # or last, or throw exception
>  }
>  }
> 
> You probably see the problem - when this code is re-executed (next
> request), the loop iterates just over 'the rest' of the hash.
> 
> Does there exist some way to protect before this problem (some kind of
> auto-destructor, finally, whatever which would automatically rewind
> the hash internal iterator while leaving the context)?

Not really a mod_perl problem, but you can read about the solution in
the docs for each.

There is a single iterator for each hash, shared by all "each",
"keys", and "values" function calls in the program; it can be reset
by reading all the elements from the hash, or by evaluating "keys
HASH" or "values HASH".

perldoc -f each

-- 
Paul Johnson - [EMAIL PROTECTED]
http://www.pjcj.net


each considered harmful?

2003-06-14 Thread Marcin Kasperski
Hmm, probably well known but ... I have not met any direct warning of
this problem so far.

 our %SOME_CONFIG = (
a => 1,
b => 2,
c => 3,
 );  

...
 while (my($k,$v) = each %SOME_CONFIG) {
 if( ... ) {
  return; # or last, or throw exception
 }
 }

You probably see the problem - when this code is re-executed (next
request), the loop iterates just over 'the rest' of the hash.

Does there exist some way to protect before this problem (some kind of
auto-destructor, finally, whatever which would automatically rewind
the hash internal iterator while leaving the context)?