ExSite::Store is a multi-purpose data store that allows for sharing of complex data structures among different processes. It is used by ExSite for the following purposes:
Furthermore, any plug-in module can utilize the Store for persistent storage of data.
The data store exposes itself to the application as a simple hash
(typically %store) which may be used by any code in a read/write
fashion. Values written to %store will persist beyond the life of
the process, and will be available to other processes (concurrent, or
subsequent) to read.
It is assumed that the store will be accessed via wrapper classes that will handle the job of fetching data from original sources, loading the data into the store, and checking the store for the data before returning to the original source. Furthermore, those classes should also clean out stale entries in the store if the original source data is updated.
The values written to the store can be arbitrarily complex Perl data
structures. They are serialized using Storable::freeze before being
saved, and are recovered using Storable::thaw. Freezing and thawing
of stored values is handled automatically by the store.
Since the store can keep track of widely disparate data, it is
important to use unique keys when reading or writing to it, to avoid
grabbing or overwriting unrelated data accidentally. The simplest way
to accomplish this is to use an MD5 hash of all the relevant key
data. For example, if caching the results of a SQL query, create an
MD5 hash of the entire query string,or alternatively of the parameters
to the appropriate fetch function that builds the query. It is the
responsibility of the caller to use appropriately hashed keys, as the
store does not know or care about the origin of the data.
The store records a few internal statistics under plain text keys that are prefixed with ``_''.
Every item has a limited lifetime in the store. It will expire if not
accessed within a certain time period (by default,
$config{store}{max_idle}, which is normally 1 hour). Little-used
items will be dropped from the store relatively quickly by this
mechanism. Even frequently-used items will expire after a maximum
storage period has elapsed (by default, this is
$config{store}{max_lifetime}, which is normally 1 day). When an
item expires, it is deleted from the store, and would then have to be
regenerated and re-stored by higher levels of code.
Because the store will remove expired data on a regular basis, you cannot rely on a stored item being present when you request it. Your code is responsible for obtaining the desired data from alternate sources if this is the case. For this reason, the store is useful primarily as a multipurpose cache to improve performance on costly data-fetch operations, or as a place to save state for a limited term.
The default lifetimes of a stored item are defined in
$config{store}{max_idle} and $config{store}{max_lifetime}. You
can override these values for invididual stored items using the the
special _store method, eg:
my $s = tie %store, "ExSite::Store";
$s->_store($key,$value,$my_lifetime,$my_idletime);
or, alternatively,
(tied %store)->_store($key,$value,$my_lifetime,$my_idletime);
To keep the store from blowing up, there is a maximum size of an
object that can be persistently stored. This is defined in
$config{store}{max_size}, which defaults to 10K. Attempts to store
larger objects will be ignored.
The ExSite::Store class handles the general-purpose store logic.
Low-level storage happens in the storage engine, which can be one of
the following:
DBM should be a bit slower, in principle, than SHM, since it uses disk rather than memory. In actual practice, however, DBM benefits from filesystem caching that is performed by the kernel, and is often comparable in speed to SHM. Otherwise, the advantage of DBM is that data will persist even through a full reboot of the server.
If you run multiple installations of ExSite on a server, you should take
care to separate the stores for each of them. If using DBM, this should
take no special effort, since the store files are written to the local
directory, which should be separated anyway. When using SHM, however,
you will have to give each installation a distinct shared memory ID
($config{store}{shmid}).
The store keeps track of the hits (items found successfully), misses (requested items that were not found), deletes (removed expired items), saves (items stored), and connections to the store.
These can be reported using the special summary method, as follows:
my $s = tie %store, "ExSite::Store";
print $s->summary;
This will also summarize all objects currently in the store, by listing their keys and sizes.
The following special methods can be accessed from the store object itself: