modperl-tips_und_twicks_apache::singleton_and_cache::cache

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



To: "Viljo Marrandi" <vilts@bbz.ee>, "modperl list"
<modperl@apache.org>
From: "Perrin Harkins" <perrin@elem.com>
Subject: Re: Tips & tricks needed :)
Date: Wed, 19 Dec 2001 10:35:06 -0500

> 2. We will use Template-Toolkit and Apache/mod_perl. Problem is that 2
> out of 3 people have never used TT or programmed mod_perl and OO Perl.
> Only I've made sites this way, they've used Embperl til now. How can I
> make this switch for them a little easier?

Get them all copies of the Eagle book and Damian's OO book (or the Advanced
Perl Programming book, which I also like for OO).  Have them read at least
the porting and traps documentation that comes with mod_perl, if not the
whole Guide.  Decide if you will be using a framework like OpenInteract or
OpenFrame.  If not, decide on a basic structure for request handling, error
handling, and parameter parsing, and document it.

We made this same transition at eToys, and you can do it.  Learning to use
TT is pretty quick, but OO and mod_perl require more hand-holding and are
much easier if you have someone around with some confidence in how to use
them.

I'm including a brief outline that I used when I gave a talk about mod_perl.
It's slightly out of date, but it shows what I considered to be the
highlights for mod_perl newbies.

> Which data should I send with cookie? Only some random
> key which is also stored in dbase and this key is used to find real data
> from dbase?

Yes, use a unique key with some kind of MAC so you can be sure it isn't
forged when it's sent back to you.  See the recent thread and the AuthCookie
module.  Note that some things still have to passed as query args or hidden
fields.  This would be anything that could be happening in multiple windows,
like search terms (if you tied them to the cookie, searches in multiple
windows would interfere with each other).

> 4. How is most reasonable to store(and use too) complex formulas and
> coefficients?

I would use an OO approach with polymorphism, like others have described.

===

To: "'Perrin Harkins'" <perrin@elem.com>,
From: Matt Sergeant <msergeant@startechgroup.co.uk>
Subject: RE: Tips & tricks needed :)
Date: Wed, 19 Dec 2001 16:01:22 -0000

> -----Original Message-----
> From: Perrin Harkins [mailto:perrin@elem.com]
> 
> > ALWAYS reinitialize $Your::Singleton::ETERNAL on each query!
> > mod_perl will *NOT* do it for you.
> 
> If you want a per-request global, use $r->pnotes() instead of 
> a standard
> perl global.  Then mod_perl *WILL* do it for you.

Actually I was wondering about writing an Apache::Singleton class, that
works the same as Class::Singleton, but clears the singleton out on each
request (by using pnotes). Would anyone be interested in that?

===

To: "Matt Sergeant" <msergeant@startechgroup.co.uk>,
From: "Perrin Harkins" <perrin@elem.com>
Subject: Re: Tips & tricks needed :)
Date: Wed, 19 Dec 2001 11:11:21 -0500

> Actually I was wondering about writing an Apache::Singleton class, that
> works the same as Class::Singleton, but clears the singleton out on each
> request (by using pnotes). Would anyone be interested in that?

This sounds a bit like Object::Registrar.  If you do it, I'd suggest giving
it a "scope" option for each variable that determines if it's process or
request scope.  In fact you could add support for some kind of data-sharing
and offer a server scope as well.

===

To: "Jean-Michel Hiver" <jhiver@mkdoc.com>,
From: "Perrin Harkins" <perrin@elem.com>
Subject: Re: Tips & tricks needed :)
Date: Wed, 19 Dec 2001 10:43:34 -0500

> ALWAYS reinitialize $Your::Singleton::ETERNAL on each query!
> mod_perl will *NOT* do it for you.

If you want a per-request global, use $r->pnotes() instead of a standard
perl global.  Then mod_perl *WILL* do it for you.

> You might think 'ah yeah but it would be nice if
> $Your::Singleton::ETERNAL could be persistent across queries...' which
> is sometimes desirable, but remember that if you have multiple instances
> of your application running on the same apache,
> $Your::Singleton::ETERNAL will be common to ALL of them.

It will be common to all requests in that particular process, but not shared
between multiple Apache processes.  If you take requests for different
applications that need different singletons on the same Apache process, you
should separate them by namespace so they don't collide.

===

To: "'Perrin Harkins'" <perrin@elem.com>,
From: Matt Sergeant <msergeant@startechgroup.co.uk>
Subject: RE: Tips & tricks needed :)
Date: Wed, 19 Dec 2001 16:20:09 -0000

> -----Original Message-----
> From: Perrin Harkins [mailto:perrin@elem.com]
> 
> > Actually I was wondering about writing an Apache::Singleton 
> class, that
> > works the same as Class::Singleton, but clears the 
> singleton out on each
> > request (by using pnotes). Would anyone be interested in that?
> 
> This sounds a bit like Object::Registrar.

No, it's nothing like Object::Registrar. It's like Class::Singleton.

===

To: "Matt Sergeant" <msergeant@startechgroup.co.uk>,
From: "Perrin Harkins" <perrin@elem.com>
Subject: Re: Tips & tricks needed :)
Date: Wed, 19 Dec 2001 11:35:08 -0500

> No, it's nothing like Object::Registrar. It's like Class::Singleton.

Okay, wishful thinking.  I don't use Class::Singleton, but I have written my
own versions of Object::Registrar a few times to accomplish the same goal.
I don't like to make my core classes dependent on running in a mod_perl
environment if I can avoid it, so I prefer to use a separate registry
approach that keeps $r->pnotes() out of my classes.  It's also nice to be
able to quickly adapt other people's classes in this way without changing
their code to use Class::Singleton.

===
To: modperl@apache.org
From: Rob Nagler <nagler@bivio.biz>
Subject: Re: Tips & tricks needed :)
Date: Wed, 19 Dec 2001 10:51:23 -0700

Perrin Harkins writes:
> Okay, wishful thinking.  I don't use Class::Singleton, but I have written my
> own versions of Object::Registrar a few times to accomplish the same goal.

Ditto.  We use a registry mechanism, too.  One thing I don't quite
understand is the need to "clear out" a singleton.  Why would a
singleton need to hold transient state?

===

To: "Rob Nagler" <nagler@bivio.biz>, <modperl@apache.org>
From: "Perrin Harkins" <perrin@elem.com>
Subject: Re: Tips & tricks needed :)
Date: Wed, 19 Dec 2001 13:17:53 -0500

> One thing I don't quite
> understand is the need to "clear out" a singleton.  Why would a
> singleton need to hold transient state?

It's good for holding something request-specific, like a user session.

===

To: modperl list <modperl@apache.org>
From: Jean-Michel Hiver <jhiver@mkdoc.com>
Subject: Re: Tips & tricks needed :)
Date: Wed, 19 Dec 2001 16:43:29 +0000


On Wed 19-Dec-2001 at 10:43:34AM -0500, Perrin Harkins wrote:
> > ALWAYS reinitialize $Your::Singleton::ETERNAL on each query!
> > mod_perl will *NOT* do it for you.
> 
> If you want a per-request global, use $r->pnotes() instead of a standard
> perl global.  Then mod_perl *WILL* do it for you.

True. But then you are using the Apache object and you're program
doesn't work as a standard CGI anymore :(


> > You might think 'ah yeah but it would be nice if
> > $Your::Singleton::ETERNAL could be persistent across queries...' which
> > is sometimes desirable, but remember that if you have multiple instances
> > of your application running on the same apache,
> > $Your::Singleton::ETERNAL will be common to ALL of them.
> 
> It will be common to all requests in that particular process, but not shared
> between multiple Apache processes.  If you take requests for different
> applications that need different singletons on the same Apache process, you
> should separate them by namespace so they don't collide.

Yup, that's what I meant. Separating by namespace is not very convenient
though. What I have been doing to get around this is that I wrote a
simple module that can be used as a global scalar and that uses tie to
return appropriate variable (FYI I've attached the module, if that
interests anyone).

===

To: "Jean-Michel Hiver" <jhiver@mkdoc.com>,
From: "Perrin Harkins" <perrin@elem.com>
Subject: Re: Tips & tricks needed :)
Date: Wed, 19 Dec 2001 13:41:41 -0500

> > If you want a per-request global, use $r->pnotes() instead of a standard
> > perl global.  Then mod_perl *WILL* do it for you.
>
> True. But then you are using the Apache object and you're program
> doesn't work as a standard CGI anymore :(

I handle this by chekcing for $ENV{MOD_PERL} and just using a global for
storage if it isn't defined.

> Separating by namespace is not very convenient
> though. What I have been doing to get around this is that I wrote a
> simple module that can be used as a global scalar and that uses tie to
> return appropriate variable (FYI I've attached the module, if that
> interests anyone).

That's a good idea.  I've done similar things with accessor methods instead
of tied scalars.

===

To: Matt Sergeant <msergeant@startechgroup.co.uk>
From: Tatsuhiko Miyagawa <miyagawa@edge.co.jp>
Subject: ANNOUNCE: Apache:Singleton 0.01 (Re: Tips & tricks
needed :))
Date: Thu, 20 Dec 2001 18:10:51 +0900

On Thu, 20 Dec 2001 08:57:32 -0000
Matt Sergeant <msergeant@startechgroup.co.uk> wrote:

> Yeah, just like that. Why don't you wrap it up and stick it on CPAN? Saves
> me another module :-)

Okay ;)

The URL

    http://bulknews.net/lib/archives/Apache-Singleton-0.01.tar.gz

has entered CPAN as

  file: $CPAN/authors/id/M/MI/MIYAGAWA/Apache-Singleton-0.01.tar.gz
  size: 1641 bytes
   md5: 57abd03817ead367287d1f5908c0143b


NAME
    Apache::Singleton - Singleton class for mod_perl

SYNOPSIS
      package Printer;
      use base qw(Apache::Singleton);

      # just the same as Class::Singleton

DESCRIPTION
    Apache::Singleton works the same as Class::Singleton, but clears the
    singleton out on each request.

    This module checks $ENV{MOD_PERL}, so it just works well in non-mod_perl
    environment.

AUTHOR
    Original idea by Matt Sergeant <matt@sergeant.org>.

    Code by Tatsuhiko Miyagawa <miyagawa@bulknews.net>

    This library is free software; you can redistribute it and/or modify it
    under the same terms as Perl itself.

SEE ALSO
    the Class::Singleton manpage



===

To: modperl@apache.org
From: wsheldah@lexmark.com
Subject: Class::Singleton dies on "warn"?
Date: Fri, 21 Dec 2001 13:05:54 -0500

Hi,

I just started experimenting with Class::Singleton to store
some static config information. I subclassed it, put a
couple test variables in it, and loaded in my HTML::Mason
page. Everything seemed fine. Then I added a simple warn
statement to the _instance_new() method so I could verify
exactly when it got instantiated from scratch, and it
basically got treated like a "die" statement, spewing the
standard Mason stack trace that Mason normally does on
run-time errors. Is this a bug or a feature? The solution
seems to be to avoid warning statements like the plague in
any Singleton objects.

===

To: Tatsuhiko Miyagawa <miyagawa@edge.co.jp>
From: DeWitt Clinton <dewitt@unto.net>
Subject: Re: [ANNOUNCE] Apache::Singleton 0.03
Date: Sat, 22 Dec 2001 09:23:30 -0500

On Sat, Dec 22, 2001 at 10:39:03PM +0900, Tatsuhiko Miyagawa wrote:

> One instance for one server (across all httpd processes).
> Implemented using Cache::SharedMemoryCache (IPC).

Maybe you want to consider directly using Cache::SharedMemoryBackend
instead of the SharedMemoryCache class.  The full cache class has the
overhead of dealing with object expiration times, which isn't going to
be necessary for the Singleton.

Also, try experimenting with the FileBackend as your sharing mechanism
instead of shared memory.  If you have a large number of Singleton
objects (unlikely, but possible) then this may be a huge performance
win.

===

To: <modperl@apache.org>
From: brian moseley <bcm@maz.org>
Subject: Cache::Cache locking
Date: Sat, 22 Dec 2001 06:55:15 -0800 (PST)

Apache::Singleton::Server got me thinking about Cache::Cache
and locking again. if i'm going to have a server-global
object, i am going to need to protect against multiple
processes updating it simultaneously, right?

we've already talked about this in regards to sessions. most
folks seem to feel that "last one wins" is sufficient for
session data. but what about for objects for which this
policy is not good enough?

if locking is necessary in some instances, even if we can
only contrive theoretical examples right now, how might it
be done in a performant way, especially for objects that can
be modified multiple times while handling a single request?
seems like if you synchronized write access to the object
and caused each process to update its local copy after each
modification, you'd have a hell of a lot of serialization
and deserialization going on in each request.

===

To: brian moseley <bcm@maz.org>
From: perrin@elem.com
Subject: Re: Cache::Cache locking
Date: Sat, 22 Dec 2001 11:03:53 -0800 (PST)

At Sat, 22 Dec 2001 06:55:15 -0800 (PST) , brian moseley <bcm@maz.org> wrote: 
>if locking is necessary in some instances, even if we can
>only contrive theoretical examples right now, how might it
>be done in a performant way, especially for objects that can
>be modified multiple times while handling a single request?

I see two basic ways the locking can be done.  One is to
create a get_for_update() method that holds an exclusive
lock.  You could still call get() for read-only access, but
you would not automatically pick up changes from other
processes and thus should not write any data that you read
with a get().  This is dependent on people being careful to
always call get_for_update() if they intend to update data.
There is no extra serialization, and you could do
record-level locking with most storage backends.

The other way is to do optimistic locking with version
numbers and throw an exception if someone else has updated
the record you want to update.  This is only useful for a
certain class of apps, like data entry screens where
collisions are rare and you can just tell the user to look
at the new data and enter her changes again.

===

To: brian moseley <bcm@maz.org>
From: Tatsuhiko Miyagawa <miyagawa@edge.co.jp>
Subject: Re: Cache::Cache locking
Date: Sun, 23 Dec 2001 04:23:47 +0900

On Sat, 22 Dec 2001 06:55:15 -0800 (PST)
brian moseley <bcm@maz.org> wrote:
 
> Apache::Singleton::Server got me thinking about Cache::Cache
> and locking again. if i'm going to have a server-global
> object, i am going to need to protect against multiple
> processes updating it simultaneously, right?

Right. Which makes me remember current Apache::Singleton::Server is
complete broken :( it doesn't update changed attribute to shared data
in IPC ... would fix.


===

To: brian moseley <bcm@maz.org>, <modperl@apache.org>
From: Gunther Birznieks <gunther@extropia.com>
Subject: Re: Cache::Cache locking
Date: Sun, 23 Dec 2001 15:33:44 +0800

At 10:55 PM 12/22/2001, brian moseley wrote:

>Apache::Singleton::Server got me thinking about Cache::Cache
>and locking again. if i'm going to have a server-global
>object, i am going to need to protect against multiple
>processes updating it simultaneously, right?
>
>we've already talked about this in regards to sessions. most
>folks seem to feel that "last one wins" is sufficient for
>session data. but what about for objects for which this
>policy is not good enough?
>
>if locking is necessary in some instances, even if we can
>only contrive theoretical examples right now, how might it
>be done in a performant way, especially for objects that can
>be modified multiple times while handling a single request?
>seems like if you synchronized write access to the object
>and caused each process to update its local copy after each
>modification, you'd have a hell of a lot of serialization
>and deserialization going on in each request.
>
>thoughts?

Well, I think it depends on the situation. In Extropia::Session what we did 
was set up policies. The default policy is similar to Apache::Session. But 
we allow stronger policies if another application requiring more stringent 
care on the session data shares the user session handle and underlying data 
store.

We ended up separating the concept into two seperate policies: a cache 
policy and a lock policy. Cache policies are things like no cache, cache 
reads, cache reads and writes (so nothing gets written until the object is 
destroyed or flushed manually). Lock policies include no locking (last 
wins), data store (the whole cache is locked because attributes may depend 
on each other), and attribute level locking (integrity is only maintained 
on the attribute write level).

These "policies" effect a general policy of how Extropia::Session works.

I think there are more sophisticated ways of doing an API than an arbitrary 
policy of course. In some cases, locking is something that should be 
settable directly. For example, I mentioned some attributes may depend on 
each other.

For example, let's say a session stores an attribute indicating your 
savings account and another indicating your checking account. Obviously to 
perform a funds transfer within your session you'd want to wrap both 
attribute changes inside of a lock.

Of course, this sort of lock can be separate from the session cache. But 
ideally in order to interact well with previously set session policies the 
locking that is automatic should be similar to the locking that is explicit.

I think if I had to do it over, I would probably not have implemented my 
own Session and reused one of the newer caching mechanisms. One of the 
reasons I didn't go with Apache::Session is that I needed more 
sophistication than Apache::Session provided but I did like Apache::Session 
enough that we wrap around it and provide the extra session features I wanted.

Later,
     Gunther

===

To: modperl@apache.org
From: Tatsuhiko Miyagawa <miyagawa@edge.co.jp>
Subject: Re: Cache::Cache locking
Date: Sun, 23 Dec 2001 21:25:04 +0900

On Sun, 23 Dec 2001 04:23:47 +0900
Tatsuhiko Miyagawa <miyagawa@edge.co.jp> wrote:

> > Apache::Singleton::Server got me thinking about Cache::Cache
> > and locking again. if i'm going to have a server-global
> > object, i am going to need to protect against multiple
> > processes updating it simultaneously, right?
> 
> Right. Which makes me remember current Apache::Singleton::Server is
> complete broken :( it doesn't update changed attribute to shared data
> in IPC ... would fix.

Apache::Singleton 0.04 is now going to CPAN, without Server
subclass, which was broken, and in fact I don't need for my
production environment ;)

If you want Server implementation (with sufficient speed and
robust locking), I'm always open to patches!


0.04  Sun Dec 23 21:20:04 JST 2001
        - Fixed docs
        - pulled off Server subclass: it was completely broken

The URL

    http://bulknews.net/lib/archives/Apache-Singleton-0.04.tar.gz

has entered CPAN as

  file: $CPAN/authors/id/M/MI/MIYAGAWA/Apache-Singleton-0.04.tar.gz
  size: 2675 bytes
   md5: 3865399d4d8a9b970fd71e2f048de8e3

 
===

To: DeWitt Clinton <dewitt@unto.net>
From: Tatsuhiko Miyagawa <miyagawa@edge.co.jp>
Subject: Re: [ANNOUNCE] Apache::Singleton 0.03
Date: Sun, 23 Dec 2001 04:08:21 +0900

On Sat, 22 Dec 2001 09:23:30 -0500
DeWitt Clinton <dewitt@unto.net> wrote:

> > One instance for one server (across all httpd processes).
> > Implemented using Cache::SharedMemoryCache (IPC).
> 
> Maybe you want to consider directly using Cache::SharedMemoryBackend
> instead of the SharedMemoryCache class.  The full cache class has the
> overhead of dealing with object expiration times, which isn't going to
> be necessary for the Singleton.

I'll look into it. Thanks for the input.
 
> Also, try experimenting with the FileBackend as your sharing mechanism
> instead of shared memory.  If you have a large number of Singleton
> objects (unlikely, but possible) then this may be a huge performance
> win.

Exactly.

===

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

doom@kzsu.stanford.edu