modperl-class_data_and_preloading_modules_dodging_the_not_stay_shared_prob

This is part of The Pile, a partial archive of some open source mailing lists and newsgroups.



To: modperl@apache.org
From: Adriano Nagelschmidt Rodrigues <anr@agestado.com.br>
Subject: Class data & preloading modules
Date: Fri, 23 Nov 2001 15:23:39 -0200

Hi,

I have some modules that use the idiom

package Foo;

use Bar;

{
  my $bar = Bar->new(args);
  sub bar { return $bar }
}

which works fine until one tries to preload them in startup.pl.

I realized that, by preloading, I was innocently sharing the same DBI
object between Apache children (nothing strange happened during
testing, but I guess it was only a question of time & stress).

I also happen to have Foo subclasses that need the DBI connection to
produce otherwise shareable (read only) class data.

My question is about good programming practice in this case. I guess
I have three options:

(init once per MaxRequestsPerChild)

* initialize the class data externally, from within a method.

* do something like

  {
    my $bar;

    sub bar {
      $bar = BAR->new(args) unless $bar; # too ugly? performance loss small?
      return $bar;
    }
  }

(init only once)

* initialize everything in the parent Apache, just make sure to create
  new DBI connections in the children.


What do you think?

===

To: modperl@apache.org
From: Chris Winters <chris@cwinters.com>
Subject: Re: Class data & preloading modules
Date: Fri, 23 Nov 2001 13:31:10 -0500

* Adriano Nagelschmidt Rodrigues (anr@agestado.com.br) [011123 12:31]:
> ...
> My question is about good programming practice in this case. I guess
> I have three options:
> 
> (init once per MaxRequestsPerChild)
> 
> * initialize the class data externally, from within a method.
> 
> * do something like
> 
>   {
>     my $bar;
> 
>     sub bar {
>       $bar = BAR->new(args) unless $bar; # too ugly? performance loss small?
>       return $bar;
>     }
>   }
> 
> (init only once)
> 
> * initialize everything in the parent Apache, just make sure to create
>   new DBI connections in the children.

Create a PerlChildInitHandler. It will execute every time a new Apache
child is created. In your startup.pl, do:

  Apache->push_handlers( PerlChildInitHandler => \&my_init );

The &my_init routine can do whatever you like.

===
To: modperl@apache.org
From: Adriano Nagelschmidt Rodrigues <anr@agestado.com.br>
Subject: Re: Class data & preloading modules
Date: Fri, 23 Nov 2001 17:06:12 -0200

Chris Winters writes:
> Create a PerlChildInitHandler. It will execute every time a new Apache
> child is created. In your startup.pl, do:
> 
>   Apache->push_handlers( PerlChildInitHandler => \&my_init );
> 
> The &my_init routine can do whatever you like.

Thanks Chris & Stas for the suggestion.

But can I use child init handlers without changing the modules' code?
Right now, they are blissfully ignorant that they work under mod_perl
(in fact, they are supposed to work standalone or in a CGI
environment).

Wouldn't this call for a duplication in the initialization code? Sorry
if I didn't understand correctly, I'm far from being an expert...

===
To: Adriano Nagelschmidt Rodrigues <anr@agestado.com.br>
From: Stas Bekman <stas@stason.org>
Subject: Re: Class data & preloading modules
Date: Sat, 24 Nov 2001 03:17:08 +0800

Adriano Nagelschmidt Rodrigues wrote:

> Chris Winters writes:
> 
>>Create a PerlChildInitHandler. It will execute every time a new Apache
>>child is created. In your startup.pl, do:
>>
>>  Apache->push_handlers( PerlChildInitHandler => \&my_init );
>>
>>The &my_init routine can do whatever you like.
>>
> 
> Thanks Chris & Stas for the suggestion.
> 
> But can I use child init handlers without changing the modules' code?
> Right now, they are blissfully ignorant that they work under mod_perl
> (in fact, they are supposed to work standalone or in a CGI
> environment).


this should work transparently. Just load your module in the 
childinithandler (e.g. have BEGIN block to create closure) or your 
suggested check on whether things were already initialized. just try.


> Wouldn't this call for a duplication in the initialization code? Sorry
> if I didn't understand correctly, I'm far from being an expert...

see above, have a flag to test against.

===

To: "Adriano Nagelschmidt Rodrigues" <anr@agestado.com.br>,
From: "Perrin Harkins" <perrin@elem.com>
Subject: Re: Class data & preloading modules
Date: Tue, 27 Nov 2001 22:51:42 -0500

> * initialize everything in the parent Apache, just make sure to create
>   new DBI connections in the children.

That's what I would do.  It increases the amount of shared memory.
Disconnect the DBI connection when you're done with it.  Apache::DBI
doesn't cache connections during startup, so this shouldn't be a
problem.

===

the rest of The Pile (a partial mailing list archive)

doom@kzsu.stanford.edu