You are viewing a plain text version of this content. The canonical link for it is here.
Posted to modperl@perl.apache.org by Stas Bekman <st...@stason.org> on 2003/06/12 06:30:01 UTC
[mp2] Apache::compat breaking 2.0 API solutions?
Last night I have done the mod_perl 1.0 to 2.0 porting presentation at the
Melbourne mongers meeting, and I have raised the issue with Apache::compat,
asking for input from my audience. Here is the problem that we have:
Apache::compat provides mod_perl 1.0 backward compatibility implementation.
And everything works just fine as long as the API has a different name.
However there is a problem if a certain method has the same name but a totally
different functionality. Here is an example:
As explained here:
http://perl.apache.org/docs/2.0/user/porting/compat.html#C__connection_E_gt_remote_addr_
in mod_perl 1.0 you'd say:
use Socket 'sockaddr_in';
my ($port, $ip) = sockaddr_in($r->connection->remote_addr);
i.e. $r->connection->remote_addr was returned a packed socket information.
However in mod_perl 2.0 lingo (read: Apache 2.0 lingo),
$r->connection->remote_addr returns an APR::SockAddr object (read: an opaque
object, to which you need to use methods to access its values). So to
accomplish the above you need to do:
require APR::SockAddr;
my $sock_addr = $c->remote_addr;
my ($port, $ip) = ($sock_addr->port_get, $sock_addr->ip_get);
this is a 1:1 mapping to the Apache 2.0 C API.
So if we provide a back-compat implementation in Apache::compat and it gets
loaded the real 2.0 API can no longer be used.
What I suggested is that we need some sort of scoped pragmata, so we can say:
{
use mod_perl::compat;
my ($port, $ip) = sockaddr_in($r->connection->remote_addr);
}
my $sock_addr = $c->remote_addr;
my ($port, $ip) = ($sock_addr->port_get, $sock_addr->ip_get);
so I can use both APIs and enable the back-compatibility functionality only in
the needed scope. Of course this doesn't make the porting as simple as
enabling Apache::compat, but it solves the API breaking problem. If it was
only possible to make the scoping work.
__________________________________________________________________
Stas Bekman JAm_pH ------> Just Another mod_perl Hacker
http://stason.org/ mod_perl Guide ---> http://perl.apache.org
mailto:stas@stason.org http://use.perl.org http://apacheweek.com
http://modperlbook.org http://apache.org http://ticketmaster.com
Re: [mp2] Apache::compat breaking 2.0 API solutions?
Posted by Stas Bekman <st...@stason.org>.
Scott Penrose wrote:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
>
>> sounds good to me. Anybody has an experience of using Filter::Simple
>> with mod_perl?
>
>
> A simple version looks like this...
>
> package Apache::compat::uber;
> use strict;
> use Filter::Simple;
>
> use constant ahh => 0;
>
> FILTER {
> print STDERR "PRE = $_\n" if ahh;
>
> s/localaddr/localaddr_compat/g;
>
> print STDERR "POST = $_\n" if ahh;
> };
>
> 1;
>
> And thats it... of course you have to write localaddr_compat in the
> Apache::compat module.
>
> (mind you, this is untested :-)
>
>
>> What perl versions Filter::Simple is working with? Assuming that
>> someone will need to use this trickery to get the same code working
>> with mod_perl 1.0 and mod_perl 2.0?
>
>
> Filter::Simple works with 5.6+
Thanks Scott, I'll give it a try.
>>> 2) Operator Overload
>>> use Apache::compat;
>>> # or what ever it actually is...
>>> print STDERR sockdaddr_in($r->localaddr);
>>> print STDERR $r->localaddr->ipnumber;
>>> $r->localaddr returns an operator overloaded object which can then
>>> check if we are returning a scalar (return the packed local address) or
>>> are we returning a blessed reference (return the normal blessed
>>> reference). I use this approach for code like this.
>>> print $md->DC->Title . "\n";
>>> print $md->DC->Title->Short . "\n";
>>
>>
>> How do you cope with a situation like this:
>>
>> my $title = $md->DC->Title;
>>
>> which can then be:
>>
>> print $title;
>>
>> or:
>>
>> print $title->Short;
>
>
> Both work, because in the first case it will be stringified to the
> actual title.
> (although, sometimes you have to do print "" . $title;
>
> In the second it will request from the overload method a blessed reference.
>
>> of course you can overload the "" operator so it'll magically work
>> because print calls "". Is that what you meants by your example?
>
>
> Yes :-) note to self, read bottom before replying above :-)
;)
> It aint perfect. The Filter::Simple would probably be more reliable.
It also won't work in the case of APR::URI::unparse which has a different
problem. It'd be nice to have a generic solution.
__________________________________________________________________
Stas Bekman JAm_pH ------> Just Another mod_perl Hacker
http://stason.org/ mod_perl Guide ---> http://perl.apache.org
mailto:stas@stason.org http://use.perl.org http://apacheweek.com
http://modperlbook.org http://apache.org http://ticketmaster.com
Re: [mp2] Apache::compat breaking 2.0 API solutions?
Posted by Scott Penrose <sc...@dd.com.au>.
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
> sounds good to me. Anybody has an experience of using Filter::Simple
> with mod_perl?
A simple version looks like this...
package Apache::compat::uber;
use strict;
use Filter::Simple;
use constant ahh => 0;
FILTER {
print STDERR "PRE = $_\n" if ahh;
s/localaddr/localaddr_compat/g;
print STDERR "POST = $_\n" if ahh;
};
1;
And thats it... of course you have to write localaddr_compat in the
Apache::compat module.
(mind you, this is untested :-)
> What perl versions Filter::Simple is working with? Assuming that
> someone will need to use this trickery to get the same code working
> with mod_perl 1.0 and mod_perl 2.0?
Filter::Simple works with 5.6+
>> 2) Operator Overload
>> use Apache::compat;
>> # or what ever it actually is...
>> print STDERR sockdaddr_in($r->localaddr);
>> print STDERR $r->localaddr->ipnumber;
>> $r->localaddr returns an operator overloaded object which can then
>> check if we are returning a scalar (return the packed local address)
>> or
>> are we returning a blessed reference (return the normal blessed
>> reference). I use this approach for code like this.
>> print $md->DC->Title . "\n";
>> print $md->DC->Title->Short . "\n";
>
> How do you cope with a situation like this:
>
> my $title = $md->DC->Title;
>
> which can then be:
>
> print $title;
>
> or:
>
> print $title->Short;
Both work, because in the first case it will be stringified to the
actual title.
(although, sometimes you have to do print "" . $title;
In the second it will request from the overload method a blessed
reference.
> of course you can overload the "" operator so it'll magically work
> because print calls "". Is that what you meants by your example?
Yes :-) note to self, read bottom before replying above :-)
It aint perfect. The Filter::Simple would probably be more reliable.
Scooter
- --
Scott Penrose
Open source developer
http://linux.dd.com.au/
scottp@dd.com.au
Dismaimer: Open sauce usually ends up never coming out (of the bottle).
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.0.6 (Darwin)
Comment: For info see http://www.gnupg.org
iD8DBQE+6BCuDCFCcmAm26YRAhuhAKCItBmR+OSFq/yW6DCk9BeNDX8jJQCfR4m0
zmmgtPgUFEL+Uc7wxxwpAjo=
=AJUR
-----END PGP SIGNATURE-----
Re: [mp2] Apache::compat breaking 2.0 API solutions?
Posted by Stas Bekman <st...@stason.org>.
[...]
> From: Scott Penrose <sc...@dd.com.au>
> To: Stas Bekman <st...@stason.org>
>
> I have two solutions for your problem you presented yesterday.
> Both have side effects but I can work them at least in part (I don't
> know all the gotchas with ModPerl though).
>
> 1) Filter::Simple
>
> use Apache::compat::uber;
>
> # or what ever it actually is...
> print STDERR sockdaddr_in($r->localaddr);
>
> no Apache::compat::uber;
>
> print STDERR $r->localaddr->ipnumber;
>
> will get converted to this
>
> print STDERR sockaddr_in($r->localaddr_compat);
>
> print STDERR $r->localaddr->ipnumber;
>
> This has the side effect of having to do a Filter stage which is slower
> start up (but not much) and you have to get the regular expression
> right, but that won't be hard.
Sounds good to me. Anybody has an experience of using Filter::Simple with
mod_perl?
What perl versions Filter::Simple is working with? Assuming that someone will
need to use this trickery to get the same code working with mod_perl 1.0 and
mod_perl 2.0?
> 2) Operator Overload
>
> use Apache::compat;
>
> # or what ever it actually is...
> print STDERR sockdaddr_in($r->localaddr);
>
> print STDERR $r->localaddr->ipnumber;
>
> $r->localaddr returns an operator overloaded object which can then
> check if we are returning a scalar (return the packed local address) or
> are we returning a blessed reference (return the normal blessed
> reference). I use this approach for code like this.
>
> print $md->DC->Title . "\n";
> print $md->DC->Title->Short . "\n";
How do you cope with a situation like this:
my $title = $md->DC->Title;
which can then be:
print $title;
or:
print $title->Short;
of course you can overload the "" operator so it'll magically work because
print calls "". Is that what you meants by your example?
__________________________________________________________________
Stas Bekman JAm_pH ------> Just Another mod_perl Hacker
http://stason.org/ mod_perl Guide ---> http://perl.apache.org
mailto:stas@stason.org http://use.perl.org http://apacheweek.com
http://modperlbook.org http://apache.org http://ticketmaster.com
Re: [mp2] Apache::compat breaking 2.0 API solutions?
Posted by Stas Bekman <st...@stason.org>.
Stas Bekman wrote:
> Last night I have done the mod_perl 1.0 to 2.0 porting presentation at
> the Melbourne mongers meeting, and I have raised the issue with
> Apache::compat, asking for input from my audience. Here is the problem
> that we have:
>
> Apache::compat provides mod_perl 1.0 backward compatibility
> implementation. And everything works just fine as long as the API has a
> different name. However there is a problem if a certain method has the
> same name but a totally different functionality. Here is an example:
>
> As explained here:
> http://perl.apache.org/docs/2.0/user/porting/compat.html#C__connection_E_gt_remote_addr_
>
>
> in mod_perl 1.0 you'd say:
>
> use Socket 'sockaddr_in';
> my ($port, $ip) = sockaddr_in($r->connection->remote_addr);
>
> i.e. $r->connection->remote_addr was returned a packed socket information.
>
> However in mod_perl 2.0 lingo (read: Apache 2.0 lingo),
> $r->connection->remote_addr returns an APR::SockAddr object (read: an
> opaque object, to which you need to use methods to access its values).
> So to accomplish the above you need to do:
> require APR::SockAddr;
> my $sock_addr = $c->remote_addr;
> my ($port, $ip) = ($sock_addr->port_get, $sock_addr->ip_get);
>
> this is a 1:1 mapping to the Apache 2.0 C API.
>
> So if we provide a back-compat implementation in Apache::compat and it
> gets loaded the real 2.0 API can no longer be used.
>
> What I suggested is that we need some sort of scoped pragmata, so we can
> say:
>
> {
> use mod_perl::compat;
> my ($port, $ip) = sockaddr_in($r->connection->remote_addr);
> }
> my $sock_addr = $c->remote_addr;
> my ($port, $ip) = ($sock_addr->port_get, $sock_addr->ip_get);
>
> so I can use both APIs and enable the back-compatibility functionality
> only in the needed scope. Of course this doesn't make the porting as
> simple as enabling Apache::compat, but it solves the API breaking
> problem. If it was only possible to make the scoping work.
And Scott Penrose, of the melbourne pm's fame sent me these suggestions
(posted here with Scott's permission):
-------- Original Message --------
Subject: Two solutions to Apache::compat
Date: Thu, 12 Jun 2003 12:47:28 +1000
From: Scott Penrose <sc...@dd.com.au>
To: Stas Bekman <st...@stason.org>
I have two solutions for your problem you presented yesterday.
Both have side effects but I can work them at least in part (I don't
know all the gotchas with ModPerl though).
1) Filter::Simple
use Apache::compat::uber;
# or what ever it actually is...
print STDERR sockdaddr_in($r->localaddr);
no Apache::compat::uber;
print STDERR $r->localaddr->ipnumber;
will get converted to this
print STDERR sockaddr_in($r->localaddr_compat);
print STDERR $r->localaddr->ipnumber;
This has the side effect of having to do a Filter stage which is slower
start up (but not much) and you have to get the regular expression
right, but that won't be hard.
2) Operator Overload
use Apache::compat;
# or what ever it actually is...
print STDERR sockdaddr_in($r->localaddr);
print STDERR $r->localaddr->ipnumber;
$r->localaddr returns an operator overloaded object which can then
check if we are returning a scalar (return the packed local address) or
are we returning a blessed reference (return the normal blessed
reference). I use this approach for code like this.
print $md->DC->Title . "\n";
print $md->DC->Title->Short . "\n";
Scooter
- --
Scott Penrose
Open source developer
http://linux.dd.com.au/
scottp@dd.com.au