| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Castor JDO - Caching conceptsIntroduction Caching and long transactions Configuration Configuration sample - count-limited Configuration sample - time-limited fifo and lru cache providers Configuration sample - fifo Configuration sample - lru Configuration sample - fifo (custommized) Caching and clustered environments Configuration sample - Coherence Configuration sample - Gigaspaces Custom cache provider Cache implementation CacheFactory implementation Configuration CacheManager - monitoring and clearing caches IntroductionAs explained at the introduction to Castor JDO, Castor has support for many advanced features such as caching. The below sections detail the features related to caching in Castor JDO, as their understanding is required to use Castor JDO in a performant and secure way. In general, performance caches enhance the application performance by reducing the number of read operations against the persistence storage, by storing and reusing the last read or committed values of the object. Performance caches do not affect the behavior of short transactions or locking. It only affects persistence objects that have been released from any transactional context. Starting from Castor 0.8.6, a performance cache implementation has been added. At a technical level, Castor maintains separate (performance) caches for each object type specified in the JDO mapping provided, allowing users to specify - for each object type individually - the type and capacity of the cache. By default, the following cache types are available:
As some of these cache providers allow for allow you to use it in a distributed mode, this allows Castor JDO to be used in a clustered (multi-JVM) environment. Please see the section below for short summary of this feature. Per definition, all build-in performance caches are write-through, because all changes to objects as part of a transaction should be persisted into the cache at commit time without delay. For problems related to the use of performance caches, please consult with the relevant entries in the JDO F.A.Q.. Caching and long transactionsAs it stands currently, performance caches also serve a dual purpose as dirty checking caches for long-transactions. This limitation implies that the object's availability in the performance cache determines the allowed time span of a long transaction. This might become an issue when performance caches of type 'count-limited' or 'time-limited' are being used, where objects will eventually be disposed. If an application tries to update an object that has been disposed from the dirty checking cache, an ObjectModifedException will be thrown. ConfigurationThe DTD declaration is as follows:
With release 1.0 of Castor the DTD has changed but it is backward compatible to the old one and allows to enable debugging of cache access for a specific class as well as passing individual configuration parameters to each cache instance. Only count-limited and time-limited of the current build-in cache types support parameters. Parameter names are case sensitive and are silently ignored if they are unknown to a cache type. It need to be noted that there are 3 parameter names that are reserved for internal use. If you specify a parameter with one of the names: type, name or debug their value will silently be overwritten with another one used internally. Configuration sample - count-limitedA count-limited least-recently-used cache (LRU) for 500 objects can be specified by:
or
If both, the capacity attribute and parameter with name="capacity" is specified, the parameter value takes precedence over the attribute value. Configuration sample - time-limitedA time-limited first-in-first-out cache (FIFO) that expires objects after 15 minutes can be specified by:
or
If both, the capacity attribute and parameter with name="ttl" is specified, the parameter value takes precedence over the attribute value. The debug attribute can be used to enable debugging for objects of a single class. In addition to setting this attribut to true you also need to set logging level of org.castor.cache.Cache to debug.
fifo and lru cache providersThe cache types fifo and lru are based on a set of articles in the O'Reilly Network by William Grosso, to implement a simplified and 1.3-compatible implementation of a Hashbelt algorithm. Hashbelts are simple, in principle. Instead of walking all objects and finding out when they're supposed to expire, use a "conveyor belt" approach. At any particular point in time, objects going into the cache go into the front of the conveyor belt. After a certain amount of time or when the size limit of a container has been reached, move the conveyor belt - put a new, empty container at the front of the conveyor belt to catch new objects, and the one that drops off of the end of the conveyor belt is, by definition, ready for garbage collection. As seen in his system, you can use a set of pluggable strategies to implement the actual hashbelt bits. A container strategy allows you to change out the implementation of the container itself - from simple hashtable-based implementations, up through more complex uses of soft referenced or hashset-based implementations, depending on what you need and what you want it to be used for. A pluggable "expire behavior" handler allows you to determine what action is taken on something which drops off of the bottom of the conveyor belt. In difference to all other cache types the fifo and lru cache types offer various configuration options. Both of them have 6 parameters to configure their behaviour.
Configuration sample - fifoA fifo cache with default values explained above is specified by:
Configuration sample - lruA lru cache with capacity=300 and ttl=300 is defined by:
or better by:
Configuration sample - fifo (custommized)An example of a customized configuration of a fifo cache is:
Caching and clustered environmentsAll of the cache providers added with release 0.9.9 are distributed caches per se or can be configured to operate in such a mode. This effectively allows Castor JDO to be used in a clustered J2EE (multi-JVM) environment, where Castor JDO runs on each of the cluster instances, and where cache state is automatically snychronized between these instances. In such an environment, Castor JDO wil make use of the underlying cache provider to replicate/distribute the content of a specific cache between the various JDOManager instances. Through the distribution mechanism of the cache provider, a client of a Castor JDO instance on one JVM will see any updates made to domain objects performed against any other JVM/JDO instance. Configuration sample - CoherenceThe following class mapping, for example, ...
defines that for all objects of type com.xyz.MyOtherObject Tangosol's Coherence cache provider should be used. Configuration sample - GigaspacesThe following class mapping, for example, ...
defines that for all objects of type com.xyz.MyOtherObject the Gigaspaces cache provider should be used. As Gigspaces supports various cache and clsuer modes, this cache provider allows product-specific configuration as shown below:
Custom cache providerAs of release 0.9.6, Castor allows for the addition of user-defined cache implementations. Whilst Castor provides a set of pre-built cache providers, offering a variety of different cache algorithms, special needs still might require the application developer to implement a custom cache algorithm. Castor facilitates such need by making available standardized interfaces and an easy to understand recipe for integrating a custom cache provider with Castor. As explained in The main component of this package is the interface Cache, which declares the external functionality of a (performance) cache. Existing (and future) cache implementations (have to) implement this interface, which is closely modelled after the java.util.Map interface. Below is a summary of the steps required to build a custom cache provider and register it with Castor JDO:
Cache implementationPlease create a class that implements the interface Cache. To assist users in this task, a AbstractBaseCache class has been supplied, which users should derive their custom Cache instances from, if they wish so. Please consult existing Cache implementations such as TimeLimited} or CountLimited for code samples.
CacheFactory implementationPlease add a class that imnplements the CacheFactory interface and make sure that you provide valid values for the two properties name and className. To assist users in this task, a AbstractCacheFactory class has been supplied, which users should derive their custom CacheFactory instances from, if they wish so. Please consult existing CacheFactory implementations such as TimeLimitedFactory} or CountLimitedFactory for code samples.
ConfigurationThe file castor.properties holds a property org.castor.cache.Factories that enlists the available cache types through their related CacheFactory instances.
To add your custom cache implementation, please append the fully-qualified class name to this list as shown below:
CacheManager - monitoring and clearing cachesSometimes it is necessary to interact with Castor's (performance) caches to e.g. (selectively) clear a Castor cache of its content, or inquire about whether a particular object instance (as identified by its identity) is cached already. For this purpose a CacheManager can be obtained from a Database instance by issuing the following code:
This instance can subsequently be used to selectively clear the Castor performance cache using one of the following methods:
To inquire whether an object has already been cached, please use the following method: Please note that once you have closed the Database instance from which you have obtained the CacheManager, the CacheManager cannot be used anymore and will throw a PersistenceException. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||