valdez has asked for the wisdom of the Perl Monks concerning the following question:

Dear Fellow Monks,

I'm developing a framework for mod_perl applications called Kinotrope. Presently, I'm working on fixing the configuration system and I would like to hear any opinion about that.

The system is based on Config::General and reads configuration files like this:

<Database> username name password secret host someserver dbname database </Database> HostRoot /home/httpd/kinotrope Templates var/templates/ ...

When an application needs to access the configuration variables it uses something like:

$c = Kinotrope::Configuration->new(); $username = $c->conf('database/username'); %db_conf = $c->conf_hash('database'); # { username => 'name', password + => ... }

I want to be able to use class Kinotrope::Configuration from within mod_perl handlers, cgi-bin and plain shell scripts. At the moment it is possible to create a new instance by passing the name of a configuration file or using an environment variable as default for the same purpose. This way it is possible to share the same configuration class between multiple projects having different configuration files. And every application or mod_perl handler can get cfg by calling new without arguments.

The default configuration file can be set in %ENV using PerlSetEnv inside apache's VirtualHost or Location sections. Here is my first question:

1. Different approaches for the same problem?

I would like to add caching of configuration files. Two distinct implementations come to my mind:

- use private variables inside Configuration class to store cfg data; it is extremely useful if you create new cfg objects wherever needed, without having to pass one object all around;

- use shared memory, maybe with IPC::Shareable, for the same purpose.

I know that the first approach is practical with a small number of concurrent projects, because of memory consumption problems, but can it be very fast. The second approach is better with many cfg files; it is slower but permits sharing of configuration data with batch applications.

I can implement both solutions and choose which solution should be used by inspecting a dedicated %ENV variable. Is this awful trick acceptable? I'm looking for some flexibility here.

2) Which caching solution would you use? Any different approach?

This system can be improved by installing an handler in an earlier phase of apache life cycle which would store the current configuration data somewhere in pnotes. So every following call to new can retrieve cfg data directly from pnotes. The resulting class would be a Singleton, I think.

3) Would you preload configuration files if under mod_perl? Can this be an answer for previous question?

Thanks in advance for every suggestion, criticism or pearl of wisdom!

Ciao, Valerio

p.s.: if someone is curious about Kinotrope, please visit my home node. Note that the project is really young and it is not what you would expect from a usable framework. It is just another way to learn something new.

Replies are listed 'Best First'.
Re: Revision of a Configuration class
by perrin (Chancellor) on Sep 04, 2002 at 16:22 UTC
    My advice is to just use one of the hundreds of config modules on CPAN instead. There are many discussions on perlmonks about which ones are best for what.

    To answer your caching question, use variables in the Configuration class. Using IPC::Shareable won't actually save you memory, but loading the data into variables before mod_perl forks (during startup) will save memory. Don't use pnotes, just create an accessor that returns the cached data. Alternatively you could do this as a singleton class (see Class::Singleton).

      Thank you very much perrin for your advices. Though, I'm already using one of the thousands config modules available on CPAN :) I'll surely try what you suggested.

      I was also looking for an advice on passing a default configuration file via ENV variables, but I didn't get an answer :( May be another module on CPAN could do better than Config::General, but I didn't found it: every modules wants a filename as argument to constructors.

      Thanks, Valerio

        The modules expect you to pass a filename, but you can get that filename any way you want to. Have your code read %ENV, grab the filename, and pass it to Config::General.