Beefy Boxes and Bandwidth Generously Provided by pair Networks
Just another Perl shrine
 
PerlMonks  

Persistant data with Mason

by crenz (Priest)
on Feb 11, 2005 at 18:17 UTC ( #430198=perlquestion: print w/ replies, xml ) Need Help??
crenz has asked for the wisdom of the Perl Monks concerning the following question:

For a web application using Mason/mod_perl/Apache 1, I have the need to have a few variables that are persistant for each request (unlike sessions, where only requests by the same user see this data). I want to keep these variables in memory, without using a database or a file.

Initially, I thought it'd be trivial with mod_perl, but I haven't been able to come up with a way to do it. Might be related to my noticing that my Perl interpreters do not seem to be reused at all by Apache anything placed in a %once block in Mason seems to be executed for each request.

Any hints?

Comment on Persistant data with Mason
Download Code
Re: Persistant data with Mason
by friedo (Prior) on Feb 11, 2005 at 18:20 UTC
    In mod_perl, each Apache child process gets its own interpreter. So while package variables will be persistent, each Apache child will have a separate instance. Perhaps a lightweight solution like DB_File or DBD::SQLite might work for your purposes.
Re: Persistant data with Mason
by Fletch (Chancellor) on Feb 11, 2005 at 18:22 UTC
Re: Persistant data with Mason
by holli (Monsignor) on Feb 11, 2005 at 18:26 UTC
    You could use the environment for that.
    .oO(if you are allowed to set variables in the environment)


    holli, /regexed monk/
Re: Persistant data with Mason
by samizdat (Vicar) on Feb 11, 2005 at 19:02 UTC
    You want common, persistent memory across all processes? The Environment Variable suggestion is a good one, but if you need fast access to larger memory arrays it has its limits.

    I don't know Mason, but IIWM, I'd use Shared Memory (SYSVSHM, in BSD parlance). Look up shmget, shmread, shmwrite. The tricky parts are:
    1. figuring out how to pass the memory pointer handle to each process
    2. write-locking the memory
    I always write code for webservers I have control of (!), so I can usually simplify the first problem because I can force my allocation to occur before anyone else's, assuring me of a known location. However, if you can get your sysadmin to allow you to allocate a small known mailbox location as the first SHM allocation, then you can use that location as the place to store your application's larger variable array. Failing the availability of this, you can always use a file in a known location. Once this is cached, the performance hit isn't too bad.

    SHM is a powerful tool!
Re: Persistant data with Mason
by bpphillips (Friar) on Feb 11, 2005 at 19:34 UTC
    if you're needing access to this data from with Mason, you can use Mason's built in data caching. First you create a component file to encapsulate the data you want to share across requests and processes (i.e. "_getSharedData").
    # mason component _getSharedData my $value = $m->cache->get("key"); return $value if(defined($value)); # compute $value here since it hasn't been stored yet $value = $$; $m->cache->set(key=>$value); return $value
    Then you can call that component anytime you want to retrieve it.
    my $value = $m->comp('/_getSharedData');
    Note that Mason's cache, by default, is stored on disk but you can use any Cache::Cache sub-class that you want (Cache::SharedMemoryCache would allow you to share the data across processes without writing it to disk).
    $m->cache(cache_class => 'SharedMemoryCache')->set(key=>$value); $value = $m->cache(cache_class => 'SharedMemoryCache')->get("key");
    Also, $m->cache->get("key") is scoped to the component you are calling it from (so don't expect to be able to access the same data from another component without calling _getSharedData

    For more info on Mason caching, see the HTML::Mason::Devel docs.

    HTH - Brian
      I believe Cache::Cache recommends using Cache::FileCache rather than Cache::SharedMemoryCache. Other than that, I agree, a cache is probably the easiest way to go. Cache::FileCache on a tmpfs or other sort of ram disk, is quite quick. Alternatively, as others have suggested, a light weight DB backend also makes sharing easy.
      Thanks, this is actually a very good suggestion. Using the environment won't work, as I'll be accessing the Perl interpreter's %ENV, not Apache's. I might dabble with Shared Memory directly some time, but for now, I think I'll just use Mason's caching capabilities to avoid reinventing the wheel...
Re: Persistant data with Mason
by trammell (Priest) on Feb 11, 2005 at 19:41 UTC
    If you're using your own handler.pl, you could just define whatever constants you need as globals there.

    If you don't like any of these suggestions, you should contact autarch. He's one of Mason's authors.

      I may be wrong, but I think this is not true. Anything you define as global in your handler.pl is global for the apache child and not for all apache childs together. They remain independent. You still need to pas by the cache method suggested by 'bpphillips' to exchange information between the processes.

      I thinks that's why 'crenz' also says:

      "anything placed in a %once block in Mason seems to be executed for each request"

      In his test environment, each request done sometimes done by the same child, sometimes by another. That's way he sees sometimes the correct behaviour, but mostly the faulty one due the low charge of his server (each time a fresh apache child!).

      Mason guarantees that everything placed in a %once block is only executed once for the apache child. In this way you can setup all necessary connections and initializations (DB, Init files, ...) for each of the apache childs.

Re: Persistant data with Mason
by injunjoel (Priest) on Feb 11, 2005 at 20:40 UTC
    Greetings all,
    Here is a thought... Could you create an object and then use the "Class Data" idea that the perltoot tutorial gives for its Census example?
    It seems to me this would help you factor out those aspects of your code that you would like to keep global across the application as well as provide a location for storage of your global vars.

    -InjunJoel
    "I do not feel obliged to believe that the same God who endowed us with sense, reason and intellect has intended us to forego their use." -Galileo

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://430198]
Approved by friedo
Front-paged by Tanktalus
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others scrutinizing the Monastery: (10)
As of 2014-12-19 08:14 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    Is guessing a good strategy for surviving in the IT business?





    Results (74 votes), past polls