problem porting to threaded mode

2008-12-31 Thread craig
Trying to shift our largely mod_perl2 web site to an Apache2 threaded  
MPM and perl ithreads.


The following works under the non-threaded prefork MPM:

use DB_File;
my @dbs;   # array of hash references
my @dbModTime; # mod times of db files
my @dbfns; # array of database pathnames

# executed before fork into child processes
sub post_config {
 my $db;
 my $s = $_[3];
 # tie the DBs and get their mod times
 for ($db = 0; $db < @dbfn; $db++) {
   $dbs[$db] = {};
   tie %{$dbs[$db]}, "DB_File", $dbfn[$db], O_RDONLY
  or die ((caller 0)[3]. " can't tie " . $dbfn[$db] . ": $!");
   $dbModTime[$db] = (CORE::stat($dbfn[$db]))[9]
  or die ((caller 0)[3]. " can't stat " . $dbfn[$db] . ": $!");
} }

The routines that use the databases re-stat the DB files and untie and  
re-tie a DB

that has changed. Each child process must do this for itself.
In the threaded environment, any thread within a process may discover  
that such
an untie and re-tie is necessary, but such an operation should be  
effective

for the other threads in the process as well. This means that @dbs and
@dbModTime should be shared among the threads:
use threads;
use threads::shared;
my @dbs   :shared; # array of hash references
my @dbModTime :shared; # mod times of db files

Making only the changes above makes perl complain "Invalid value for  
shared scalar"
about the '$dbs[$db] = {};' line. This error message can be fixed as  
follows:

 for ($db = 0; $db < @dbfn; $db++) {
   $dbs[$db] = shared_clone({});
   tie %{$dbs[$db]}, "DB_File", $dbfn[$db], O_RDONLY
  or die ((caller 0)[3]. " can't tie " . $dbfn[$db] . ": $!");
   $dbModTime[$db] = (CORE::stat($dbfn[$db]))[9]
  or die ((caller 0)[3]. " can't stat " . $dbfn[$db] . ": $!");
   $s->log->notice ($dbfn[$db]." has " .scalar(keys(%{$dbs[$db]}))."  
entries");

 }

Unfortunately, when this is done the server starts, but the DBs look  
empty and

the log notices for each DB show "0 entries".
Removing the ':shared' tag for @dbs and the 'shared_clone()' wrapper  
for '{}'

causes the log notices to show the proper number of entries for each DB,
but blows up the Apache configuration process (before the 'resuming  
normal

operations' message) with
httpd in free(): error: chunk is already free

in error_log and the following on the terminal:
Abort trap (core dumped)
Error invoking apachectl start command

I guess not having databases is better. I've tried using @dbs as an  
array of
references to named, shared hashes: also no database content. The  
'worker'

and 'event' MPMs work identically w/r/t this problem.
Suggestions of things to try will be very welcome.

Happy New Year, cmac



Re: preserving request body across redirects

2008-12-31 Thread Mark Hedges

> > Oh no, the framework doesn't depend on using a session
> > at all.  Just this particular auth module depends on
> > plugging in the session beforehand.
>
> So I have to have a persistant backstoring session in
> order to use the auth module? 

Well, now, but as you recommended, maybe not necessary.

> I'd think 'implementation subclass must implement a method
> that returns validity of username' would be more flexible
> and concise.  You could use apache environment variables
> and other request state information to pass extra data to
> that function based on what  or  or
>  its in, as a forinstance.

Well, it would get $r.  Yes, I thought it would be a good
idea to rework it so getting the username is its own method,
that way you could subclass and get it from LDAP or
whatever.  Actually in that case, it's not clear that even a
DBI handle is necessary for the top-level implementation,
although if you use the connector handler to get one in your
subclass you could do joins or whatever you need to do.
Then I can also drop the directives for the table name and
field names.

Thanks for the advice!

There may be something wrong with your mail program, or with
alpine's way of reading your mail.  It's hard to sort out
where I wrote and where you wrote because everything has
only one level of '> ' quotes.

Mark

Re: preserving request body across redirects

2008-12-31 Thread David Ihnen

Mark Hedges wrote:

- a lot of times people use references to
other structures when they should subclass... these
references function only to re-map arguments to other
modules, which is ridiculous.
  
Careful on the should.  It can seem extra and possibly confusing but 
isn't always.  Delegation is a valid pattern that is cleaner than 
inheriting at times, particularly when you're mixing in a few different 
modules at the same time to do something.  If you're merely extending an 
existing, then yes, inheritance is good.  Multi-directional 
multi-inheritance can get really messy... (as I dug myself out of in 
development recently myself)  if you haven't read, at least scan...


http://www.perldesignpatterns.com/?MixIns
http://www.perldesignpatterns.com/?DelegationConcept
http://www.perldesignpatterns.com/?CompositePattern

And forgive me if I'm too talky on the subject.  :)

On Tue, 30 Dec 2008, David Ihnen wrote:
  

Yes.  But timtowdti on how that information is
distributed.  In my opinion any *framework* must not
depend on the *application* having established a
persistent backstore of shared session data, so that it
can persist put/posts.  You're *significantly*
constraining the parameters of the implementations
utilizing the framework by requiring this, which I
consider to be exactly what frameworks shouldn't do.  We
may disagree.  :)



Oh no, the framework doesn't depend on using a session at
all.  Just this particular auth module depends on plugging
in the session beforehand.
  
So I have to have a persistant backstoring session in order to use the 
auth module? 

It requires server storage to know what usernames are
available in this situation *yes*.  But that is merely at
authentication time - not during the lifetime of the
session.  An auth service is not a session service.

It does not require server session storage inherently to
associate a session cookie with a user - the cookie has
plenty of storage to do that itself.



Hrmm.  I'll think about that... maybe the only thing
necessary is that a database handle is available from
Apache2::Controller::DBI::Connector.
  


I'd think 'implementation subclass must implement a method that returns 
validity of username' would be more flexible and concise.  You could use 
apache environment variables and other request state information to pass 
extra data to that function based on what  or  or 
 its in, as a forinstance.


That way you wouldn't attempt to corral the user into using a particular 
method of acquiring user data.  I mean, think of the directive 
proliferation that impends from trying to configure all the DBI stuff.  
Sure, perhaps your connector subclass defines the connection string and 
all that hooey (hopefully THAT stuff isn't in the directive 
proliferation...) - but how do you query in this database once you have 
the connection?  Do you define table, column, where conditions, joins?  
An arbitrary SQL string (language in language, ack!)  What if I did 
things way differently... and had an external service providing the data 
that doesn't even require a query, as such, but of course I could layer 
through DBI if I wanted/had to (SELECT openid_identifier FROM USERS 
WHERE username = ?   translating into a json-rpc call to my user store 
service {id:1, method:'get_users', parameters:[?]) that really does do 
the same job as a query, conceptually, but does not utilize the 
assumption that we have a database backed store available at all? 

Example code could show how a dbi connection could be used and 
concisely, but is that part of the requirements of utilizing the framework?


David



Re: preserving request body across redirects

2008-12-31 Thread Mark Hedges

On Wed, 31 Dec 2008, Foo JH wrote:
> Mark Hedges wrote:
> > http://search.cpan.org/~markle/Apache2-Controller-1.000.001/
> Very interesting. I have a controller which functions in a
> slightly different way, but it's good to see alternative
> approaches. I think yours makes life easier.

Thanks Foo!  I've seen the idea implemented a number of
ways, open source and not.  Part of my point was proof of
concept that a lot of the abstractions were useless hoops to
jump through -- a lot of times people use references to
other structures when they should subclass... these
references function only to re-map arguments to other
modules, which is ridiculous.

On Tue, 30 Dec 2008, David Ihnen wrote:
> Yes.  But timtowdti on how that information is
> distributed.  In my opinion any *framework* must not
> depend on the *application* having established a
> persistent backstore of shared session data, so that it
> can persist put/posts.  You're *significantly*
> constraining the parameters of the implementations
> utilizing the framework by requiring this, which I
> consider to be exactly what frameworks shouldn't do.  We
> may disagree.  :)

Oh no, the framework doesn't depend on using a session at
all.  Just this particular auth module depends on plugging
in the session beforehand.

> It requires server storage to know what usernames are
> available in this situation *yes*.  But that is merely at
> authentication time - not during the lifetime of the
> session.  An auth service is not a session service.
>
> It does not require server session storage inherently to
> associate a session cookie with a user - the cookie has
> plenty of storage to do that itself.

Hrmm.  I'll think about that... maybe the only thing
necessary is that a database handle is available from
Apache2::Controller::DBI::Connector.

> Your session times out when you say it times out.  And
> changes states when you say it changes states.  You can
> have two time periods - one being re-auth request time
> period, another being true expiration time period.  The
> purpose of a session timeout is to stop large time delta
> recycling of session data.  The purpose of re-auth time
> period is to nudge your flow into getting a new
> authentication token without the interruption of actual
> logout.  Neither of these is an infinite state, and would
> not be replicated by infinite timeout.

That could work.  Sort of want to avoid a proliferation of
directives... but I guess that's a potential control that
would be less complicated and wouldn't require a persistent
session store on the server.  And can set a flag in notes
that this happened for the app to deal with it if it wants
to, as you said.

Data::UUID's are a good idea for the auth tracking cookie.
For the backend-session plugin right now I'm just using the
_session_id from Apache::Session as the cookie value.

Re: HTTP Response Headers fixup

2008-12-31 Thread David Ihnen

André Warnier wrote:


One of my questions is thus : assuming I keep adding this custom 
header "Test-Header" via mod_headers, will it be visible by the 
HTTPHeadersFixup subclass I create and configure ? 
Its an output connection filter, so I can't imagine it wouldn't work as 
you expect.
if yes, I could make a simple test in my subclass to detect if this 
request is indeed one that needs to be modified.
If the filter configuration in the  is insufficient you mean?  
You certainly can inspect and react.

Or is there another/better/simpler way to resolve my problem ?

http://perl.apache.org/docs/2.0/user/handlers/filters.html#C_PerlOutputFilterHandler_

You can also use output filter handler stage... just look for the header 
in the brigade and insert your own header instead.


Though that sounds more complicated than the ready-made header fixup 
handler.  :)


David





HTTP Response Headers fixup

2008-12-31 Thread André Warnier

Hi.

I have a peculiar problem, and need a peculiar solution.
In an Apache 2.2.3, mod_jk, Tomcat 5.5.x, mod_perl2, perl 5.8.8, Linux 
environment, some links are being re-directed by Apache via mod_jk, to a 
back-end Tomcat server, and a webapp running in that server.


For reasons that are off-topic and obscure, that webapp generates html 
pages that are really encoded in iso-8859-2, but with a Content-Type 
response header that says they are iso-8859-1. It's like that, and I 
cannot change this at the webapp or Tomcat level, not even with a 
servlet filter.


So I need to modify the Content-Type response header, after-the-fact 
(meaning when the response from Tomcat has been channeled back to Apache 
via mod_jk).

My first inspiration was to do it using mod_headers.
But this does not work for some reason.  I have been told on either the 
Apache or Tomcat forum, that it was because Apache or mod_jk does 
something internally, to prevent the response headers generated by 
Tomcat, to be modifiable by Apache later on.
I do not really know if that is true, but it matches the symptoms that I 
am seeing : a custom HTTP header that I *add* to the response after 
mod_jk shows up properly at browser level, but it conpletely ignores my 
attempts at deleting/editing/replacing the Content-Type header for the 
same response.


Then I found Apache2::Filter::HTTPHeadersFixup, which seems to be almost 
exactly what I am looking for.

Except that I have a doubt :
HTTPHeadersFixup is a connection filter, I guess by necessity for that 
kind of thing.  Which means that it affects all requests that go through 
that VHost.  However, only a small fraction of these requests (the ones 
that are re-directed to that rogue Tomcat application) should have their 
response Content-Type modified, and not all requests.
So my question is, rather generally, what would be the best way to 
implement what I need, either with HTTPHeadersFixup or without it ?


Here is a snippet of the configuration I have at the moment, including 
what I tried with mod_headers (but which does not work) :

(lines with ### prefix are my comments to explain what it does/should do)

Start :

### set the is-jk variable only for requests that will be re-directed to 
the rogue Tomcat application


SetEnvIf REQUEST_URI "/servlet\.[^\.]+$" is-jk

### if the above var is set, then try modifying the mod_jk response 
header after-the-fact, at VHost level


Header always set Content-Type: "text/html; charset=ISO-8859-2" env=is-jk

### just to check the above, also add a custom header to the response, 
under the same conditions


Header always set Test-Header: "VHost level" env=is-jk

### the following Location is where the mod_jk redirect really happens 
(the setHandler plays the same role as a JkMount directive)



  SetHandler jakarta-servlet

### try the same as before, but within the specific Location scope
  Header always set Content-Type: "text/html; charset=ISO-8859-2"
  Header always set Test-Header: "Location level"


:End

The result of the above, is that the custom header "Test-Header" gets 
indeed added to the appropriate responses, at the "Location" level (the 
Location directive replaces the one generated by the generic one).
But, the Content-Type header obstinately stays at what the rogue webapp 
set it, which is "Content-Type: text/html; charset=ISO-8859-1" (instead 
of -2 at the end).


One of my questions is thus : assuming I keep adding this custom header 
"Test-Header" via mod_headers, will it be visible by the 
HTTPHeadersFixup subclass I create and configure ? if yes, I could make 
a simple test in my subclass to detect if this request is indeed one 
that needs to be modified.  Or is there another/better/simpler way to 
resolve my problem ?


And, best wishes to all for tomorrow and on.