[jboss-cvs] JBossCache/docs/JBossCache-UserGuide/en/modules ...

Manik Surtani msurtani at jboss.com
Fri Jan 19 12:01:00 EST 2007


  User: msurtani
  Date: 07/01/19 12:01:00

  Added:       docs/JBossCache-UserGuide/en/modules             
                        mgmt_information.xml state_transfer.xml
                        introduction.xml eviction_policies.xml
                        compatibility.xml treecache_marshaller.xml
                        architecture.xml jboss_integration.xml
                        replication.xml cache_loaders.xml configuration.xml
                        transactions.xml basic_api.xml
  Log:
  Refactoring docs dir
  
  Revision  Changes    Path
  1.1      date: 2007/01/19 17:01:00;  author: msurtani;  state: Exp;JBossCache/docs/JBossCache-UserGuide/en/modules/mgmt_information.xml
  
  Index: mgmt_information.xml
  ===================================================================
  <chapter id="mgmt_information">
     <title>Management Information</title>
     <para>JBoss Cache includes JMX MBeans to expose cache functionality and provide statistics that can be
        used to analyze cache operations. JBoss Cache can also broadcast cache events as MBean notifications for handling
        via JMX monitoring tools.
     </para>
  
     <section>
        <title>JBoss Cache MBeans</title>
        <para>JBoss Cache provides an MBean that allows JMX access to a cache instance. This MBean is accessible from an
           MBean
           server through the service name specified in the cache instance's configuration. For example, the Tomcat
           clustering cache instance
           is accessible through the service named "jboss.cache:service=TomcatClusteringCache." This MBean can be used to
           perform
           most cache operations via JMX.
        </para>
        <para>JBoss Cache also provides MBeans for each interceptor configured in the cache's interceptor stack. These
           MBeans
           are used to capture and expose statistics related to cache operations. They are hierarchically associated with
           the
           cache's primary MBean and have service names that reflect this relationship. For example, a replication
           interceptor MBean
           for the TomcatClusteringCache instance will be accessible through the service named
           "jboss.cache:service=TomcatClusteringCache,treecache-interceptor=ReplicationInterceptor."
        </para>
     </section>
  
     <section>
        <title>JBoss Cache Statistics</title>
        <para>JBoss Cache captures statistics in its interceptors and exposes the statistics through interceptor MBeans.
           Cache interceptor
           MBeans are enabled by default; these MBeans can be disabled for a specific cache instance through the
           <emphasis>UseInterceptorMbeans</emphasis>
           attribute. See the Configuration chapter for further details on configuration of this
           attribute.
        </para>
        <para>Each interceptor's MBean provides an attribute that can be used to disable maintenance of statistics for
           that interceptor.
           Note that the majority of the statistics are provided by the CacheMgmtInterceptor MBean so this interceptor is
           the most significant
           in this regard. If you want to disable all statistics for performance reasons, you should utilize the
           <emphasis>UseInterceptorMbeans</emphasis>
           configuration setting as this will prevent the CacheMgmtInterceptor from being included in the cache's
           interceptor stack when the
           cache is started.
        </para>
  
        <para>Each interceptor provides the following common operations and attributes.</para>
  
        <itemizedlist>
           <listitem>dumpStatistics - returns a Map containing the interceptor's attributes and values.</listitem>
           <listitem>resetStatistics - resets all statistics maintained by the interceptor.</listitem>
           <listitem>setStatisticsEnabled(boolean) - allows statistics to be disabled for a specific interceptor.
           </listitem>
        </itemizedlist>
  
        <para>The following table describes the statistics currently available for JBoss Cache.</para>
        <table>
           <title>JBoss Cache Management Statistics</title>
           <tgroup cols="4">
              <colspec colnum="1" colwidth="2*"/>
              <colspec colnum="2" colwidth="2*"/>
              <colspec colnum="3" colwidth="1*"/>
              <colspec colnum="4" colwidth="3*"/>
              <thead>
                 <row>
                    <entry>MBean Name</entry>
                    <entry>Attribute</entry>
                    <entry>Type</entry>
                    <entry>Description</entry>
                 </row>
              </thead>
              <tbody>
                 <row>
                    <entry>ActivationInterceptor</entry>
                    <entry>Activations</entry>
                    <entry>long</entry>
                    <entry>Number of passivated nodes that have been activated.</entry>
                 </row>
                 <row>
                    <entry>CacheLoaderInterceptor</entry>
                    <entry>CacheLoaderLoads</entry>
                    <entry>long</entry>
                    <entry>Number of nodes loaded through a cache loader.</entry>
                 </row>
                 <row>
                    <entry>CacheLoaderInterceptor</entry>
                    <entry>CacheLoaderMisses</entry>
                    <entry>long</entry>
                    <entry>Number of unsuccessful attempts to load a node through a cache loader.</entry>
                 </row>
                 <row>
                    <entry>CacheMgmtInterceptor</entry>
                    <entry>Hits</entry>
                    <entry>long</entry>
                    <entry>Number of successful attribute retrievals.</entry>
                 </row>
                 <row>
                    <entry>CacheMgmtInterceptor</entry>
                    <entry>Misses</entry>
                    <entry>long</entry>
                    <entry>Number of unsuccessful attribute retrievals.</entry>
                 </row>
                 <row>
                    <entry>CacheMgmtInterceptor</entry>
                    <entry>Stores</entry>
                    <entry>long</entry>
                    <entry>Number of attribute store operations.</entry>
                 </row>
                 <row>
                    <entry>CacheMgmtInterceptor</entry>
                    <entry>Evictions</entry>
                    <entry>long</entry>
                    <entry>Number of node evictions.</entry>
                 </row>
                 <row>
                    <entry>CacheMgmtInterceptor</entry>
                    <entry>NumberOfAttributes</entry>
                    <entry>int</entry>
                    <entry>Number of attributes currently cached.</entry>
                 </row>
                 <row>
                    <entry>CacheMgmtInterceptor</entry>
                    <entry>NumberOfNodes</entry>
                    <entry>int</entry>
                    <entry>Number of nodes currently cached.</entry>
                 </row>
                 <row>
                    <entry>CacheMgmtInterceptor</entry>
                    <entry>ElapsedTime</entry>
                    <entry>long</entry>
                    <entry>Number of seconds that the cache has been running.</entry>
                 </row>
                 <row>
                    <entry>CacheMgmtInterceptor</entry>
                    <entry>TimeSinceReset</entry>
                    <entry>long</entry>
                    <entry>Number of seconds since the cache statistics have been reset.</entry>
                 </row>
                 <row>
                    <entry>CacheMgmtInterceptor</entry>
                    <entry>AverageReadTime</entry>
                    <entry>long</entry>
                    <entry>Average time in milliseconds to retrieve a cache attribute, including unsuccessful
                       attribute retrievals.
                    </entry>
                 </row>
                 <row>
                    <entry>CacheMgmtInterceptor</entry>
                    <entry>AverageWriteTime</entry>
                    <entry>long</entry>
                    <entry>Average time in milliseconds to write a cache attribute.</entry>
                 </row>
                 <row>
                    <entry>CacheMgmtInterceptor</entry>
                    <entry>HitMissRatio</entry>
                    <entry>double</entry>
                    <entry>Ratio of hits to hits and misses. A hit is a get attribute operation that results in an object
                       being
                       returned to the client. The retrieval may be from a cache loader if the entry isn't in the local
                       cache.
                    </entry>
                 </row>
                 <row>
                    <entry>CacheMgmtInterceptor</entry>
                    <entry>ReadWriteRatio</entry>
                    <entry>double</entry>
                    <entry>Ratio of read operations to write operations. This is the ratio of cache hits and misses to
                       cache stores.
                    </entry>
                 </row>
                 <row>
                    <entry>CacheStoreInterceptor</entry>
                    <entry>CacheLoaderStores</entry>
                    <entry>long</entry>
                    <entry>Number of nodes written to the cache loader.</entry>
                 </row>
                 <row>
                    <entry>InvalidationInterceptor</entry>
                    <entry>Invalidations</entry>
                    <entry>long</entry>
                    <entry>Number of cached nodes that have been invalidated.</entry>
                 </row>
                 <row>
                    <entry>PassivationInterceptor</entry>
                    <entry>Passivations</entry>
                    <entry>long</entry>
                    <entry>Number of cached nodes that have been passivated.</entry>
                 </row>
                 <row>
                    <entry>TxInterceptor</entry>
                    <entry>Prepares</entry>
                    <entry>long</entry>
                    <entry>Number of transaction prepare operations performed by this interceptor.</entry>
                 </row>
                 <row>
                    <entry>TxInterceptor</entry>
                    <entry>Commits</entry>
                    <entry>long</entry>
                    <entry>Number of transaction commit operations performed by this interceptor.</entry>
                 </row>
                 <row>
                    <entry>TxInterceptor</entry>
                    <entry>Rollbacks</entry>
                    <entry>long</entry>
                    <entry>Number of transaction rollbacks operations performed by this interceptor.</entry>
                 </row>
              </tbody>
           </tgroup>
        </table>
  
     </section>
  
     <section>
        <title>Receiving Cache Notifications</title>
        <para>JBoss Cache users can register a listener to receive cache events as described in the Eviction Policies
           chapter.
           Users can alternatively utilize the cache's management information infrastructure to receive these events via
           JMX
           notifications. Cache events are accessible as notifications by registering a NotificationListener for the
           CacheMgmtInterceptor
           MBean. This functionality is only available if cache statistics are enabled as described in the previous
           section.
        </para>
  
        <para>The following table depicts the JMX notifications available for JBoss Cache as well as the cache events to
           which they correspond.
           These are the notifications that can be received through the CacheMgmtInterceptor MBean. Each notification
           represents a single
           event published by JBoss Cache and provides user data corresponding to the parameters of the event.
        </para>
        <table>
           <title>JBoss Cache MBean Notifications</title>
           <tgroup cols="3">
              <thead>
                 <row>
                    <entry>Notification Type</entry>
                    <entry>Notification Data</entry>
                    <entry>TreeCacheListener Event</entry>
                 </row>
              </thead>
              <tbody>
                 <row>
                    <entry>org.jboss.cache.CacheStarted</entry>
                    <entry>String : cache service name</entry>
                    <entry>cacheStarted</entry>
                 </row>
                 <row>
                    <entry>org.jboss.cache.CacheStopped</entry>
                    <entry>String : cache service name</entry>
                    <entry>cacheStopped</entry>
                 </row>
                 <row>
                    <entry>org.jboss.cache.NodeCreated</entry>
                    <entry>String : fqn</entry>
                    <entry>NodeCreated</entry>
                 </row>
                 <row>
                    <entry>org.jboss.cache.NodeEvicted</entry>
                    <entry>String : fqn</entry>
                    <entry>NodeEvicted</entry>
                 </row>
                 <row>
                    <entry>org.jboss.cache.NodeLoaded</entry>
                    <entry>String : fqn</entry>
                    <entry>NodeLoaded</entry>
                 </row>
                 <row>
                    <entry>org.jboss.cache.NodeModifed</entry>
                    <entry>String : fqn</entry>
                    <entry>NodeModifed</entry>
                 </row>
                 <row>
                    <entry>org.jboss.cache.NodeRemoved</entry>
                    <entry>String : fqn</entry>
                    <entry>NodeRemoved</entry>
                 </row>
                 <row>
                    <entry>org.jboss.cache.NodeVisited</entry>
                    <entry>String : fqn</entry>
                    <entry>NodeVisited</entry>
                 </row>
                 <row>
                    <entry>org.jboss.cache.ViewChange</entry>
                    <entry>String : view</entry>
                    <entry>ViewChange</entry>
                 </row>
                 <row>
                    <entry>org.jboss.cache.NodeActivate</entry>
                    <entrytbl cols="1">
                       <tbody>
                          <row>
                             <entry rowsep="0">Object[0]=String: fqn</entry>
                          </row>
                          <row>
                             <entry>Object[1]=Boolean: pre</entry>
                          </row>
                       </tbody>
                    </entrytbl>
                    <entry>NodeActivate</entry>
                 </row>
                 <row>
                    <entry>org.jboss.cache.NodeEvict</entry>
                    <entrytbl cols="1">
                       <tbody>
                          <row>
                             <entry rowsep="0">Object[0]=String: fqn</entry>
                          </row>
                          <row>
                             <entry>Object[1]=Boolean: pre</entry>
                          </row>
                       </tbody>
                    </entrytbl>
                    <entry>NodeEvict</entry>
                 </row>
                 <row>
                    <entry>org.jboss.cache.NodeModify</entry>
                    <entrytbl cols="1">
                       <tbody>
                          <row>
                             <entry rowsep="0">Object[0]=String: fqn</entry>
                          </row>
                          <row>
                             <entry rowsep="0">Object[1]=Boolean: pre</entry>
                          </row>
                          <row>
                             <entry>Object[2]=Boolean: isLocal</entry>
                          </row>
                       </tbody>
                    </entrytbl>
                    <entry>NodeModify</entry>
                 </row>
                 <row>
                    <entry>org.jboss.cache.NodePassivate</entry>
                    <entrytbl cols="1">
                       <tbody>
                          <row>
                             <entry rowsep="0">Object[0]=String: fqn</entry>
                          </row>
                          <row>
                             <entry>Object[1]=Boolean: pre</entry>
                          </row>
                       </tbody>
                    </entrytbl>
                    <entry>NodePassivate</entry>
                 </row>
                 <row>
                    <entry>org.jboss.cache.NodeRemove</entry>
                    <entrytbl cols="1">
                       <tbody>
                          <row>
                             <entry rowsep="0">Object[0]=String: fqn</entry>
                          </row>
                          <row>
                             <entry rowsep="0">Object[1]=Boolean: pre</entry>
                          </row>
                          <row>
                             <entry>Object[2]=Boolean: isLocal</entry>
                          </row>
                       </tbody>
                    </entrytbl>
                    <entry>NodeRemove</entry>
                 </row>
              </tbody>
           </tgroup>
        </table>
  
        <para>The following is an example of how to programmatically receive cache notifications when running in a JBoss
           application server
           environment. In this example, the client uses a filter to specify which events are of interest.
        </para>
  
        <programlisting>
           MyListener listener = new MyListener();
           NotificationFilterSupport filter = null;
  
           // get reference to MBean server
           Context ic = new InitialContext();
           MBeanServerConnection server = (MBeanServerConnection)ic.lookup("jmx/invoker/RMIAdaptor");
  
           // get reference to CacheMgmtInterceptor MBean
           String cache_service = "jboss.cache:service=TomcatClusteringCache";
           String mgmt_service = cache_service + ",treecache-interceptor=CacheMgmtInterceptor";
           ObjectName mgmt_name = new ObjectName(mgmt_service);
  
           // configure a filter to only receive node created and removed events
           filter = new NotificationFilterSupport();
           filter.disableAllTypes();
           filter.enableType(CacheMgmtInterceptor.NOTIF_NODE_CREATED);
           filter.enableType(CacheMgmtInterceptor.NOTIF_NODE_REMOVED);
  
           // register the listener with a filter
           // leave the filter null to receive all cache events
           server.addNotificationListener(mgmt_name, listener, filter, null);
  
           // ...
  
           // on completion of processing, unregister the listener
           server.removeNotificationListener(mgmt_name, listener, filter, null);
        </programlisting>
  
        <para>The following is the simple notification listener implementation used in the previous example.</para>
        <programlisting>
           private class MyListener implements NotificationListener, Serializable {
           public void handleNotification(Notification notification, Object handback) {
           String message = notification.getMessage();
           String type = notification.getType();
           Object userData = notification.getUserData();
           System.out.println(type + ": "+message);
           if (userData == null) {
           System.out.println("notification data is null");
           }
           else if (userData instanceof String) {
           System.out.println("notification data: "+(String)userData);
           }
           else if (userData instanceof Object[]) {
           Object[] ud = (Object[])userData;
           for (int i = 0; i &gt; ud.length; i++) {
           System.out.println("notification data: "+ud[i].toString());
           }
           }
           else {
           System.out.println("notification data class: " + userData.getClass().getName());
           }
           }
           }
        </programlisting>
  
        <para>Note: the JBoss Cache management implementation only listens to cache events after a client registers to
           receive MBean notifications. As soon as no clients are registered for notifications, the MBean will remove
           itself
           as a cache listener.
        </para>
  
     </section>
  
     <section>
        <title>Accessing Cache MBeans in a Standalone Environment</title>
        <para>JBoss Cache MBeans are readily accessed when running cache instances in an application server that provides
           an MBean server interface such as JBoss JMX Console. Refer to server documentation for instructions on how to
           access
           MBeans running in a server's MBean container.
        </para>
        <para>JBoss Cache MBeans are also accessible when running in a non-server environment if the JVM is JDK 5.0 or
           later.
           When running a standalone cache in a JDK 5 environment, you can access the cache's MBeans as follows.
        </para>
        <para>
           <orderedlist>
              <listitem>Set the system property
                 <emphasis>-Dcom.sun.management.jmxremote</emphasis>
                 when starting the JVM
                 where the cache will run.
              </listitem>
              <listitem>Once the JVM is running, start the JDK 5
                 <emphasis>jconsole</emphasis>
                 utility, located in the JDK's /bin directory.
              </listitem>
              <listitem>When the utility loads, you will be able to select your JVM and connect to it. The JBoss Cache
                 MBeans will be
                 available on the MBeans panel.
              </listitem>
           </orderedlist>
        </para>
        <para>Note: The
           <emphasis>jconsole</emphasis>
           utility will automatically register as a listener for cache notifications when connected
           to a JVM running JBoss Cache instances.
        </para>
  
        <para>The following figure shows cache interceptor MBeans in
           <emphasis>jconsole</emphasis>
           . Cache statistics are displayed
           for the CacheMgmt interceptor:
        </para>
  
        <figure>
           <title>CacheMgmtInterceptor MBean</title>
  
           <mediaobject>
              <imageobject>
                 <imagedata fileref="images/CacheMgmtInterceptor.png"/>
              </imageobject>
           </mediaobject>
        </figure>
  
     </section>
  
  </chapter>
  
  
  
  1.1      date: 2007/01/19 17:01:00;  author: msurtani;  state: Exp;JBossCache/docs/JBossCache-UserGuide/en/modules/state_transfer.xml
  
  Index: state_transfer.xml
  ===================================================================
  <chapter id="state_transfer">
     <title>State Transfer</title>
  
     <para>"State Transfer" refers to the process by which a JBoss Cache instance
        prepares itself to begin providing a service by acquiring the current
        state from another cache instance and integrating that state into its
        own state.
     </para>
  
     <section>
        <title>Types of State Transfer</title>
  
        <para>The state that is acquired and integrated can consist of two basic
           types:
        </para>
  
        <orderedlist>
           <listitem>
              <para>"Transient" or "in-memory" state. This consists of the actual
                 in-memory state of another cache instance -- the contents of the
                 various in-memory nodes in the cache that is providing state are
                 serialized and transferred; the recipient deserializes the data,
                 creates corresponding nodes in its own in-memory tree, and populates
                 them with the transferred data.
              </para>
  
              <para>"In-memory" state transfer is enabled by setting
                 the cache's
                 <literal>FetchInMemoryState</literal>
                 property
                 to
                 <literal>true</literal>
                 .
              </para>
           </listitem>
           <listitem>
              <para>"Persistent" state. Only applicable if a non-shared
                 cache loader is used. The state stored in the state-provider
                 cache's persistent store is deserialized and transferred; the
                 recipient passes the data to its own cache loader, which persists
                 it to the recipient's persistent store.
              </para>
  
              <para>"Persistent" state transfer is enabled by setting
                 a cache loader's
                 <literal>CacheLoaderFetchPersistentState</literal>
                 property to
                 <literal>true</literal>
                 . If multiple cache loaders
                 are configured in a chain, only one can have this property
                 set to true; otherwise you will get an exception at startup.
              </para>
  
              <para>Persistent state transfer with a shared cache loader does
                 not make sense, as the same persistent store that provides the
                 data will just end up receiving it. Therefore, if a shared cache
                 loader is used, the cache will not allow a persistent state
                 transfer even if a cache loader has
                 <literal>CacheLoaderFetchPersistentState</literal>
                 set to
                 <literal>true</literal>
                 .
              </para>
           </listitem>
        </orderedlist>
  
        <para>Which of these types of state transfer is appropriate depends on the usage
           of the cache.
        </para>
  
        <orderedlist>
           <listitem>
              <para>If a write-through cache loader is used, the current cache
                 state is fully represented by the persistent state. Data may
                 have been evicted from the in-memory state, but it will still be
                 in the persistent store. In this case, if the cache loader is not
                 shared, persistent state transfer is used to ensure the new cache
                 has the correct state. In-memory state can be transferred as well
                 if the desire is to have a "hot" cache -- one that has all
                 relevant data in memory when the cache begins providing service.
                 (Note that the "CacheLoaderPreload" configuration parameter can
                 be used as well to provide a "warm" or "hot" cache without
                 requiring an in-memory state transfer. This approach somewhat
                 reduces the burden on the cache instance providing state, but
                 increases the load on the persistent store on the recipient
                 side.)
              </para>
           </listitem>
           <listitem>
              <para>If a cache loader is used with passivation, the full
                 representation of the state can only be obtained by combining
                 the in-memory (i.e. non-passivated) and persistent (i.e. passivated)
                 states. Therefore an in-memory state transfer is necesssary. A
                 persistent state transfer is necessary if the cache loader is
                 not shared.
              </para>
           </listitem>
           <listitem>
              <para>If no cache loader is used and the cache is solely a
                 write-aside cache (i.e. one that is used to cache data that can
                 also be found in a persistent store, e.g. a database), whether
                 or not in-memory state should be transferred depends on whether
                 or not a "hot" cache is desired.
              </para>
           </listitem>
        </orderedlist>
     </section>
     <section>
        <title>When State Transfer Occurs</title>
  
        <para>If either in-memory or persistent state transfer is enabled, a full or
           partial state transfer will be done at various times, depending on how the
           cache is used. "Full" state transfer refers to the transfer of the state
           related to the entire tree -- i.e. the root node and all nodes below it.
           A "partial" state transfer is one where just a portion of the tree is
           transferred -- i.e. a node at a given Fqn and all nodes below it.
        </para>
  
        <para>If either in-memory or persistent state transfer is enabled, state
           transfer will occur at the following times:
        </para>
  
        <orderedlist>
           <listitem>
              <para>Initial state transfer. This occurs when the cache is first
                 started (as part of the processing of the
                 <literal>start()</literal>
                 method). This is a full state transfer. The state is retrieved
                 from the cache instance that has been operational the longest. If
                 there is any problem receiving or integrating the state, the cache
                 will not start.
              </para>
  
              <para>Initial state transfer will occur unless:</para>
  
              <orderedlist>
                 <listitem>
                    <para>The cache's
                       <literal>InactiveOnStartup</literal>
                       property
                       is
                       <literal>true</literal>
                       . This property is used in conjunction
                       with region-based marshalling; see below for more on this.
                    </para>
                 </listitem>
                 <listitem>
                    <para>Buddy replication is used. See below for more on
                       state transfer with buddy replication.
                    </para>
                 </listitem>
              </orderedlist>
           </listitem>
  
           <listitem>
              <para>Partial state transfer following region activation. Only
                 relevant when region-based marshalling is used. Here a special
                 classloader is needed to unmarshal the state for a portion of
                 the tree. State transfer cannot succeed until the application
                 registers this classloader with the cache. Once the application
                 registers its classloader, it calls
                 <literal>activateRegion(String fqn)</literal>
                 .
                 As part of the region activation process, a partial state transfer
                 of the relevant subtree's state is performed. The state is
                 requested from the oldest cache instance in the cluster; if that
                 instance responds with no state, state is requested from each
                 instance one by one until one provides state or all instances have
                 been queried.
              </para>
  
              <para>Typically when region-based marshalling is used, the cache's
                 <literal>InactiveOnStartup</literal>
                 property is set to
                 <literal>true</literal>
                 . This suppresses initial state transfer,
                 which would fail due to the inability to deserialize the
                 transferred state.
              </para>
           </listitem>
  
           <listitem>
              <para>Buddy replication. When buddy replication is used, initial
                 state transfer is disabled. Instead, when a cache instance joins the
                 cluster, it becomes the buddy of one or more other instances, and
                 one or more other instances become its buddy. Each time an instance
                 determines it has a new buddy providing backup for it, it pushes
                 it's current state to the new buddy. This "pushing" of state to
                 the new buddy is slightly different from other forms of state
                 transfer, which are based on a "pull" approach (i.e. recipient
                 asks for and receives state). However, the process of preparing
                 and integrating the state is the same.
              </para>
  
              <para>This "push" of state upon buddy group formation only occurs
                 if the
                 <literal>InactiveOnStartup</literal>
                 property is set to
                 <literal>false</literal>
                 . If it is
                 <literal>true</literal>
                 ,
                 state transfer amongst the buddies only occurs when the application
                 calls
                 <literal>activateRegion(String fqn)</literal>
                 on the various
                 members of the group.
              </para>
  
              <para>Partial state transfer following an
                 <literal>activateRegion()</literal>
                 call is slightly different in the buddy replication case as well.
                 Instead of requesting the partial state from one cache instance,
                 and trying all instances until one responds, with buddy replication
                 the instance that is activating a region will request partial
                 state from each instance for which it is serving as a backup.
              </para>
           </listitem>
        </orderedlist>
  
  
     </section>
  </chapter>
  
  
  1.1      date: 2007/01/19 17:01:00;  author: msurtani;  state: Exp;JBossCache/docs/JBossCache-UserGuide/en/modules/introduction.xml
  
  Index: introduction.xml
  ===================================================================
  <?xml version="1.0" encoding="UTF-8"?>
  <chapter id="introduction">
     <title>Introduction</title>
  
     <section>
        <title>What is a
           <literal>TreeCache</literal>
           ?
        </title>
  
        <para>
           A
           <literal>TreeCache</literal>
           is a tree-structured, replicated, transactional cache from JBoss Cache.
           <literal>TreeCache</literal>
           is the backbone for many fundamental JBoss Application Server clustering services, including - in certain
           versions - clustering JNDI, HTTP and EJB sessions, and clustering JMS.
        </para>
        <para>
           In addition to this,
           <literal>TreeCache</literal>
           can be used as a standalone transactional and replicated cache or even an object oriented data store, may be
           embedded in other J2EE compliant application servers such as BEA WebLogic or IBM WebSphere, servlet containers
           such as Tomcat, or even in Java applications that do not run from within an application server.
        </para>
     </section>
  
     <section>
        <title>
           <literal>TreeCache</literal>
           Basics
        </title>
  
        <para>The structure of a
           <literal>TreeCache</literal>
           is a tree with nodes. Each node has a
           name and zero or more children. A node can only have 1 parent; there is
           currently no support for graphs. A node can be reached by navigating from
           the root recursively through children, until the requested node is found. It can
           also be accessed by giving a fully qualified name (FQN), which consists of
           the concatenation of all node names from the root to the node in question.
        </para>
  
        <para>A
           <literal>TreeCache</literal>
           can have multiple roots, allowing for a number of
           different trees to be present in a single cache instance. Note that a one level tree is
           essentially a
           <literal>HashMap</literal>
           . Each node in the tree has a map of keys and
           values. For a replicated cache, all keys and values have to be
           <literal>Serializable</literal>
           . Serializability is not a requirement for
           <literal>PojoCache</literal>
           , where
           reflection and aspect-oriented programming is used to replicate any type.
        </para>
  
        <para>A
           <literal>TreeCache</literal>
           can be either local or replicated. Local trees exist
           only inside the Java VM in which they are created, whereas replicated trees
           propagate any changes to all other replicated trees in the same cluster. A
           cluster may span different hosts on a network or just different JVMs
           on a single host.
        </para>
  
        <para>The first version of
           <literal>TreeCache</literal>
           was essentially a single
           <literal>HashMap</literal>
           that replicated. However, the decision
           was taken to go with a tree structured cache because (a) it is more
           flexible and efficient and (b) a tree can always be reduced to a map,
           thereby offering both possibilities. The efficiency argument was driven by
           concerns over replication overhead, and was that a value itself can be a
           rather sophisticated object, with aggregation pointing to other objects,
           or an object containing many fields. A small change in the object would
           therefore trigger the entire object (possibly the transitive closure over
           the object graph) to be serialized and propagated to the other nodes in
           the cluster. With a tree, only the modified nodes in the tree need to be
           serialized and propagated. This is not necessarily a concern for
           <literal>TreeCache</literal>
           , but is a
           vital requirement for
           <literal>PojoCache</literal>
           (as we will see in the separate
           <literal>PojoCache</literal>
           documentation).
        </para>
  
        <para>When a change is made to the
           <literal>TreeCache</literal>
           , and that change is done in
           the context of a transaction, then we defer the replication of changes until the transaction
           commits successfully. All modifications are kept in a list associated with
           the transaction for the caller. When the transaction commits, we replicate the
           changes. Otherwise, (on a rollback) we simply undo the changes locally and release
           any locks, resulting in zero replication traffic and overhead. For example, if a caller
           makes 100 modifications and then rolls back the transaction, we will not replicate
           anything, resulting in no network traffic.
        </para>
  
        <para>If a caller has no transaction associated with it (and isolation level is not
           NONE - more about this later), we will replicate right after each modification, e.g. in the above
           case we would send 100 messages, plus an additional message for the
           rollback. In this sense, running without a transaction can be thought of as analogous as running with
           auto-commit switched on in JDBC terminology, where each operation is committed automatically.
        </para>
  
        <para>There is an API for plugging in different transaction managers: all
           it requires is to get the transaction associated with the caller's thread. Several
           <literal>TransactionManagerLookup</literal>
           implementations are provided for popular transaction managers, including a
           <literal>DummyTransactionManager</literal>
           for testing.
        </para>
  
        <para>Finally, we use pessimistic locking of the cache by default, with optimistic locking as a configurable
           option. With pessimistic locking, we can
           configure the local locking policy corresponding to database-style
           transaction isolation levels, i.e., SERIALIZABLE, REPEATABLE,
           READ_COMMITTED, READ_UNCOMMITTED and NONE. More on transaction
           isolation levels will be discussed later. Note that the cluster-wide
           isolation level is READ-UNCOMMITTED by default as we don’t acquire a
           cluster-wide lock on touching an object for which we don’t yet have a lock
           (this would result in too high an overhead for messaging).
        </para>
        <para>With optimistic locking, isolation levels are ignored as each transaction effectively maintains a copy of
           the data with which it works on and then attempts to merge back into the tree structure upon transaction
           completion. This results in a near-serializable degree of data integrity, applied cluster-wide, for the minor
           performance penalty incurred when validating workspace data at commit time, and the occasional transaction
           commit failure due to validation failures at commit time.
        </para>
     </section>
  </chapter>
  
  
  1.1      date: 2007/01/19 17:01:00;  author: msurtani;  state: Exp;JBossCache/docs/JBossCache-UserGuide/en/modules/eviction_policies.xml
  
  Index: eviction_policies.xml
  ===================================================================
  <chapter id="eviction_policies">
     <title>Eviction Policies</title>
  
     <para>Eviction policies specify the living behavior of a node residing inside the
        cache, e.g., life time and maximum numbers allowed.
        Memory constraints on servers mean cache cannot grow indefinitely, so policies
        need to be in place to restrict the size of the cache in memory.
     </para>
  
     <section>
        <title>Eviction Policy Plugin</title>
  
        <para>The design of the JBoss Cache eviction policy framework is based
           on the
           <literal>EvictionInterceptor</literal>
           to
           handle cache events and relay them back to the eviction policies. During the cache start up,
           an
           <literal>EvictionInterceptor</literal>
           will be added to the cache
           interceptor stack if the eviction policy is specified.
           Then whenever a cached node is added, removed, evicted, or visited, the
           <literal>EvictionInterceptor</literal>
           will maintain state statistics and
           information will be relayed to each individual Eviction Region.
           Each Region can define a different
           <literal>EvictionPolicy</literal>
           implementation that
           will know how to correlate cache add, remove, and visit events back to a
           defined eviction behavior. It's the policy provider's responsibility to
           decide when to call back the cache "evict" operation.
        </para>
  
        <para>There is a single eviction thread (timer) that will run at a
           configured interval. This thread will make calls into each of the policy
           providers and inform it of any aggregated adds,
           removes and visits (gets) events to the cache during the configured interval.
           The eviction thread is responsible for kicking off the eviction policy
           processing (a single pass) for each configured eviction cache
           region.
        </para>
  
        <para>In order to implement an eviction policy, the following interfaces
           must be implemented: org.jboss.cache.eviction.EvictionPolicy,
           org.jboss.cache.eviction.EvictionAlgorithm,
           org.jboss.cache.eviction.EvictionQueue and
           org.jboss.cache.eviction.EvictionConfiguration. When compounded
           together, each of these interface implementations define all the
           underlying mechanics necessary for a complete eviction policy
           implementation.
        </para>
  
        <figure>
           <title>TreeCache eviction UML Diagram</title>
  
           <mediaobject>
              <imageobject>
                 <imagedata fileref="images/EvictionUML.png"/>
              </imageobject>
           </mediaobject>
        </figure>
  
        <programlisting>public interface EvictionPolicy
           {
           /**
           * Evict a node form the underlying cache.
           *
           * @param fqn DataNode corresponds to this fqn.
           * @throws Exception
           */
           void evict(Fqn fqn) throws Exception;
  
           /**
           * Return children names as Objects
           *
           * @param fqn
           * @return Child names under given fqn
           */
           Set getChildrenNames(Fqn fqn);
  
           /**
           * Is this a leaf node?
           *
           * @param fqn
           * @return true/false if leaf node.
           */
           boolean hasChild(Fqn fqn);
  
           Object getCacheData(Fqn fqn, Object key);
  
           /**
           * Method called to configure this implementation.
           */
           void configure(TreeCache cache);
  
           /**
           * Get the associated EvictionAlgorithm used by the EvictionPolicy.
           * &lt;p/&gt;
           * This relationship should be 1-1.
           *
           * @return An EvictionAlgorithm implementation.
           */
           EvictionAlgorithm getEvictionAlgorithm();
  
           /**
           * The EvictionConfiguration implementation class used by this EvictionPolicy.
           *
           * @return EvictionConfiguration implementation class.
           */
           Class getEvictionConfigurationClass();
  
           /**
           * This method will be invoked prior to an event being processed for a node
           * with the specified Fqn.
           *
           <p>
              * This method provides a way to optimize the performance of eviction by
              * signalling that the node associated with the specified Fqn should not be
              * subject to normal eviction processing. It can also be used to filter
              * out certain {@link NodeEventType event types} in which the particular
              * eviction algorithm has no interest.
              *
           </p>
           *
           <p>
              * If this method returns false then the event is processed normally
              * and eviction processing for the node continues. As a result, the event
              * will be added to the {@link Region eviction region's} event queue where
              * at some later point the particular algorithm of the eviction policy
              * can use it to decide whether to call {@link #evict(Fqn)}.
              *
           </p>
           *
           <p>
              * If this method returns true, then the event is ignored and will not factor
              * in any subsequent eviction processing.
              *
           </p>
           *
           * @param fqn The Fqn of the node associated with the event.
           * @param eventType the type of the event
           *
           * @return
           <code>true</code>
           to ignore events of this type for this Fqn,
           *
           <code>false</code>
           to process events normally.
           */
           boolean canIgnoreEvent(Fqn fqn, NodeEventType eventType);
  
           }
        </programlisting>
  
        <programlisting>public interface EvictionAlgorithm
           {
           /**
           * Entry point for evictin algorithm. This is an api called by the EvictionTimerTask
           * to process the node events in waiting and actual pruning, if necessary.
           *
           * @param region Region that this algorithm will operate on.
           */
           void process(Region region) throws EvictionException;
  
           /**
           * Reset the whole eviction queue. Queue may needs to be reset due to corrupted state, for example.
           *
           * @param region Region that this algorithm will operate on.
           */
           void resetEvictionQueue(Region region);
  
           /**
           * Get the EvictionQueue implementation used by this algorithm.
           *
           * @return the EvictionQueue implementation.
           */
           EvictionQueue getEvictionQueue();
  
           }
        </programlisting>
  
        <programlisting>public interface EvictionQueue
           {
           /**
           * Get the first entry in the queue.
           * &lt;p/&gt;
           * If there are no entries in queue, this method will return null.
           * &lt;p/&gt;
           * The first node returned is expected to be the first node to evict.
           *
           * @return first NodeEntry in queue.
           */
           public NodeEntry getFirstNodeEntry();
  
           /**
           * Retrieve a node entry by Fqn.
           * &lt;p/&gt;
           * This will return null if the entry is not found.
           *
           * @param fqn Fqn of the node entry to retrieve.
           * @return Node Entry object associated with given Fqn param.
           */
           public NodeEntry getNodeEntry(Fqn fqn);
  
           public NodeEntry getNodeEntry(String fqn);
  
           /**
           * Check if queue contains the given NodeEntry.
           *
           * @param entry NodeEntry to check for existence in queue.
           * @return true/false if NodeEntry exists in queue.
           */
           public boolean containsNodeEntry(NodeEntry entry);
  
           /**
           * Remove a NodeEntry from queue.
           * &lt;p/&gt;
           * If the NodeEntry does not exist in the queue, this method will return normally.
           *
           * @param entry The NodeEntry to remove from queue.
           */
           public void removeNodeEntry(NodeEntry entry);
  
           /**
           * Add a NodeEntry to the queue.
           *
           * @param entry The NodeEntry to add to queue.
           */
           public void addNodeEntry(NodeEntry entry);
  
           /**
           * Get the size of the queue.
           *
           * @return The number of items in the queue.
           */
           public int size();
  
           /**
           * Clear the queue.
           */
           public void clear();
  
           }
        </programlisting>
  
        <programlisting>public interface EvictionConfiguration
           {
           public static final int WAKEUP_DEFAULT = 5;
  
           public static final String ATTR = "attribute";
           public static final String NAME = "name";
  
           public static final String REGION = "region";
           public static final String WAKEUP_INTERVAL_SECONDS = "wakeUpIntervalSeconds";
           public static final String MAX_NODES = "maxNodes";
           public static final String TIME_TO_IDLE_SECONDS = "timeToIdleSeconds";
           public static final String TIME_TO_LIVE_SECONDS = "timeToLiveSeconds";
           public static final String MAX_AGE_SECONDS = "maxAgeSeconds";
           public static final String MIN_NODES = "minNodes";
           public static final String REGION_POLICY_CLASS = "policyClass";
  
           /**
           * Parse the XML configuration for the given specific eviction region.
           * &lt;p/&gt;
           * The element parameter should contain the entire region block. An example
           * of an entire Element of the region would be:
           * &lt;p/&gt;
           * &lt;region name="abc"&gt;
           * &lt;attribute name="maxNodes"&gt;10&lt;/attribute&gt;
           * &lt;/region&gt;
           *
           * @param element DOM element for the region. &lt;region name="abc"&gt;&lt;/region&gt;
           * @throws ConfigureException
           */
           public void parseXMLConfig(Element element) throws ConfigureException;
           }
        </programlisting>
  
        <para>
           <emphasis>Note that:</emphasis>
        </para>
  
        <itemizedlist>
           <listitem>
              <para>The EvictionConfiguration class 'parseXMLConfig(Element)'
                 method expects only the DOM element pertaining to the region the
                 policy is being configured for.
              </para>
           </listitem>
        </itemizedlist>
  
        <itemizedlist>
           <listitem>
              <para>The EvictionConfiguration implementation should maintain
                 getter and setter methods for configured properties pertaining to
                 the policy used on a given cache region. (e.g. for LRUConfiguration
                 there is a int getMaxNodes() and a setMaxNodes(int))
              </para>
           </listitem>
        </itemizedlist>
  
        <para>Alternatively, the implementation of a new eviction policy
           provider can be further simplified by extending BaseEvictionPolicy and
           BaseEvictionAlgorithm. Or for properly sorted EvictionAlgorithms (sorted
           in eviction order - see LFUAlgorithm) extending
           BaseSortedEvictionAlgorithm and implementing SortedEvictionQueue takes
           care of most of the common functionality available in a set of eviction
           policy provider classes
        </para>
  
        <programlisting>public abstract class BaseEvictionPolicy implements EvictionPolicy
           {
           protected static final Fqn ROOT = new Fqn("/");
  
           protected TreeCache cache_;
  
           public BaseEvictionPolicy()
           {
           }
  
           /** EvictionPolicy interface implementation */
  
           /**
           * Evict the node under given Fqn from cache.
           *
           * @param fqn The fqn of a node in cache.
           * @throws Exception
           */
           public void evict(Fqn fqn) throws Exception
           {
           cache_.evict(fqn);
           }
  
           /**
           * Return a set of child names under a given Fqn.
           *
           * @param fqn Get child names for given Fqn in cache.
           * @return Set of children name as Objects
           */
           public Set getChildrenNames(Fqn fqn)
           {
           try
           {
           return cache_.getChildrenNames(fqn);
           }
           catch (CacheException e)
           {
           e.printStackTrace();
           }
           return null;
           }
  
           public boolean hasChild(Fqn fqn)
           {
           return cache_.hasChild(fqn);
           }
  
           public Object getCacheData(Fqn fqn, Object key)
           {
           try
           {
           return cache_.get(fqn, key);
           }
           catch (CacheException e)
           {
           e.printStackTrace();
           }
           return null;
           }
  
           public void configure(TreeCache cache)
           {
           this.cache_ = cache;
           }
  
           public boolean canIgnoreEvent(Fqn fqn, NodeEventType eventType) {
           return false;
           }
  
           }
        </programlisting>
  
        <programlisting>public abstract class BaseEvictionAlgorithm implements EvictionAlgorithm
           {
           private static final Log log = LogFactory.getLog(BaseEvictionAlgorithm.class);
  
           protected Region region;
           protected BoundedBuffer recycleQueue;
           protected EvictionQueue evictionQueue;
  
           /**
           * This method will create an EvictionQueue implementation and prepare it for use.
           *
           * @param region Region to setup an eviction queue for.
           * @return The created EvictionQueue to be used as the eviction queue for this algorithm.
           * @throws EvictionException
           * @see EvictionQueue
           */
           protected abstract EvictionQueue setupEvictionQueue(Region region) throws EvictionException;
  
           /**
           * This method will check whether the given node should be evicted or not.
           *
           * @param ne NodeEntry to test eviction for.
           * @return True if the given node should be evicted. False if the given node should not be evicted.
           */
           protected abstract boolean shouldEvictNode(NodeEntry ne);
  
           protected BaseEvictionAlgorithm()
           {
           recycleQueue = new BoundedBuffer();
           }
  
           protected void initialize(Region region) throws EvictionException
           {
           this.region = region;
           evictionQueue = setupEvictionQueue(region);
           }
  
           /**
           * Process the given region.
           * &lt;p/&gt;
           * Eviction Processing encompasses the following:
           * &lt;p/&gt;
           * - Add/Remove/Visit Nodes
           * - Prune according to Eviction Algorithm
           * - Empty/Retry the recycle queue of previously evicted but locked (during actual cache eviction) nodes.
           *
           * @param region Cache region to process for eviction.
           * @throws EvictionException
           */
           public void process(Region region) throws EvictionException
           {
           if (this.region == null)
           {
           this.initialize(region);
           }
  
           this.processQueues(region);
           this.emptyRecycleQueue();
           this.prune();
           }
  
           public void resetEvictionQueue(Region region)
           {
           }
  
           /**
           * Get the underlying EvictionQueue implementation.
           *
           * @return the EvictionQueue used by this algorithm
           * @see EvictionQueue
           */
           public EvictionQueue getEvictionQueue()
           {
           return this.evictionQueue;
           }
  
           /**
           * Event processing for Evict/Add/Visiting of nodes.
           * &lt;p/&gt;
           * - On AddEvents a new element is added into the eviction queue
           * - On RemoveEvents, the removed element is removed from the eviction queue.
           * - On VisitEvents, the visited node has its eviction statistics updated (idleTime, numberOfNodeVisists, etc..)
           *
           * @param region Cache region to process for eviction.
           * @throws EvictionException
           */
           protected void processQueues(Region region) throws EvictionException
           {
           EvictedEventNode node;
           int count = 0;
           while ((node = region.takeLastEventNode()) != null)
           {
           int eventType = node.getEvent();
           Fqn fqn = node.getFqn();
  
           count++;
           switch (eventType)
           {
           case EvictedEventNode.ADD_EVENT:
           this.processAddedNodes(fqn);
           break;
           case EvictedEventNode.REMOVE_EVENT:
           this.processRemovedNodes(fqn);
           break;
           case EvictedEventNode.VISIT_EVENT:
           this.processVisitedNodes(fqn);
           break;
           default:
           throw new RuntimeException("Illegal Eviction Event type " + eventType);
           }
           }
  
           if (log.isTraceEnabled())
           {
           log.trace("processed " + count + " node events");
           }
  
           }
  
           protected void evict(NodeEntry ne)
           {
           // NodeEntry ne = evictionQueue.getNodeEntry(fqn);
           if (ne != null)
           {
           evictionQueue.removeNodeEntry(ne);
           if (!this.evictCacheNode(ne.getFqn()))
           {
           try
           {
           recycleQueue.put(ne);
           }
           catch (InterruptedException e)
           {
           e.printStackTrace();
           }
           }
           }
           }
  
           /**
           * Evict a node from cache.
           *
           * @param fqn node corresponds to this fqn
           * @return True if successful
           */
           protected boolean evictCacheNode(Fqn fqn)
           {
           if (log.isTraceEnabled())
           {
           log.trace("Attempting to evict cache node with fqn of " + fqn);
           }
           EvictionPolicy policy = region.getEvictionPolicy();
           // Do an eviction of this node
  
           try
           {
           policy.evict(fqn);
           }
           catch (Exception e)
           {
           if (e instanceof TimeoutException)
           {
           log.warn("eviction of " + fqn + " timed out. Will retry later.");
           return false;
           }
           e.printStackTrace();
           return false;
           }
  
           if (log.isTraceEnabled())
           {
           log.trace("Eviction of cache node with fqn of " + fqn + " successful");
           }
  
           return true;
           }
  
           /**
           * Process an Added cache node.
           *
           * @param fqn FQN of the added node.
           * @throws EvictionException
           */
           protected void processAddedNodes(Fqn fqn) throws EvictionException
           {
           if (log.isTraceEnabled())
           {
           log.trace("Adding node " + fqn + " to eviction queue");
           }
  
           long stamp = System.currentTimeMillis();
           NodeEntry ne = new NodeEntry(fqn);
           ne.setModifiedTimeStamp(stamp);
           ne.setNumberOfNodeVisits(1);
           // add it to the node map and eviction queue
           if (evictionQueue.containsNodeEntry(ne))
           {
           if (log.isTraceEnabled())
           {
           log.trace("Queue already contains " + ne.getFqn() + " processing it as visited");
           }
           this.processVisitedNodes(ne.getFqn());
           return;
           }
  
           evictionQueue.addNodeEntry(ne);
  
           if (log.isTraceEnabled())
           {
           log.trace(ne.getFqn() + " added successfully to eviction queue");
           }
           }
  
           /**
           * Remove a node from cache.
           * &lt;p/&gt;
           * This method will remove the node from the eviction queue as well as
           * evict the node from cache.
           * &lt;p/&gt;
           * If a node cannot be removed from cache, this method will remove it from the eviction queue
           * and place the element into the recycleQueue. Each node in the recycle queue will get retried until
           * proper cache eviction has taken place.
           * &lt;p/&gt;
           * Because EvictionQueues are collections, when iterating them from an iterator, use iterator.remove()
           * to avoid ConcurrentModificationExceptions. Use the boolean parameter to indicate the calling context.
           *
           * @param fqn FQN of the removed node
           * @throws EvictionException
           */
           protected void processRemovedNodes(Fqn fqn) throws EvictionException
           {
           if (log.isTraceEnabled())
           {
           log.trace("Removing node " + fqn + " from eviction queue and attempting eviction");
           }
  
           NodeEntry ne = evictionQueue.getNodeEntry(fqn);
           if (ne != null)
           {
           evictionQueue.removeNodeEntry(ne);
           }
  
           if (log.isTraceEnabled())
           {
           log.trace(fqn + " removed from eviction queue");
           }
           }
  
           /**
           * Visit a node in cache.
           * &lt;p/&gt;
           * This method will update the numVisits and modifiedTimestamp properties of the Node.
           * These properties are used as statistics to determine eviction (LRU, LFU, MRU, etc..)
           * &lt;p/&gt;
           * *Note* that this method updates Node Entries by reference and does not put them back
           * into the queue. For some sorted collections, a remove, and a re-add is required to
           * maintain the sorted order of the elements.
           *
           * @param fqn FQN of the visited node.
           * @throws EvictionException
           */
           protected void processVisitedNodes(Fqn fqn) throws EvictionException
           {
           NodeEntry ne = evictionQueue.getNodeEntry(fqn);
           if (ne == null)
           {
           this.processAddedNodes(fqn);
           return;
           }
           // note this method will visit and modify the node statistics by reference!
           // if a collection is only guaranteed sort order by adding to the collection,
           // this implementation will not guarantee sort order.
           ne.setNumberOfNodeVisits(ne.getNumberOfNodeVisits() + 1);
           ne.setModifiedTimeStamp(System.currentTimeMillis());
           }
  
           /**
           * Empty the Recycle Queue.
           * &lt;p/&gt;
           * This method will go through the recycle queue and retry to evict the nodes from cache.
           *
           * @throws EvictionException
           */
           protected void emptyRecycleQueue() throws EvictionException
           {
           while (true)
           {
           Fqn fqn;
  
           try
           {
           fqn = (Fqn) recycleQueue.poll(0);
           }
           catch (InterruptedException e)
           {
           e.printStackTrace();
           break;
           }
  
           if (fqn == null)
           {
           if (log.isTraceEnabled())
           {
           log.trace("Recycle queue is empty");
           }
           break;
           }
  
           if (log.isTraceEnabled())
           {
           log.trace("emptying recycle bin. Evict node " + fqn);
           }
  
           // Still doesn't work
           if (!evictCacheNode(fqn))
           {
           try
           {
           recycleQueue.put(fqn);
           }
           catch (InterruptedException e)
           {
           e.printStackTrace();
           }
           break;
           }
           }
           }
  
           protected void prune() throws EvictionException
           {
           NodeEntry entry;
           while ((entry = evictionQueue.getFirstNodeEntry()) != null)
           {
           if (this.shouldEvictNode(entry))
           {
           this.evict(entry);
           }
           else
           {
           break;
           }
           }
           }
  
           }
        </programlisting>
  
        <para>
           <emphasis>Note that:</emphasis>
        </para>
  
        <itemizedlist>
           <listitem>
              <para>The BaseEvictionAlgorithm class maintains a processing
                 structure. It will process the ADD, REMOVE, and VISIT events queued
                 by the Region (events are originated from the
                 EvictionTreeCacheListener) first. It also maintains an collection of
                 items that were not properly evicted during the last go around
                 because of held locks. That list is pruned. Finally, the
                 EvictionQueue itself is pruned for entries that should be evicted
                 based upon the configured eviction rules for the region.
              </para>
           </listitem>
        </itemizedlist>
  
        <programlisting>
           public abstract class BaseSortedEvictionAlgorithm extends BaseEvictionAlgorithm implements EvictionAlgorithm
           {
           private static final Log log = LogFactory.getLog(BaseSortedEvictionAlgorithm.class);
  
           public void process(Region region) throws EvictionException
           {
           super.process(region);
           }
  
           protected void processQueues(Region region) throws EvictionException
           {
           boolean evictionNodesModified = false;
  
           EvictedEventNode node;
           int count = 0;
           while ((node = region.takeLastEventNode()) != null)
           {
           int eventType = node.getEvent();
           Fqn fqn = node.getFqn();
  
           count++;
           switch (eventType)
           {
           case EvictedEventNode.ADD_EVENT:
           this.processAddedNodes(fqn);
           evictionNodesModified = true;
           break;
           case EvictedEventNode.REMOVE_EVENT:
           this.processRemovedNodes(fqn);
           break;
           case EvictedEventNode.VISIT_EVENT:
           this.processVisitedNodes(fqn);
           evictionNodesModified = true;
           break;
           default:
           throw new RuntimeException("Illegal Eviction Event type " + eventType);
           }
           }
  
           if (log.isTraceEnabled())
           {
           log.trace("Eviction nodes visited or added requires resort of queue " + evictionNodesModified);
           }
  
           this.resortEvictionQueue(evictionNodesModified);
  
  
           if (log.isTraceEnabled())
           {
           log.trace("processed " + count + " node events");
           }
  
           }
  
           /**
           * This method is called to resort the queue after add or visit events have occurred.
           * &lt;p/&gt;
           * If the parameter is true, the queue needs to be resorted. If it is false, the queue does not
           * need resorting.
           *
           * @param evictionQueueModified True if the queue was added to or visisted during event processing.
           */
           protected void resortEvictionQueue(boolean evictionQueueModified)
           {
           long begin = System.currentTimeMillis();
           ((SortedEvictionQueue) evictionQueue).resortEvictionQueue();
           long end = System.currentTimeMillis();
  
           if (log.isTraceEnabled())
           {
           long diff = end - begin;
           log.trace("Took " + diff + "ms to sort queue with " + getEvictionQueue().size() + " elements");
           }
           }
  
           }
        </programlisting>
  
        <para>
           <emphasis>Note that:</emphasis>
        </para>
  
        <itemizedlist>
           <listitem>
              <para>The BaseSortedEvictionAlgorithm class will maintain a boolean
                 through the algorithm processing that will determine if any new
                 nodes were added or visited. This allows the Algorithm to determine
                 whether to resort the eviction queue items (in first to evict order)
                 or to skip the potentially expensive sorting if there have been no
                 changes to the cache in this region.
              </para>
           </listitem>
        </itemizedlist>
  
        <programlisting>public interface SortedEvictionQueue extends EvictionQueue
           {
           /**
           * Provide contract to resort a sorted queue.
           */
           public void resortEvictionQueue();
           }
        </programlisting>
  
        <para>
           <emphasis>Note that:</emphasis>
        </para>
  
        <itemizedlist>
           <listitem>
              <para>The SortedEvictionQueue interface defines the contract used by
                 the BaseSortedEvictionAlgorithm abstract class that is used to
                 resort the underlying queue. Again, the queue sorting should be
                 sorted in first to evict order. The first entry in the list should
                 evict before the last entry in the queue. The last entry in the
                 queue should be the last entry that will require eviction.
              </para>
           </listitem>
        </itemizedlist>
     </section>
  
     <section>
        <title>TreeCache Eviction Policy Configuration</title>
  
        <para>TreeCache 1.2.X allows a single eviction policy provider class to
           be configured for use by all regions. As of TreeCache 1.3.x each cache
           region can define its own eviction policy provider or it can use the
           eviction policy provider class defined at the cache level (1.2.x
           backwards compatibility)
        </para>
  
        <para>Please note that configuring the policy via XML has the implicit restriction that
           the region Fqn can only be String based. Afterall, there is no easy way to
           specify a generic object-based Fqn through external XML. If you need to evict
           non-String based Fqn, you will need to do it at runtime via programmatic API. See
           the following section for examples.
        </para>
  
        <para>Here is an example of a legacy 1.2.x EvictionPolicyConfig element
           to configure TreeCache for use with a single eviction policy
           provider
        </para>
  
        <programlisting>
           &lt;attribute name="EvictionPolicyClass"&gt;org.jboss.cache.eviction.LRUPolicy&lt;/attribute&gt;
           &lt;!-- Specific eviction policy configurations. This is LRU --&gt;
           &lt;attribute name="EvictionPolicyConfig"&gt;
           &lt;config&gt;
           &lt;attribute name="wakeUpIntervalSeconds"&gt;5&lt;/attribute&gt;
           &lt;!-- This defaults to 200000 if not specified --&gt;
           &lt;attribute name="eventQueueSize"&gt;100000&lt;/attribute&gt;
           &lt;!-- Cache wide default --&gt;
           &lt;region name="/_default_"&gt;
           &lt;attribute name="maxNodes"&gt;5000&lt;/attribute&gt;
           &lt;attribute name="timeToLiveSeconds"&gt;1000&lt;/attribute&gt;
           &lt;/region&gt;
           &lt;region name="/org/jboss/data"&gt;
           &lt;attribute name="maxNodes"&gt;5000&lt;/attribute&gt;
           &lt;attribute name="timeToLiveSeconds"&gt;1000&lt;/attribute&gt;
           &lt;/region&gt;
           &lt;region name="/org/jboss/test/data"&gt;
           &lt;attribute name="maxNodes"&gt;5&lt;/attribute&gt;
           &lt;attribute name="timeToLiveSeconds"&gt;4&lt;/attribute&gt;
           &lt;/region&gt;
           &lt;region name="/test/"&gt;
           &lt;attribute name="maxNodes"&gt;10000&lt;/attribute&gt;
           &lt;attribute name="timeToLiveSeconds"&gt;5&lt;/attribute&gt;
           &lt;/region&gt;
           &lt;region name="/maxAgeTest/"&gt;
           &lt;attribute name="maxNodes"&gt;10000&lt;/attribute&gt;
           &lt;attribute name="timeToLiveSeconds"&gt;8&lt;/attribute&gt;
           &lt;attribute name="maxAgeSeconds"&gt;10&lt;/attribute&gt;
           &lt;/region&gt;
           &lt;/config&gt;
           &lt;/attribute&gt;
        </programlisting>
  
        <para>Here is an example of configuring a different eviction provider
           per region
        </para>
  
        <programlisting>
           &lt;attribute name="EvictionPolicyConfig"&gt;
           &lt;config&gt;
           &lt;!-- This defaults to 200000 if not specified --&gt;
           &lt;attribute name="eventQueueSize"&gt;100000&lt;/attribute&gt;
           &lt;attribute name="wakeUpIntervalSeconds"&gt;5&lt;/attribute&gt;
           &lt;!-- Cache wide default --&gt;
           &lt;region name="/_default_" policyClass="org.jboss.cache.eviction.LRUPolicy"&gt;
           &lt;attribute name="maxNodes"&gt;5000&lt;/attribute&gt;
           &lt;attribute name="timeToLiveSeconds"&gt;1000&lt;/attribute&gt;
           &lt;/region&gt;
           &lt;region name="/org/jboss/data" policyClass="org.jboss.cache.eviction.LFUPolicy"&gt;
           &lt;attribute name="maxNodes"&gt;5000&lt;/attribute&gt;
           &lt;attribute name="minNodes"&gt;1000&lt;/attribute&gt;
           &lt;/region&gt;
           &lt;region name="/org/jboss/test/data" policyClass="org.jboss.cache.eviction.FIFOPolicy"&gt;
           &lt;attribute name="maxNodes"&gt;5&lt;/attribute&gt;
           &lt;/region&gt;
           &lt;region name="/test/" policyClass="org.jboss.cache.eviction.MRUPolicy"&gt;
           &lt;attribute name="maxNodes"&gt;10000&lt;/attribute&gt;
           &lt;/region&gt;
           &lt;region name="/maxAgeTest/" policyClass="org.jboss.cache.eviction.LRUPolicy"&gt;
           &lt;attribute name="maxNodes"&gt;10000&lt;/attribute&gt;
           &lt;attribute name="timeToLiveSeconds"&gt;8&lt;/attribute&gt;
           &lt;attribute name="maxAgeSeconds"&gt;10&lt;/attribute&gt;
           &lt;/region&gt;
           &lt;/config&gt;
           &lt;/attribute&gt;
        </programlisting>
  
        <para>Lastly, an example of mixed mode. In this scenario the regions
           that have a specific policy defined will use that policy. Those that do
           not will default to the policy defined on the entire cache
           instance.
        </para>
  
        <programlisting>
           &lt;attribute name="EvictionPolicyClass"&gt;org.jboss.cache.eviction.LRUPolicy&lt;/attribute&gt;
           &lt;!-- Specific eviction policy configurations. This is LRU --&gt;
           &lt;attribute name="EvictionPolicyConfig"&gt;
           &lt;config&gt;
           &lt;attribute name="wakeUpIntervalSeconds"&gt;5&lt;/attribute&gt;
           &lt;!-- This defaults to 200000 if not specified --&gt;
           &lt;attribute name="eventQueueSize"&gt;100000&lt;/attribute&gt;
           &lt;!-- Cache wide default --&gt;
           &lt;region name="/_default_"&gt;
           &lt;attribute name="maxNodes"&gt;5000&lt;/attribute&gt;
           &lt;attribute name="timeToLiveSeconds"&gt;1000&lt;/attribute&gt;
           &lt;/region&gt;
           &lt;region name="/org/jboss/data" policyClass="org.jboss.cache.eviction.FIFOPolicy"&gt;
           &lt;attribute name="maxNodes"&gt;5000&lt;/attribute&gt;
           &lt;/region&gt;
           &lt;region name="/test/" policyClass="org.jboss.cache.eviction.MRUPolicy"&gt;
           &lt;attribute name="maxNodes"&gt;10000&lt;/attribute&gt;
           &lt;/region&gt;
           &lt;region name="/maxAgeTest/"&gt;
           &lt;attribute name="maxNodes"&gt;10000&lt;/attribute&gt;
           &lt;attribute name="timeToLiveSeconds"&gt;8&lt;/attribute&gt;
           &lt;attribute name="maxAgeSeconds"&gt;10&lt;/attribute&gt;
           &lt;/region&gt;
           &lt;/config&gt;
           &lt;/attribute&gt;
        </programlisting>
     </section>
     <section>
        <title>Dynamic eviction policy configuration</title>
  
        <para>TreeCache now allows reconfiguration of eviction policy providers
           programatically at runtime. An example of how to reconfigure at runtime
           and how to set an LRU region to have maxNodes to 12345 timeToLiveSeconds
           to 500 and maxAgeSeconds to 1000 programatically.
        </para>
  
        <programlisting>
           // note this is just to show that a running TreeCache instance must be
           // retrieved somehow. How it is implemented is up to the implementor.
           TreeCache cache = getRunningTreeCacheInstance();
  
           org.jboss.cache.RegionManager regionManager = cache.getRegionManager();
           org.jboss.cache.Region region = regionManager.getRegion("/myRegionName", true);
           EvictionConfiguation config = region.getEvictionConfiguration();
           ((LRUConfiguration)config).setMaxNodes(12345);
           ((LRUConfiguration)config).setTimeToLiveSeconds(500);
           ((LRUConfiguration)config).setMaxAgeSeconds(1000);
        </programlisting>
  
        <para>Here is another example that shows how to insert a region at runtime:</para>
        <programlisting>
           // cache needs to be started first
           cache_.start();
  
           // region name is ignored here.
           String xml = "&lt;region name="/dummy"&gt;" +
           "&lt;attribute name="maxNodes"&gt;10000&lt;/attribute&gt;" +
           "&lt;attribute name="timeToLiveSeconds"&gt;4&lt;/attribute&gt;" +
           "&lt;/region&gt;";
           Element element = XmlHelper.stringToElement(xml);
  
           RegionManager regionManager = cache_.getEvictionRegionManager();
           // Fqn is the region name
           Integer ii = new Integer(1);
           Fqn fqn = new Fqn(ii);
           // Create region will be added to the eviction process automatically
           Region region = regionManager.createRegion(fqn, element);
        </programlisting>
        <para>Afterwards, a cache put like the following will be evicted later:</para>
        <programlisting>
           Integer ii = new Integer(1);
           Fqn rootfqn = new Fqn(ii);
           Integer in = new Integer(3);
           Fqn fqn = new Fqn(rootfqn, in);
           cache_.put(fqn, in, in);
        </programlisting>
     </section>
  
     <section>
        <title>TreeCache LRU eviction policy implementation</title>
  
        <para>TreeCache has implemented a LRU eviction policy,
           <literal>org.jboss.cache.eviction.LRUPolicy</literal>
           , that controls
           both the node lifetime and age. This policy guarantees O(n) = 1 for
           adds, removals and lookups (visits). It has the following configuration
           parameters:
        </para>
  
        <itemizedlist>
           <listitem>
              <para>
                 <literal>wakeUpIntervalSeconds</literal>
                 . This is the interval
                 (in seconds) to process the node events and also to perform sweeping
                 for the size limit and age-out nodes.
              </para>
           </listitem>
  
           <listitem>
              <para>
                 <literal>Region</literal>
                 . Region is a group of nodes that
                 possess the same eviction policy, e.g., same expired time. In
                 TreeCache, region is denoted by a fqn, e.g.,
                 <literal>/company/personnel</literal>
                 , and it is recursive. In
                 specifying the region, the order is important. For example, if
                 <literal>/org/jboss/test</literal>
                 is specified before
                 <literal>/org/jboss/test/data</literal>
                 , then any node under
                 <literal>/org/jboss/test/data</literal>
                 belongs to the first region
                 rather than the second. Note also that whenever eviction policy is
                 activated, there should always be a
                 <literal>/_default_</literal>
                 region which covers all the eviction policies not specified by the
                 user. In addition, the region configuration is not programmable,
                 i.e., all the policies have to be specified via XML
                 configuration.
                 <itemizedlist>
                    <listitem>
                       <para>
                          <literal>maxNodes</literal>
                          . This is the maximum number
                          of nodes allowed in this region. 0 denotes no limit.
                       </para>
                    </listitem>
  
                    <listitem>
                       <para>
                          <literal>timeToLiveSeconds</literal>
                          . Time to idle (in
                          seconds) before the node is swept away. 0 denotes no
                          limit.
                       </para>
                    </listitem>
  
                    <listitem>
                       <para>
                          <literal>maxAgeSeconds</literal>
                          . Time an object should
                          exist in TreeCache (in seconds) regardless of idle time before
                          the node is swept away. 0 denotes no limit.
                       </para>
                    </listitem>
                 </itemizedlist>
              </para>
           </listitem>
        </itemizedlist>
  
        <para>Please see the above section for an example.</para>
     </section>
  
     <section>
        <title>TreeCache FIFO eviction policy implementation</title>
  
        <para>TreeCache has implemented a FIFO eviction policy,
           <literal>org.jboss.cache.eviction.FIFOPolicy</literal>
           , that will
           control the eviction in a proper first in first out order. This policy
           guarantees O(n) = 1 for adds, removals and lookups (visits). It has the
           following configuration parameters:
        </para>
  
        <itemizedlist>
           <listitem>
              <para>
                 <literal>wakeUpIntervalSeconds</literal>
                 . This is the interval
                 (in seconds) to process the node events and also to perform sweeping
                 for the size limit and age-out nodes.
              </para>
           </listitem>
  
           <listitem>
              <para>
                 <literal>Region</literal>
                 . Region is a group of nodes that
                 possess the same eviction policy, e.g., same expired time. In
                 TreeCache, region is denoted by a fqn, e.g.,
                 <literal>/company/personnel</literal>
                 , and it is recursive. In
                 specifying the region, the order is important. For example, if
                 <literal>/org/jboss/test</literal>
                 is specified before
                 <literal>/org/jboss/test/data</literal>
                 , then any node under
                 <literal>/org/jboss/test/data</literal>
                 belongs to the first region
                 rather than the second. Note also that whenever eviction policy is
                 activated, there should always be a
                 <literal>/_default_</literal>
                 region which covers all the eviction policies not specified by the
                 user. In addition, the region configuration is not programmable,
                 i.e., all the policies have to be specified via XML
                 configuration.
                 <itemizedlist>
                    <listitem>
                       <para>
                          <literal>maxNodes</literal>
                          . This is the maximum number
                          of nodes allowed in this region. Any integer less than or
                          equal to 0 will throw an exception when the policy provider is
                          being configured for use.
                       </para>
                    </listitem>
                 </itemizedlist>
              </para>
           </listitem>
        </itemizedlist>
  
        <para>Please read the above section for an example.</para>
     </section>
  
     <section>
        <title>TreeCache MRU eviction policy implementation</title>
  
        <para>TreeCache has implemented a MRU eviction policy,
           <literal>org.jboss.cache.eviction.MRUPolicy</literal>
           , that will control
           the eviction in based on most recently used algorithm. The most recently
           used nodes will be the first to evict with this policy. This policy
           guarantees O(n) = 1 for adds, removals and lookups (visits). It has the
           following configuration parameters:
        </para>
  
        <itemizedlist>
           <listitem>
              <para>
                 <literal>wakeUpIntervalSeconds</literal>
                 . This is the interval
                 (in seconds) to process the node events and also to perform sweeping
                 for the size limit and age-out nodes.
              </para>
           </listitem>
  
           <listitem>
              <para>
                 <literal>Region</literal>
                 . Region is a group of nodes that
                 possess the same eviction policy, e.g., same expired time. In
                 TreeCache, region is denoted by a fqn, e.g.,
                 <literal>/company/personnel</literal>
                 , and it is recursive. In
                 specifying the region, the order is important. For example, if
                 <literal>/org/jboss/test</literal>
                 is specified before
                 <literal>/org/jboss/test/data</literal>
                 , then any node under
                 <literal>/org/jboss/test/data</literal>
                 belongs to the first region
                 rather than the second. Note also that whenever eviction policy is
                 activated, there should always be a
                 <literal>/_default_</literal>
                 region which covers all the eviction policies not specified by the
                 user. In addition, the region configuration is not programmable,
                 i.e., all the policies have to be specified via XML
                 configuration.
                 <itemizedlist>
                    <listitem>
                       <para>
                          <literal>maxNodes</literal>
                          . This is the maximum number
                          of nodes allowed in this region. Any integer less than or
                          equal to 0 will throw an exception when the policy provider is
                          being configured for use.
                       </para>
                    </listitem>
                 </itemizedlist>
              </para>
           </listitem>
        </itemizedlist>
  
        <para>Please read the above section for an example.</para>
     </section>
  
     <section>
        <title>TreeCache LFU eviction policy implementation</title>
  
        <para>TreeCache has implemented a LFU eviction policy,
           <literal>org.jboss.cache.eviction.LFUPolicy</literal>
           , that will control
           the eviction in based on least frequently used algorithm. The least
           frequently used nodes will be the first to evict with this policy. Node
           usage starts at 1 when a node is first added. Each time it is visted,
           the node usage counter increments by 1. This number is used to determine
           which nodes are least frequently used. LFU is also a sorted eviction
           algorithm. The underlying EvictionQueue implementation and algorithm is
           sorted in ascending order of the node visits counter. This class
           guarantees O(n) = 1 for adds, removal and searches. However, when any
           number of nodes are added/visited to the queue for a given processing
           pass, a single O(n) = n*log(n) operation is used to resort the queue in
           proper LFU order. Similarly if any nodes are removed or evicted, a
           single O(n) = n pruning operation is necessary to clean up the
           EvictionQueue. LFU has the following configuration parameters:
        </para>
  
        <itemizedlist>
           <listitem>
              <para>
                 <literal>wakeUpIntervalSeconds</literal>
                 . This is the interval
                 (in seconds) to process the node events and also to perform sweeping
                 for the size limit and age-out nodes.
              </para>
           </listitem>
  
           <listitem>
              <para>
                 <literal>Region</literal>
                 . Region is a group of nodes that
                 possess the same eviction policy, e.g., same expired time. In
                 TreeCache, region is denoted by a fqn, e.g.,
                 <literal>/company/personnel</literal>
                 , and it is recursive. In
                 specifying the region, the order is important. For example, if
                 <literal>/org/jboss/test</literal>
                 is specified before
                 <literal>/org/jboss/test/data</literal>
                 , then any node under
                 <literal>/org/jboss/test/data</literal>
                 belongs to the first region
                 rather than the second. Note also that whenever eviction policy is
                 activated, there should always be a
                 <literal>/_default_</literal>
                 region which covers all the eviction policies not specified by the
                 user. In addition, the region configuration is not programmable,
                 i.e., all the policies have to be specified via XML
                 configuration.
                 <itemizedlist>
                    <listitem>
                       <para>
                          <literal>maxNodes</literal>
                          . This is the maximum number
                          of nodes allowed in this region. A value of 0 for maxNodes
                          means that there is no upper bound for the configured cache
                          region.
                       </para>
                    </listitem>
  
                    <listitem>
                       <para>
                          <literal>minNodes</literal>
                          . This is the minimum number
                          of nodes allowed in this region. This value determines what
                          the eviction queue should prune down to per pass. e.g. If
                          minNodes is 10 and the cache grows to 100 nodes, the cache is
                          pruned down to the 10 most frequently used nodes when the
                          eviction timer makes a pass through the eviction
                          algorithm.
                       </para>
                    </listitem>
                 </itemizedlist>
              </para>
           </listitem>
        </itemizedlist>
  
        <para>Please read the above section for an example.</para>
     </section>
  
     <section>
        <title>TreeCache expiration eviction policy implementation</title>
  
        <para>
           TreeCache has implemented a per-node expiration and eviction
           policy,
           <literal>org.jboss.cache.eviction.ExpirationPolicy</literal>
           ,
           that evicts nodes based on an absolute expiration time. The
           expiration time is indicated using the
           <literal>org.jboss.cache.Node.put()</literal>
           method, using a key String
           <literal>expiration</literal>
           and the absolute time as a
           <literal>java.lang.Long</literal>
           object, with a value indicated as milliseconds past midnight
           January 1st, 1970 UTC (the same relative time as provided by
           <literal>java.lang.System.currentTimeMillis()</literal>
           ).
        </para>
  
        <para>
           This policy guarantees O(n) = 1 for adds and removals.
           Internally, a sorted set (TreeSet) containing the expiration
           time and FQN of the nodes is stored, which essentially
           functions as a heap.
        </para>
  
        <para>
           This policy has the following configuration parameters:
        </para>
  
        <itemizedlist>
           <listitem>
              <para>
                 <literal>wakeUpIntervalSeconds</literal>
                 . This is the interval
                 (in seconds) to process the node events and also to perform removal
                 for expired nodes and check the size limit.
              </para>
           </listitem>
  
           <listitem>
              <para>
                 <literal>expirationKeyName</literal>
                 . This is the Node key name used
                 in the eviction algorithm. The configuration default is
                 <literal>expiration</literal>
                 .
              </para>
           </listitem>
  
           <listitem>
              <para>
                 <literal>Region</literal>
                 . Region is a group of nodes that
                 possess this eviction policy.
                 <itemizedlist>
                    <listitem>
                       <para>
                          <literal>maxNodes</literal>
                          . This is the maximum number
                          of nodes allowed in this region. If the number of nodes for
                          a region exceeds this amount, then eviction will occur first for
                          the soonest to expire nodes.
                       </para>
                    </listitem>
                 </itemizedlist>
              </para>
           </listitem>
        </itemizedlist>
  
        <para>
           The following listing shows how the expiration date is indicated and how the
           policy is applied:
           <programlisting>
              Cache cache;
              Fqn fqn1 = Fqn.fromString("/node/1");
              Long future = new Long(System.currentTimeMillis() + 2000);
              cache.put(fqn1, ExpirationConfiguration.EXPIRATION_KEY, future);
              assertTrue(cache.get(fqn1) != null);
              Thread.sleep(5000);
              // after 5 seconds, expiration completes
              assertTrue(cache.get(fqn1) == null);
           </programlisting>
           Note that the expiration time of nodes is only checked when the
           region manager wakes up every
           <literal>wakeUpIntervalSeconds</literal>
           , so eviction
           may happen a few seconds later than indicated.
        </para>
     </section>
  
  </chapter>
  
  
  1.1      date: 2007/01/19 17:01:00;  author: msurtani;  state: Exp;JBossCache/docs/JBossCache-UserGuide/en/modules/compatibility.xml
  
  Index: compatibility.xml
  ===================================================================
  <chapter id="compatibility">
     <title>Version Compatibility and Interoperability</title>
  
     <para>While this is not absolutely guaranteed, generally speaking within a
        major version, releases of JBoss Cache are meant to be compatible and
        interoperable. Compatible in the sense that it should be possible to
        upgrade an application from one version to another by simply replacing the
        jars. Interoperable in the sense that if two different versions of
        JBoss Cache are used in the same cluster, they should be able to exchange
        replication and state transfer messages. Note however that interoperability
        requires use of the same JGroups version in all nodes in the cluster.
        In most cases, the version of JGroups used by a version of JBoss Cache can
        be upgraded.
     </para>
  
     <para>In the 1.2.4 and 1.2.4.SP1 releases, API compatibility and
        interoperability with previous releases was broken. The primary purpose
        of the 1.2.4.SP2 release was to restore API compatibility and
        interoperability. Note, however, that restoring API compatibility with
        earlier releases meant that 1.2.4.SP2 is not completely API compatible with
        the other two 1.2.4 releases. If you have built applications on top of
        1.2.4 or 1.2.4.SP1, please recompile before upgrading to 1.2.4.SP2 in
        order to be sure you have no issues.
     </para>
  
     <para>Beginning in 1.2.4.SP2, a new configuration attribute
        <literal>ReplicationVersion</literal>
        has been added. This attribute needs to be set in
        order to allow interoperability with previous releases. The value should
        be set to the release name of the version with which interoperability is
        desired, e.g. "1.2.3". If this attribute is set, the wire format of
        replication and state transfer messages will conform to that understood
        by the indicated release. This mechanism allows us to improve JBoss Cache by
        using more efficient wire formats while still providing a means to preserve
        interoperability.
     </para>
  
     <para>In a rare usage scenario, multiple different JBoss Cache instances may
        be operating on each node in a cluster, but not all need to interoperate
        with a version 1.2.3 cache, and thus some caches will not be configured
        with
        <literal>ReplicationVersion</literal>
        set to 1.2.3. This can cause problems with
        serialization of Fqn objects. If you are using this kind of configuration,
        are having problems and are unwilling to set
        <literal>ReplicationVersion</literal>
        to
        <literal>1.2.3</literal>
        on all caches, a workaround is to set system property
        <literal>jboss.cache.fqn.123compatible</literal>
        to
        <literal>true</literal>
        .
     </para>
  
  </chapter>
  
  
  1.1      date: 2007/01/19 17:01:00;  author: msurtani;  state: Exp;JBossCache/docs/JBossCache-UserGuide/en/modules/treecache_marshaller.xml
  
  Index: treecache_marshaller.xml
  ===================================================================
  <chapter id="treecache_marshaller">
     <title>TreeCacheMarshaller</title>
  
     <para>
        Rather than using standard Java serialization to serialize
        <literal>java.lang.reflect.Method</literal>
        objects and their parameters when remote caches talk to each other to replicate data, JBoss Cache uses
        its own mechanism to marshall and unmarshall data called the
        <literal>TreeCacheMarshaller</literal>
        .
     </para>
     <para>In addition to providing the performance and efficiency enhancements over standard Java serialization,
        The
        <literal>TreeCacheMarshaller</literal>
        also performs one other function. In order to deserialize an
        object replicated to it from a remote
        cache, a cache instance needs to have access to the classloader that
        defines the object's class. This is simple if the cache's own
        classloader can access the required classes, but for situations where
        JBoss Cache is used as a service supporting clients that use different
        classloaders, the
        <literal>TreeCacheMarshaller</literal>
        can be configured to use different classloaders
        on a per-region basis by allowing application code to
        register a classloader that should be used to handle replication for a
        portion of the tree.
     </para>
  
     <section>
        <title>Basic Usage</title>
  
        <para>
           <literal>TreeCache</literal>
           exposes the following basic API for
           controlling the behavior of
           <literal>TreeCacheMarshaller</literal>
           :
        </para>
  
        <programlisting>
           /**
           * Sets whether marshalling uses scoped class loaders on a per region basis.
           *
           * This property must be set to true before any call to
           * {@link #registerClassLoader(String, ClassLoader)} or
           * {@link #activateRegion(String)}
           *
           * @param isTrue
           */
           void setUseRegionBasedMarshalling(boolean isTrue);
  
           /**
           * Gets whether marshalling uses scoped class loaders on a per region basis.
           */
           boolean getUseRegionBasedMarshalling();
  
           /**
           * Registers the given classloader with
           <code>TreeCacheMarshaller</code>
           for
           * use in unmarshalling replicated objects for the specified region.
           *
           * @param fqn The fqn region. This fqn and its children will use this classloader for (un)marshalling.
           * @param cl The class loader to use
           *
           * @throws RegionNameConflictException if
           <code>fqn</code>
           is a descendant of
           * an FQN that already has a classloader
           * registered.
           * @throws IllegalStateException if
           <code>useMarshalling</code>
           is
           <code>false</code>
           */
           void registerClassLoader(String fqn, ClassLoader cl) throws RegionNameConflictException;
  
           /**
           * Instructs the
           <code>TreeCacheMarshaller</code>
           to no longer use a special
           * classloader to unmarshal replicated objects for the specified region.
           *
           * @param fqn The fqn of the root node of region.
           *
           * @throws RegionNotFoundException if no classloader has been registered for
           *
           <code>fqn</code>
           .
           * @throws IllegalStateException if
           <code>useMarshalling</code>
           is
           <code>false</code>
           */
           void unregisterClassLoader(String fqn) throws RegionNotFoundException;
        </programlisting>
  
        <para>Property
           <literal>UseRegionBasedMarshalling</literal>
           controls whether
           classloader-based marshalling should be used. This property should be
           set as part of normal cache configuration, typically in the cache's XML
           configuration file:
        </para>
  
        <programlisting>&lt;attribute name="UseRegionBasedMarshalling"&gt;true&lt;/attribute&gt;</programlisting>
  
        <para>Anytime after
           <literal>UseRegionBasedMarshalling</literal>
           is set to
           <literal>true</literal>
           , the application code can call
           <literal>registerClassLoader</literal>
           to associate a classloader with
           the portion of the cache rooted in a particular FQN. Once registered,
           the classloader will be used to unmarshal any replication traffic
           related to the node identified by the FQN or to any of its
           descendants.
        </para>
  
        <para>At this time,
           <literal>registerClassLoader</literal>
           only supports
           String-based FQNs.
        </para>
  
        <para>Note that it is illegal to register a classloader for an FQN that
           is a descendant of an FQN for which a classloader has already been
           registered. For example, if classloader
           <literal>X</literal>
           is
           registered for FQN
           <literal>/a</literal>
           , a
           <literal>RegionNameConflictException</literal>
           will be thrown if an
           attempt is made to register classloader
           <literal>Y</literal>
           for FQN
           <literal>/a/b</literal>
           .
        </para>
  
        <para>Method
           <literal>unregisterClassLoader</literal>
           is used to remove
           the association between a classloader and a particular cache region. Be
           sure to call this method when you are done using the cache with a
           particular classloader, or a reference to the classloader will be held,
           causing a memory leak!
        </para>
     </section>
  
     <section>
        <title>Region Activation/Inactivation</title>
  
        <para>The basic API discussed above is helpful, but in situations where
           applications with different classloaders are sharing a cache, the
           lifecycle of those applications will typically be different from that of
           the cache. The result of this is that it is difficult or impossible to
           register all required classloaders before a cache is started. For
           example, consider the following scenario:
        </para>
  
        <orderedlist>
           <listitem>TreeCache on machine A starts.</listitem>
  
           <listitem>On A a classloader is registered under FQN /x.</listitem>
  
           <listitem>Machine B starts, so TreeCache on B starts.</listitem>
  
           <listitem>An object is put in the machine A cache under FQN
              /x/1.
           </listitem>
  
           <listitem>Replication to B fails, as the required classloader is not
              yet registered.
           </listitem>
  
           <listitem>On B a classloader is registered under FQN /x, but too late
              to prevent the replication error.
           </listitem>
        </orderedlist>
  
        <para>Furthermore, if any objects had been added to server A before
           server B was started, the initial transfer of state from A to B would
           have failed as well, as B would not be able to unmarshal the transferred
           objects.
        </para>
  
        <para>To resolve this problem, if region-based marshalling is used a cache
           instance can be configured to ignore replication events for a portion of
           the tree. That portion of the tree is considered "inactive". After the
           needed classloader has been registered, the portion of the tree can be
           "activated". Activation causes the following events to occur:
        </para>
  
        <itemizedlist>
           <listitem>Any existing state for that portion of the tree is
              transferred from another node in the cluster and integrated into the
              local tree.
           </listitem>
  
           <listitem>TreeCacheMarshaller begins normal handling of replication
              traffic related to the portion of the tree.
           </listitem>
        </itemizedlist>
  
        <para>In addition to the basic marshalling related API discussed above,
           TreeCache exposes the following API related to activating and
           inactivating portions of the cache:
        </para>
  
        <programlisting>
           /**
           * Sets whether the entire tree is inactive upon startup, only responding
           * to replication messages after {@link #activateRegion(String)} is
           * called to activate one or more parts of the tree.
           * &lt;p&gt;
           * This property is only relevant if {@link #getUseRegionBasedMarshalling()} is
           *
           <code>true</code>
           .
           *
           */
           public void setInactiveOnStartup(boolean inactiveOnStartup);
  
           /**
           * Gets whether the entire tree is inactive upon startup, only responding
           * to replication messages after {@link #activateRegion(String)} is
           * called to activate one or more parts of the tree.
           * &lt;p&gt;
           * This property is only relevant if {@link #getUseRegionBasedMarshalling()} is
           *
           <code>true</code>
           .
           */
           public boolean isInactiveOnStartup();
  
           /**
           * Causes the cache to transfer state for the subtree rooted at
           *
           <code>subtreeFqn</code>
           and to begin accepting replication messages
           * for that subtree.
           * &lt;p&gt;
           * &lt;strong&gt;NOTE:&lt;/strong&gt; This method will cause the creation of a node
           * in the local tree at
           <code>subtreeFqn</code>
           whether or not that
           * node exists anywhere else in the cluster. If the node does not exist
           * elsewhere, the local node will be empty. The creation of this node will
           * not be replicated.
           *
           * @param subtreeFqn Fqn string indicating the uppermost node in the
           * portion of the tree that should be activated.
           *
           * @throws RegionNotEmptyException if the node
           <code>subtreeFqn</code>
           * exists and has either data or children
           *
           * @throws IllegalStateException
           * if {@link #getUseRegionBasedMarshalling() useRegionBasedMarshalling} is
           <code>false</code>
           */
           public void activateRegion(String subtreeFqn)
           throws RegionNotEmptyException, RegionNameConflictException, CacheException;
  
           /**
           * Causes the cache to stop accepting replication events for the subtree
           * rooted at
           <code>subtreeFqn</code>
           and evict all nodes in that subtree.
           *
           * @param subtreeFqn Fqn string indicating the uppermost node in the
           * portion of the tree that should be activated.
           * @throws RegionNameConflictException if
           <code>subtreeFqn</code>
           indicates
           * a node that is part of another
           * subtree that is being specially
           * managed (either by activate/inactiveRegion()
           * or by registerClassLoader())
           * @throws CacheException if there is a problem evicting nodes
           *
           * @throws IllegalStateException
           * if {@link #getUseRegionBasedMarshalling() useRegionBasedMarshalling} is
           <code>false</code>
           */
           public void inactivateRegion(String subtreeFqn) throws RegionNameConflictException, CacheException;
        </programlisting>
  
        <para>Property
           <literal>InactiveOnStartup</literal>
           controls whether the
           entire cache should be considered inactive when the cache starts. In
           most use cases where region activation is needed, this property would be
           set to true. This property should be set as part of normal cache
           configuration, typically in the cache's XML configuration file:
        </para>
  
        <programlisting>&lt;attribute name="InactiveOnStartup"&gt;true&lt;/attribute&gt;</programlisting>
  
        <para>When
           <literal>InactiveOnStartup</literal>
           is set to true, no state
           transfer will be performed on startup, even if property
           <literal>FetchInMemoryState</literal>
           is true.
        </para>
  
        <para>When
           <literal>activateRegion()</literal>
           is invoked, each node in
           the cluster will be queried to see if it has active state for that
           portion of the tree. If one does, it will return the current state,
           which will then be integrated into the tree. Once state is transferred
           from one node, no other nodes will be asked for state. This process is
           somewhat different from the initial state transfer process that occurs
           at startup when property
           <literal>FetchInMemoryState</literal>
           is set to
           true. During initial state transfer, only the oldest member of the
           cluster is queried for state. This approach is inadequate for region
           activation, as it is possible that the oldest member of the cluster also
           has the region inactivated, and thus cannot provide state. So, each node
           in the cluster is queried until one provides state.
        </para>
  
        <para>Before requesting state from other nodes,
           <literal>activateRegion()</literal>
           will confirm that there is no
           existing data in the portion of the tree being activated. If there is
           any, a
           <literal>RegionNotEmptyException</literal>
           will be thrown.
        </para>
  
        <para>It is important to understand that when a region of the tree is
           marked as inactive, this only means replication traffic from other
           cluster nodes related to that portion of the tree will be ignored. It is
           still technically possible for objects to be placed in the inactive
           portion of the tree locally (via a
           <literal>put</literal>
           call), and any
           such local activity will be replicated to other nodes. TreeCache will
           not prevent this kind of local activity on an inactive region, but, as
           discussed above
           <literal>activateRegion()</literal>
           will throw an
           exception if it discovers data in a region that is being
           activated.
        </para>
  
        <section>
           <title>Example usage of Region Activation/Inactivation</title>
  
           <para>As an example of the usage of region activation and
              inactivation, let's imagine a scenario where a TreeCache instance is
              deployed as a shared MBean service by deploying a
              <literal>-service.xml</literal>
              in the JBoss
              <literal>/deploy</literal>
              directory. One of the users of this cache
              could be a web application, which when started will register its
              classloader with the TreeCache and activate its own region of the
              cache.
           </para>
  
           <para>First, the XML configuration file for the shared cache service
              would be configured as follows (only relevant portions are
              shown):
           </para>
  
           <programlisting>
              &lt;?xml version="1.0" encoding="UTF-8" ?&gt;
              &lt;server&gt;
              &lt;classpath codebase="./lib" archives="jboss-cache.jar, jgroups.jar" /&gt;
  
              &lt;!-- ==================================================================== --&gt;
              &lt;!-- Defines TreeCache configuration --&gt;
              &lt;!-- ==================================================================== --&gt;
              &lt;mbean code="org.jboss.cache.TreeCache" name="com.xyz.cache:service=SharedCache"&gt;
  
              .......
  
              &lt;!-- Configure Marshalling --&gt;
              &lt;attribute name="getUseRegionBasedMarshalling"&gt;true&lt;/attribute&gt;
              &lt;attribute name="InactiveOnStartup"&gt;true&lt;/attribute&gt;
  
              ........
  
              &lt;/mbean&gt;
              &lt;/server&gt;
           </programlisting>
  
           <para>For the webapp, registering/unregistering the classloader and
              activating/inactivating the app's region in the cache are tasks that
              should be done as part of initialization and destruction of the app.
              So, using a
              <literal>ServletContextListener</literal>
              to manage these
              tasks seems logical. Following is an example listener:
           </para>
  
           <programlisting>
              package example;
  
              import javax.management.MalformedObjectNameException;
              import javax.management.ObjectName;
              import javax.servlet.ServletContextEvent;
              import javax.servlet.ServletContextListener;
  
              import org.jboss.cache.TreeCacheMBean;
              import org.jboss.mx.util.MBeanProxyExt;
  
              public class ActiveInactiveRegionExample implements ServletContextListener
              {
              private TreeCacheMBean cache;
  
              public void contextInitialized(ServletContextEvent arg0) {
              try {
              findCache();
  
              cache.registerClassLoader("/example", Thread.currentThread().getContextClassLoader());
              cache.activeRegion("/example");
              }
              catch (Exception e) {
              // ... handle exception
              }
  
              }
  
              public void contextDestroyed(ServletContextEvent arg0) {
              cache.inactivateRegion("/example");
              cache.unregisterClassLoader("/example");
              }
  
              private void findCache() throws MalformedObjectNameException {
              // Find the shared cache service in JMX and create a proxy to it
              ObjectName cacheServiceName_ = new ObjectName("com.xyz.cache:service=SharedCache");
              // Create Proxy-Object for this service
              cache = (TreeCacheMBean) MBeanProxyExt.create(TreeCacheMBean.class, cacheServiceName_);
              }
              }
           </programlisting>
  
           <para>The listener makes use of the JBoss utility class
              <literal>MBeanProxyExt</literal>
              to find the TreeCache in JMX and
              create a proxy to it. (See the "Running and using TreeCache inside
              JBoss" section below for more on accessing a TreeCache). It then
              registers its classloader with the cache and activates its region.
              When the webapp is being destroyed, it inactivates its region and
              unregisters its classloader (thus ensuring that the classloader isn't
              leaked via a reference to it held by TreeCacheMarshaller).
           </para>
  
           <para>Note the order of the method calls in the example class --
              register a classloader before activating a region, and inactivate the
              region before unregistering the classloader.
           </para>
        </section>
     </section>
  
     <section>
        <title>Region Activation/Inactivation with a CacheLoader</title>
  
        <para>The activateRegion()/inactivateRegion() API can be used in
           conjunction with a CacheLoader as well, but only if the cache loader
           implementation implements interface
           <literal>org.jboss.cache.loader.ExtendedCacheLoader</literal>
           . This is a
           subinterface of the normal
           <literal>CacheLoader</literal>
           interface. It
           additionally specifies the following methods needed to support the
           partial state transfer that occurs when a region is activated:
        </para>
  
        <programlisting>
           /**
           * Fetch a portion of the state for this cache from secondary storage
           * (disk, DB) and return it as a byte buffer.
           * This is for activation of a portion of new cache from a remote cache.
           * The new cache would then call {@link #storeState(byte[], Fqn)}.
           *
           * @param subtree Fqn naming the root (i.e. highest level parent) node of
           * the subtree for which state is requested.
           *
           * @see org.jboss.cache.TreeCache#activateRegion(String)
           */
           byte[] loadState(Fqn subtree) throws Exception;
  
           /**
           * Store the given portion of the cache tree's state in secondary storage.
           * Overwrite whatever is currently in secondary storage.
           *
           * @param state the state to store
           * @param subtree Fqn naming the root (i.e. highest level parent) node of
           * the subtree included in
           <code>state</code>
           .
           */
           void storeState(byte[] state, Fqn subtree) throws Exception;
  
           /**
           * Sets the {@link RegionManager} this object should use to manage
           * marshalling/unmarshalling of different regions using different
           * classloaders.
           * &lt;p&gt;
           * &lt;strong&gt;NOTE:&lt;/strong&gt; This method is only intended to be used
           * by the
           <code>TreeCache</code>
           instance this cache loader is
           * associated with.
           * &lt;/p&gt;
           *
           * @param manager the region manager to use, or
           <code>null</code>
           .
           */
           void setRegionManager(RegionManager manager);
        </programlisting>
  
        <para>JBossCache currently comes with two implementations of
           ExtendedCacheLoader,
           <literal>FileExtendedCacheLoader</literal>
           and
           <literal>JDBCExtendedCacheLoader</literal>
           . These classes extend
           FileCacheLoader and JDBCCacheLoader, respectively, implementing the
           extra methods in the extended interface.
        </para>
     </section>
     <section>
        <title>Performance over Java serialization</title>
        <para>
           To achieve the performance and efficiency gains, the
           <literal>TreeCacheMarshaller</literal>
           uses a number of techniques
           including method ids for known methods and magic numbers for known internal class types which drastically
           reduces
           the size of calls to remote caches, greatly improving throughput and reducing the overhead of Java
           serialization.
        </para>
        <para>
           To make things even faster, the
           <literal>TreeCacheMarshaller</literal>
           uses
           <ulink url="http://labs.jboss.org/portal/index.html?ctrl:id=page.default.info&amp;project=serialization">JBoss
              Serialization
           </ulink>
           ,
           a highly efficient drop-in replacement for Java serialization for user-defined classes. JBoss Serialization is
           enabled and always used
           by default, although this can be disabled, causing the marshalling of user-defined classes to revert to Java
           serialization. JBoss Serialization
           is disabled by passing in the
           <literal>-Dserialization.jboss=false</literal>
           environment variable into your JVM.
        </para>
     </section>
  
     <section>
        <title>Backward compatibility</title>
        <para>
           Marshalling in JBoss Cache is now versioned. All communications between caches contain a version
           <literal>short</literal>
           which allows JBoss Cache instances of different versions to communicate with each other. Up until JBoss Cache
           1.4.0, all versions were able to communicate with each other anyway since they all used simple serialization of
           <literal>org.jgroups.MethodCall</literal>
           objects, provided they all used the same version of JGroups. This requirement (more a requirement of the
           JGroups messaging layer than JBoss Cache) still exists, even though with JBoss Cache 1.4.0, we've moved to a
           much more efficient and sophisticated marshalling mechanism.
        </para>
        <para>
           JBoss Cache 1.4.0 and future releases of JBoss Cache will always be able to unmarshall data from previous
           versions of JBoss Cache. For JBoss Cache 1.4.0 and future releases to marshall data in a format that is
           compatible with older versions, however, you would have to start JBoss Cache with the following configuration
           attribute:
           <programlisting><![CDATA[
  				<!-- takes values such as 1.2.3, 1.2.4 and 1.3.0 -->
  				<attribute name="ReplicationVersion">1.2.4</attribute>
  				]]>
           </programlisting>
        </para>
     </section>
  </chapter>
  
  
  1.1      date: 2007/01/19 17:01:00;  author: msurtani;  state: Exp;JBossCache/docs/JBossCache-UserGuide/en/modules/architecture.xml
  
  Index: architecture.xml
  ===================================================================
  <chapter id="architecture">
     <title>Architecture</title>
  
     <figure>
        <title>Schematic TreeCache architecture</title>
  
        <mediaobject>
           <imageobject>
              <imagedata fileref="images/TreeCacheArchitecture.gif"/>
           </imageobject>
        </mediaobject>
     </figure>
  
     <para>The architecture is shown above. The example shows 2 Java VMs, each
        has created an instance of
        <literal>TreeCache</literal>
        . These VMs can be located on the same
        machine, or on 2 different machines. The setup of the underlying group
        communication subsystem is done using
        <ulink url="http://www.jgroups.org">JGroups</ulink>
        .
     </para>
  
     <para>Any modification (see API below) in one cache will be replicated to
        the other cache
        <footnote>
           <para>Note that you can have more than 2 caches in a cluster.</para>
        </footnote>
        and vice versa. Depending on the transactional settings, this replication will occur either after each
        modification or at the end of a transaction (at commit
        time). When a new cache is created, it can optionally acquire the contents
        from one of the existing caches on startup.
     </para>
  
  </chapter>
  
  
  1.1      date: 2007/01/19 17:01:00;  author: msurtani;  state: Exp;JBossCache/docs/JBossCache-UserGuide/en/modules/jboss_integration.xml
  
  Index: jboss_integration.xml
  ===================================================================
  <chapter id="jboss_integration">
     <title>Running JBoss Cache within JBoss Application Server</title>
  
     <para>If JBoss Cache is run in JBoss AS then JBoss Cache can be deployed as an
        MBean. The steps below illustrate how to do this. We do not deploy JBoss Cache as a
        Service Archive (SAR), but as a JAR (
        <literal>jboss-cache.jar</literal>
        in the lib directory) and
        an XML file defining the MBean. Of course, JBoss Cache can also be
        deployed as a SAR, or even as part of a WAR, EJB or EAR.
     </para>
  
     <para>First, the
        <literal>jboss-cache.jar</literal>
        file has to be copied to the /lib
        directory and JBoss AS has to be restarted. Then a regular JBoss Cache
        configuration file in XML format has to be copied to the /deploy
        directory. The XML file format is the same as discussed in
        the Configuration chapter.
     </para>
  
     <para>In order to be used from a client such as a servlet in the Tomcat web
        container inside the same JBoss container, JMX can be used:
     </para>
  
     <programlisting>MBeanServer server=MBeanServerLocator.locateJBoss();
        TreeCacheMBean cache;
        cache=(TreeCacheMBean)MBeanProxyExt.create(TreeCacheMBean.class, "jboss.cache:service=TreeCache", server);
        cache.put("/a/b/c", null);
     </programlisting>
  
     <para>The MBeanServerLocator class is a helper to find the (only) JBoss
        MBean server inside the current VM. The static create() method creates a
        dynamic proxy to the given interface and uses JMX to dynamically dispatch
        methods invoked against the generated interface. The name used to look up
        the MBean is the same as defined in the configuration file.
     </para>
  
     <section>
        <title>Running as an MBean</title>
        <para>If JBoss Cache is run inside of JBoss AS (as an MBean), we can bind it
           into JNDI using JrmpProxyFactory, just like any other MBean. Below is an
           example of how to do this:
           <programlisting> &lt;mbean
              code="org.jboss.invocation.jrmp.server.JRMPProxyFactory"
              name="mydomain:service=proxyFactory,type=jrmp,target=factory"&gt;
              &lt;attribute
              name="InvokerName"&gt;jboss:service=invoker,type=jrmp&lt;/attribute&gt;
              &lt;attribute
              name="TargetName"&gt;jboss.cache:service=TreeCache&lt;/attribute&gt;
              &lt;attribute name="JndiName"&gt;MyCache&lt;/attribute&gt; &lt;attribute
              name="InvokeTargetMethod"&gt;true&lt;/attribute&gt; &lt;attribute
              name="ExportedInterface"&gt;org.jboss.cache.TreeCacheMBean&lt;/attribute&gt;
              &lt;attribute name="ClientInterceptors"&gt; &lt;iterceptors&gt;
              &lt;interceptor&gt;org.jboss.proxy.ClientMethodInterceptor&lt;/interceptor&gt;
              &lt;interceptor&gt;org.jboss.proxy.SecurityInterceptor&lt;/interceptor&gt;
              &lt;interceptor&gt;org.jboss.invocation.InvokerInterceptor&lt;/interceptor&gt;
              &lt;/iterceptors&gt; &lt;/attribute&gt;
              &lt;depends&gt;jboss:service=invoker,type=jrmp&lt;/depends&gt;
              &lt;depends&gt;jboss.cache:service=TreeCache&lt;/depends&gt;
              &lt;/mbean&gt; </programlisting>
        </para>
  
        <para>The
           <literal>InvokerName</literal>
           attribute needs to point to a
           valid JBoss invoker MBean.
           <literal>TargetName</literal>
           is the JMX name
           of the MBean that needs to be bound into JNDI.
           <literal>JndiName</literal>
           is the name under which the MBean will be
           bound, and
           <literal>ExportedInterface</literal>
           is the interface name of
           the MBean.
        </para>
     </section>
  </chapter>
  
  
  1.1      date: 2007/01/19 17:01:00;  author: msurtani;  state: Exp;JBossCache/docs/JBossCache-UserGuide/en/modules/replication.xml
  
  Index: replication.xml
  ===================================================================
  <chapter id="replication">
     <title>Clustered Caches</title>
  
     <para>The
        <literal>TreeCache</literal>
        can be configured to be either local (standalone) or clustered. If
        in a cluster, the cache can be configured to replicate changes, or to
        invalidate changes. A detailed discussion on this follows.
     </para>
  
     <section>
        <title>Local Cache</title>
  
        <para>Local caches don't join a cluster and don't communicate with other
           nodes in a cluster. Therefore their elements don't need to be
           serializable - however, we recommend making them serializable, enabling a
           user to change the cache mode at any time.
        </para>
     </section>
  
     <section>
        <title>Clustered Cache - Using Replication</title>
  
        <para>Replicated caches replicate all changes to the
           other
           <literal>TreeCache</literal>
           instances in the cluster. Replication can either happen
           after each modification (no transactions), or at the end of a
           transaction (commit time).
        </para>
  
        <para>Replication can be synchronous or asynchronous . Use of either one
           of the options is application dependent. Synchronous replication blocks
           the caller (e.g. on a put()) until the modifications have been
           replicated successfully to all nodes in a cluster. Asynchronous
           replication performs replication in the background (the put() returns
           immediately).
           <literal>TreeCache</literal>
           also offers a replication queue, where
           modifications are replicated periodically (i.e. interval-based), or when
           the queue size exceeds a number of elements, or a combination
           thereof.
        </para>
  
        <para>Asynchronous replication is faster (no caller blocking), because
           synchronous replication requires acknowledgments from all nodes in a
           cluster that they received and applied the modification successfully
           (round-trip time). However, when a synchronous replication returns
           successfully, the caller knows for sure that all modifications have been
           applied at all nodes, whereas this may or may not be the case with
           asynchronous replication. With asynchronous replication, errors are
           simply written to a log. Even when using transactions, a transaction may succeed but replication may not
           succeed on all
           <literal>TreeCache</literal>
           instances.
        </para>
  
        <section>
           <title>Replicated Caches and Transactions</title>
           <para>
              When using transactions, replication only occurs at the transaction boundary - i.e., when a transaction
              commits.
              This results in minimising replication traffic since a single modification os broadcast rather than a series
              of
              individual modifications, and can be a lot more efficient than not using transactions. Another effect of
              this
              is that if a transaction were to roll back, nothing is broadcast across a cluster.
           </para>
           <para>
              Depending on whether you are running your cluster in asynchronous or synchronous mode, JBoss Cache will use
              either a single phase or
              <ulink url="http://en.wikipedia.org/wiki/Two-phase_commit_protocol">two phase commit</ulink>
              protocol, respectively.
           </para>
           <section>
              <title>One Phase Commits</title>
              <para>
                 Used when your cache mode is REPL_ASYNC. All modifications are replicated in a single call, which
                 instructs
                 remote caches to apply the changes to their local in-memory state and commit locally. Remote
                 errors/rollbacks are never fed back to the originator of the transaction since the communication is
                 asynchronous.
              </para>
           </section>
           <section>
              <title>Two Phase Commits</title>
              <para>
                 Used when your cache mode is REPL_SYNC. Upon committing your transaction, JBoss Cache broadcasts a
                 prepare call,
                 which carries all modifications relevant to the transaction. Remote caches then acquire local locks on
                 their
                 im-memory state and apply the modifications. Once all remote caches respond to the prepare call, the
                 originator of the transaction broadcasts a commit. This instructs all remote caches to commit their data.
                 If any of the caches fail to respond to the prepare phase, the originator broadcasts a rollback.
              </para>
              <para>
                 Note that although the prepare phase is synchronous, the commit and rollback phases are asynchronous.
                 This
                 is because
                 <ulink url="http://java.sun.com/products/jta/">Sun's JTA specification</ulink>
                 does not specify how transactional resources should deal with failures
                 at this stage of a transaction; and other resources participating in the transaction may have
                 indeterminate
                 state anyway. As such, we do away with the overhead of synchronous communication for this phase of the
                 transaction. That said, they can be forced to be synchronous using the
                 <literal>SyncCommitPhase</literal>
                 and
                 <literal>SyncRollbackPhase</literal>
                 configuration options.
              </para>
           </section>
  
        </section>
  
        <section>
           <title>Buddy Replication</title>
           <para>
              Buddy Replication allows you to suppress replicating your data to all instances in a cluster. Instead,
              each instance picks one or more 'buddies' in the cluster, and only replicates to these specific buddies.
              This greatly helps scalability as there is no longer a memory and network traffic impact every time another
              instance is added to a cluster.
           </para>
           <para>
              One of the most common use cases of Buddy Replication is when a replicated cache is used by a servlet
              container to store HTTP session data. One of the pre-requisites to buddy replication working well and being
              a real benefit is the use of
              <emphasis>session affinity</emphasis>
              , also known as
              <emphasis>sticky sessions</emphasis>
              in HTTP session replication speak. What this means is that if certain data is frequently accessed, it is
              desirable that this is always accessed on one instance rather than in a round-robin fashion as this helps
              the cache cluster optimise how it chooses buddies, where it stores data, and minimises replication traffic.
           </para>
           <para>
              If this is not possible, Buddy Replication may prove to be more of an overhead than a benefit.
           </para>
           <section>
              <title>Selecting Buddies</title>
              <para>
                 Buddy Replication uses an instance of a
                 <literal>org.jboss.cache.buddyreplication.BuddyLocator</literal>
                 which contains the logic used to select buddies in a network. JBoss Cache currently ships with a single
                 implementation,
                 <literal>org.jboss.cache.buddyreplication.NextMemberBuddyLocator</literal>
                 , which is used
                 as a default if no implementation is provided. The
                 <literal>NextMemberBuddyLocator</literal>
                 selects the
                 next member in the cluster, as the name suggests, and guarantees an even spread of buddies for each
                 instance.
              </para>
              <para>
                 The
                 <literal>NextMemberBuddyLocator</literal>
                 takes in 2 parameters, both optional.
                 <itemizedlist>
                    <listitem>
                       <literal>numBuddies</literal>
                       - specifies how many buddies each instance should pick to back its data onto. This defaults to 1.
                    </listitem>
                    <listitem>
                       <literal>ignoreColocatedBuddies</literal>
                       - means that
                       each instance will
                       <emphasis>try</emphasis>
                       to select a buddy on a different physical host. If not able to do so though,
                       it will fall back to colocated instances. This defaults to
                       <literal>true</literal>
                       .
                    </listitem>
                 </itemizedlist>
              </para>
           </section>
           <section>
              <title>BuddyPools</title>
              <para>
                 Also known as replication groups, a buddy pool is an optional construct where each instance in a cluster
                 may be configured with a buddy pool name. Think of this as an 'exclusive club membership' where when
                 selecting buddies,
                 <literal>BuddyLocator</literal>
                 s would try and select buddies sharing the same
                 buddy pool name. This allows system administrators a degree of flexibility and control over how buddies
                 are selected. For example, a sysadmin may put two instances on two separate physical servers that
                 may be on two separate physical racks in the same buddy pool. So rather than picking an
                 instance on a different host on the same rack,
                 <literal>BuddyLocator</literal>
                 s would rather pick
                 the instance in the same buddy pool, on a separate rack which may add a degree of redundancy.
              </para>
           </section>
           <section>
              <title>Failover</title>
              <para>
                 In the unfortunate event of an instance crashing, it is assumed that the client connecting to the
                 cache (directly or indirectly, via some other service such as HTTP session replication) is able to
                 redirect the request to any other random cache instance in the cluster. This is where a concept of
                 Data Gravitation comes in.
              </para>
              <para>
                 Data Gravitation is a concept where if a request is made on a cache in the cluster and the cache does
                 not contain this information, it then asks other instances in the cluster for the data. If even this
                 fails, it would (optionally) ask other instances to check in the backup data they store for other caches.
                 This means that even if a cache containing your session dies, other instances will still be able
                 to access this data by asking the cluster to search through their backups for this data.
              </para>
              <para>
                 Once located, this data is then transferred to the instance which requested it and is added to this
                 instance's data tree. It is then (optionally) removed from all other instances (and backups) so
                 that if session affinity is used, the affinity should now be to this new cache instance which has
                 just
                 <emphasis>taken ownership</emphasis>
                 of this data.
              </para>
              <para>
                 Data Gravitation is implemented as an interceptor. The following (all optional) configuration properties
                 pertain to data gravitation.
                 <itemizedlist>
                    <listitem>
                       <literal>dataGravitationRemoveOnFind</literal>
                       - forces all remote caches that own the data or hold backups for the data to remove that data,
                       thereby making the requesting cache the new data owner. If set to
                       <literal>false</literal>
                       an evict is broadcast instead of a remove, so any state
                       persisted in cache loaders will remain. This is useful if you have a shared cache loader
                       configured. Defaults to
                       <literal>true</literal>
                       .
                    </listitem>
                    <listitem>
                       <literal>dataGravitationSearchBackupTrees</literal>
                       - Asks remote instances to search through their backups as well as main data trees. Defaults to
                       <literal>true</literal>
                       . The resulting effect is that if this is
                       <literal>true</literal>
                       then backup nodes can respond to data gravitation requests in addition to data owners.
                    </listitem>
                    <listitem>
                       <literal>autoDataGravitation</literal>
                       - Whether data gravitation occurs for every cache miss. My default this is set to
                       <literal>false</literal>
                       to prevent unnecessary network calls. Most use cases will know when it may need to gravitate data
                       and will pass in an
                       <literal>Option</literal>
                       to enable data gravitation on a per-invocation basis. If
                       <literal>autoDataGravitation</literal>
                       is
                       <literal>true</literal>
                       this
                       <literal>Option</literal>
                       is unnecessary.
                    </listitem>
                 </itemizedlist>
              </para>
           </section>
           <section>
              <title>Implementation</title>
              <para>
                 <figure>
                    <title>Class diagram of the classes involved in buddy replication and how they are related to each
                       other
                    </title>
  
                    <mediaobject>
                       <imageobject>
                          <imagedata fileref="images/PackageOverview-BuddyReplication.png"/>
                       </imageobject>
                    </mediaobject>
                 </figure>
              </para>
  
           </section>
           <section>
              <title>Configuration</title>
              <para>
                 <programlisting><![CDATA[
                      <!-- Buddy Replication config -->
                      <attribute name="BuddyReplicationConfig">
                          <config>
  
  							<!-- Enables buddy replication.  This is the ONLY mandatory configuration element here. -->
                              <buddyReplicationEnabled>true</buddyReplicationEnabled>
  
  							<!-- These are the default values anyway -->
                              <buddyLocatorClass>org.jboss.cache.buddyreplication.NextMemberBuddyLocator</buddyLocatorClass>
  
  							<!-- numBuddies is the number of backup nodes each node maintains.  ignoreColocatedBuddies means that
                                  each node will *try* to select a buddy on a different physical host.  If not able to do so though,
                                  it will fall back to colocated nodes. -->
                              <buddyLocatorProperties>
                                  numBuddies = 1
                                  ignoreColocatedBuddies = true
                              </buddyLocatorProperties>
  
  							<!-- A way to specify a preferred replication group.  If specified, we try and pick a buddy why shares
                              the same pool name (falling back to other buddies if not available).  This allows the sysdmin to hint at
                              backup buddies are picked, so for example, nodes may be hinted topick buddies on a different physical rack
                              or power supply for added fault tolerance.  -->
                              <buddyPoolName>myBuddyPoolReplicationGroup</buddyPoolName>
  
  							<!-- Communication timeout for inter-buddy group organisation messages (such as assigning to and removing
                              from groups, defaults to 1000. -->
                              <buddyCommunicationTimeout>2000</buddyCommunicationTimeout>
  
  							<!-- Whether data is removed from old owners when gravitated to a new owner.  Defaults to true.  -->
  							<dataGravitationRemoveOnFind>true</dataGravitationRemoveOnFind>
  
  							<!-- Whether backup nodes can respond to data gravitation requests, or only the data owner is supposed to respond.
  								defaults to true. -->
  							<dataGravitationSearchBackupTrees>true</dataGravitationSearchBackupTrees>
  
  							<!-- Whether all cache misses result in a data gravitation request.  Defaults to false, requiring callers to
  								enable data gravitation on a per-invocation basis using the Options API.  -->
  						    <autoDataGravitation>false</autoDataGravitation>
  
                          </config>
                      </attribute>
                      ]]>
                 </programlisting>
              </para>
           </section>
        </section>
     </section>
  
     <section>
        <title>Clustered Cache - Using Invalidation</title>
  
        <para>If a cache is configured for invalidation rather than replication,
           every time data is changed in a cache other caches in the cluster
           receive a message informing them that their data is now stale and should
           be evicted from memory. Invalidation, when used with a shared cache
           loader (see chapter on Cache Loaders) would cause remote caches to refer
           to the shared cache loader to retrieve modified data. The benefit of
           this is twofold: network traffic is minimised as invalidation messages
           are very small compared to replicating updated data, and also that other
           caches in the cluster look up modified data in a lazy manner, only when
           needed.
        </para>
  
        <para>Invalidation messages are sent after each modification (no
           transactions), or at the end of a transaction, upon successful commit.
           This is usually more efficient as invalidation messages can be optimised
           for the transaction as a whole rather than on a per-modification
           basis.
        </para>
  
        <para>Invalidation too can be synchronous or asynchronous, and just as
           in the case of replication, synchronous invalidation blocks
           until all caches in the cluster receive invalidation messages and have
           evicted stale data while asynchronous invalidation works in a
           'fire-and-forget' mode, where invalidation messages are broadcast but
           doesn't block and wait for responses.
        </para>
     </section>
  </chapter>
  
  
  1.1      date: 2007/01/19 17:01:00;  author: msurtani;  state: Exp;JBossCache/docs/JBossCache-UserGuide/en/modules/cache_loaders.xml
  
  Index: cache_loaders.xml
  ===================================================================
  <chapter id="cache_loaders">
     <title>Cache Loaders</title>
  
     <para>JBoss Cache can use a
        <emphasis>cache loader</emphasis>
        to back up the in-memory cache to a backend datastore. If JBoss Cache is configured with a cache loader, then
        the following features are provided:
        <itemizedlist>
           <listitem>Whenever a cache element is accessed, and that element is not in
              the cache (e.g. due to eviction or due to server restart), then the cache loader transparently
              loads the element into the cache if found in the backend
              store.
           </listitem>
  
           <listitem>Whenever an element is modified, added or removed, then that
              modification is persisted in the backend store via the cache loader. If
              transactions are used, all modifications created within a transaction
              are persisted. To this end, the cache loader takes part in the two
              phase commit protocol run by the transaction manager.
           </listitem>
        </itemizedlist>
     </para>
  
     <para>Currently, the cache loader API looks similar to the TreeCache API.
        In the future, they will both implement the
        <emphasis>same</emphasis>
        interface. The goal is to be able to form hierarchical cache topologies,
        where one cache can delegate to another, which in turn may delegate to yet
        another cache.
     </para>
  
     <para>As of JBossCache 1.3.0, you can now define several cache loaders, in
        a chain. The impact is that the cache will look at all of the cache
        loaders in the order they've been configured, until it finds a valid,
        non-null element of data. When performing writes, all cache loaders are
        written to (except if the ignoreModifications element has been set to true
        for a specific cache loader. See the configuration section below for
        details.
     </para>
  
     <para>The cache loader interface is defined in
        org.jboss.cache.loader.CacheLoader as follows (edited for brevity):
     </para>
  
     <programlisting>public interface CacheLoader extends Service {
  
        /**
        * Sets the configuration. Will be called before {@link #create()} and {@link #start()}
        * @param props A set of properties specific to a given CacheLoader
        */
        void setConfig(Properties props);
  
        void setCache(TreeCache c);
  
  
        /**
        * Returns a list of children names, all names are &lt;em&gt;relative&lt;/em&gt;. Returns null if the parent node
        is not found.
        * The returned set must not be modified, e.g. use Collections.unmodifiableSet(s) to return the result
        * @param fqn The FQN of the parent
        * @return Set&lt;String&gt;. A list of children. Returns null if no children nodes are present, or the parent is
        * not present
        */
        Set getChildrenNames(Fqn fqn) throws Exception;
  
  
        /**
        * Returns the value for a given key. Returns null if the node doesn't exist, or the value is not bound
        */
        Object get(Fqn name, Object key) throws Exception;
  
  
        /**
        * Returns all keys and values from the persistent store, given a fully qualified name.
        *
        * NOTE that the expected return value of this method has changed from JBossCache 1.2.x
        * and before! This will affect cache loaders written prior to JBossCache 1.3.0 and such
        * implementations should be checked for compliance with the behaviour expected.
        *
        * @param name
        * @return Map&lt;Object,Object&gt; of keys and values for the given node. Returns null if the node is not
        * found. If the node is found but has no attributes, this method returns an empty Map.
        * @throws Exception
        */
        Map get(Fqn name) throws Exception;
  
  
        /**
        * Checks whether the CacheLoader has a node with Fqn
        * @return True if node exists, false otherwise
        */
        boolean exists(Fqn name) throws Exception;
  
  
        /**
        * Inserts key and value into the attributes hashmap of the given node. If the node does not exist, all
        * parent nodes from the root down are created automatically
        */
        void put(Fqn name, Object key, Object value) throws Exception;
  
        /**
        * Inserts all elements of attributes into the attributes hashmap of the given node, overwriting existing
        * attributes, but not clearing the existing hashmap before insertion (making it a union of existing and
        * new attributes)
        * If the node does not exist, all parent nodes from the root down are created automatically
        * @param name The fully qualified name of the node
        * @param attributes A Map of attributes. Can be null
        */
        void put(Fqn name, Map attributes) throws Exception;
  
        /**
        * Inserts all modifications to the backend store. Overwrite whatever is already in
        * the datastore.
        * @param modifications A List&lt;Modification&gt; of modifications
        * @throws Exception
        */
        void put(List modifications) throws Exception;
  
        /** Removes the given key and value from the attributes of the given node. No-op if node doesn't exist */
        void remove(Fqn name, Object key) throws Exception;
  
        /**
        * Removes the given node. If the node is the root of a subtree, this will recursively remove all subnodes,
        * depth-first
        */
        void remove(Fqn name) throws Exception;
  
        /** Removes all attributes from a given node, but doesn't delete the node itself */
        void removeData(Fqn name) throws Exception;
  
  
        /**
        * Prepare the modifications. For example, for a DB-based CacheLoader:
        * &lt;ol&gt;
        * &lt;li&gt;Create a local (JDBC) transaction
        * &lt;li&gt;Associate the local transaction with &lt;code&gt;tx&lt;/code&gt; (tx is the key)
        * &lt;li&gt;Execute the coresponding SQL statements against the DB (statements derived from modifications)
        * &lt;/ol&gt;
        * For non-transactional CacheLoader (e.g. file-based), this could be a null operation
        * @param tx The transaction, just used as a hashmap key
        * @param modifications List&lt;Modification&gt;, a list of all modifications within the given transaction
        * @param one_phase Persist immediately and (for example) commit the local JDBC transaction as well. When true,
        * we won't get a {@link #commit(Object)} or {@link #rollback(Object)} method call later
        */
        void prepare(Object tx, List modifications, boolean one_phase) throws Exception;
  
        /**
        * Commit the transaction. A DB-based CacheLoader would look up the local JDBC transaction asociated
        * with &lt;code&gt;tx&lt;/code&gt; and commit that transaction&lt;br/&gt;
        * Non-transactional CacheLoaders could simply write the data that was previously saved transiently under the
        * given &lt;code&gt;tx&lt;/code&gt; key, to (for example) a file system (note this only holds if the previous
        prepare() did
        * not define one_phase=true
        */
        void commit(Object tx) throws Exception;
  
        /**
        * Roll the transaction back. A DB-based CacheLoader would look up the local JDBC transaction asociated
        * with &lt;code&gt;tx&lt;/code&gt; and roll back that transaction
        */
        void rollback(Object tx);
  
        /**
        * Fetch the entire state for this cache from secondary storage (disk, DB) and return it as a byte buffer.
        * This is for initialization of a new cache from a remote cache. The new cache would then call
        * storeEntireState()
        * todo: define binary format for exchanging state
        */
        byte[] loadEntireState() throws Exception;
  
        /** Store the given state in secondary storage. Overwrite whatever is currently in storage */
        void storeEntireState(byte[] state) throws Exception;
        }
     </programlisting>
  
     <para>
        <emphasis role="bold">NOTE:</emphasis>
        the contract defined by the CacheLoader interface has changed
        from JBoss Cache 1.3.0 onwards, specifically with the
        <literal>get(Fqn fqn)</literal>
        method.
        Special care must be taken with custom CacheLoader implementations to ensure this new contract is
        still adhered to. See the javadoc above on this method for details, or visit
        <ulink url="http://wiki.jboss.org/wiki/Wiki.jsp?page=JBossCacheCacheLoaders">this wiki page</ulink>
        for more discussion on this.
     </para>
  
     <para>CacheLoader implementations that need to support partial state transfer should
        also implement the subinterface org.jboss.cache.loader.ExtendedCacheLoader:
     </para>
  
     <programlisting>public interface ExtendedCacheLoader extends CacheLoader
        {
        /**
        * Fetch a portion of the state for this cache from secondary storage
        * (disk, DB) and return it as a byte buffer.
        * This is for activation of a portion of new cache from a remote cache.
        * The new cache would then call {@link #storeState(byte[], Fqn)}.
        *
        * @param subtree Fqn naming the root (i.e. highest level parent) node of
        * the subtree for which state is requested.
        *
        * @see org.jboss.cache.TreeCache#activateRegion(String)
        */
        byte[] loadState(Fqn subtree) throws Exception;
  
        /**
        * Store the given portion of the cache tree's state in secondary storage.
        * Overwrite whatever is currently in secondary storage. If the transferred
        * state has Fqns equal to or children of parameter
        <code>subtree</code>
        ,
        * then no special behavior is required. Otherwise, ensure that
        * the state is integrated under the given 'subtree'. Typically
        * in the latter case 'subtree' would be the Fqn of the buddy
        * backup region for a buddy group; e.g.
        *
        * If the the transferred state had Fqns starting with "/a" and
        * 'subtree' was "/_BUDDY_BACKUP_/192.168.1.2:5555" then the
        * state should be stored in the local persistent store under
        * "/_BUDDY_BACKUP_/192.168.1.2:5555/a"
        *
        * @param state the state to store
        * @param subtree Fqn naming the root (i.e. highest level parent) node of
        * the subtree included in 'state'. If the Fqns
        * of the data included in 'state' are not
        * already children of 'subtree', then their
        * Fqns should be altered to make them children of
        * 'subtree' before they are persisted.
        */
        void storeState(byte[] state, Fqn subtree) throws Exception;
  
        /**
        * Sets the {@link RegionManager} this object should use to manage
        * marshalling/unmarshalling of different regions using different
        * classloaders.
        *
        * NOTE: This method is only intended to be used by the TreeCache instance
        * this cache loader is associated with.
        *
        * @param manager the region manager to use, or
        <code>null</code>
        .
        */
        void setRegionManager(RegionManager manager);
  
        }
     </programlisting>
  
     <para>
        <emphasis role="bold">NOTE:</emphasis>
        If a cache loader is used along with
        buddy replication, the cache loader must implement
        <literal>ExtendedCacheLoader</literal>
        unless its
        <literal>FetchPersistentState</literal>
        property is set to false.
     </para>
  
     <para>
        <emphasis role="bold">NOTE:</emphasis>
        the contract defined by the
        <literal>ExtendedCacheLoader</literal>
        interface has changed
        from JBoss Cache 1.4.0 onwards, specifically with the requirement that data passed to
        <literal>storeState</literal>
        method be integrated under the given subtree, even if that data didn't originate in that subtree. This
        behavior is necessary to properly support buddy replication. Special care must be taken with custom
        ExtendedCacheLoader implementations to ensure this new contract is still adhered to.
     </para>
  
     <section>
        <title>The CacheLoader Interface</title>
  
        <para>The interaction between JBoss Cache and a CacheLoader
           implementation is as follows. When
           <literal>CacheLoaderConfiguration</literal>
           (see below) is non-null, an
           instance of each configured
           <literal>cacheloader</literal>
           is created
           when the cache is created. Since
           <literal>CacheLoader</literal>
           extends
           <literal>Service</literal>
           ,
        </para>
  
        <programlisting>public interface Service {
           void create() throws Exception;
  
           void start() throws Exception;
  
           void stop();
  
           void destroy();
           }
        </programlisting>
  
        <para>
           <literal>CacheLoader.create()</literal>
           and
           <literal>CacheLoader.start()</literal>
           are called when the cache is
           started. Correspondingly,
           <literal>stop()</literal>
           and
           <literal>destroy()</literal>
           are called when the cache is
           stopped.
        </para>
  
        <para>Next,
           <literal>setConfig()</literal>
           and
           <literal>setCache()</literal>
           are called. The latter can be used to
           store a reference to the cache, the former is used to configure this
           instance of the CacheLoader. For example, here a database CacheLoader
           could establish a connection to the database.
        </para>
  
        <para>The CacheLoader interface has a set of methods that are called
           when no transactions are used:
           <literal>get()</literal>
           ,
           <literal>put()</literal>
           ,
           <literal>remove()</literal>
           and
           <literal>removeData()</literal>
           : they get/set/remove the value
           immediately. These methods are described as javadoc comments in the
           above interface.
        </para>
  
        <para>Then there are three methods that are used with transactions:
           <literal>prepare()</literal>
           ,
           <literal>commit()</literal>
           and
           <literal>rollback()</literal>
           . The
           <literal>prepare()</literal>
           method
           is called when a transaction is to be committed. It has a transaction
           object and a list of modfications as argument. The transaction object
           can be used as a key into a hashmap of transactions, where the values
           are the lists of modifications. Each modification list has a number of
           <literal>Modification</literal>
           elements, which represent the changes
           made to a cache for a given transaction. When
           <literal>prepare()</literal>
           returns successfully, then the CacheLoader
           <emphasis>must</emphasis>
           be able to commit (or rollback) the
           transaction successfully.
        </para>
  
        <para>Currently, the TreeCache takes care of calling prepare(), commit()
           and rollback() on the CacheLoaders at the right time. We intend to make
           both the TreeCache and the CacheLoaders XA resources, so that instead of
           calling those methods on a loader, the cache will only enlist the loader
           with the TransactionManager on the same transaction.
        </para>
  
        <para>The
           <literal>commit()</literal>
           method tells the CacheLoader to
           commit the transaction, and the
           <literal>rollback()</literal>
           method
           tells the CacheLoader to discard the changes associated with that
           transaction.
        </para>
  
        <para>The last two methods are
           <literal>loadEntireState()</literal>
           and
           <literal>storeEntireState()</literal>
           . The first method asks the
           CacheLoader to get the entire state the backend store manages and return
           it as a byte buffer, and the second tells a CacheLoader to replace its
           entire state with the byte buffer argument. These methods are used for
           scenarios where each JBossCache node in a cluster has its own local data
           store, e.g. a local DB, and - when a new node starts - we have to
           initialize its backend store with the contents of the backend store of
           an existing member. See below for deails.
        </para>
  
        <para>The
           <literal>ExtendedCacheLoader</literal>
           methods are also
           related to state transfer. The
           <literal>loadState(Fqn)</literal>
           method is called
           when the cache is preparing a partial state transfer -- that is, the
           transfer of just the portion of the cache loader's state that is rooted
           in the given Fqn. The
           <literal>storeState(byte[], Fqn)</literal>
           method
           is then invoked on the cache loader of the node that is receiving the
           state transfer. Partial state transfers occur when the cache's
           <literal>activateRegion()</literal>
           API is used and during the
           formation of buddy groups if buddy replication is used.
        </para>
     </section>
  
     <section>
        <title>Configuration via XML</title>
  
        <para>The CacheLoader is configured as follows in the JBossCache XML
           file:
        </para>
  
        <programlisting>    &lt;!-- ==================================================================== --&gt;
           &lt;!-- Defines TreeCache configuration --&gt;
           &lt;!-- ==================================================================== --&gt;
  
           &lt;mbean code="org.jboss.cache.TreeCache" name="jboss.cache:service=TreeCache"&gt;
  
           &lt;!-- New 1.3.x cache loader config block --&gt;
           &lt;attribute name="CacheLoaderConfiguration"&gt;
           &lt;config&gt;
           &lt;!-- if passivation is true, only the first cache loader is used; the rest are ignored --&gt;
           &lt;passivation&gt;false&lt;/passivation&gt;
           &lt;!-- comma delimited FQNs to preload --&gt;
           &lt;preload&gt;/&lt;/preload&gt;
           &lt;!-- are the cache loaders shared in a cluster? --&gt;
           &lt;shared&gt;false&lt;/shared&gt;
  
           &lt;!-- we can now have multiple cache loaders, which get chained --&gt;
           &lt;!-- the 'cacheloader' element may be repeated --&gt;
           &lt;cacheloader&gt;
           &lt;class&gt;org.jboss.cache.loader.JDBCCacheLoader&lt;/class&gt;
           &lt;!-- same as the old CacheLoaderConfig attribute --&gt;
           &lt;properties&gt;
           cache.jdbc.driver=com.mysql.jdbc.Driver
           cache.jdbc.url=jdbc:mysql://localhost:3306/jbossdb
           cache.jdbc.user=root
           cache.jdbc.password=
           &lt;/properties&gt;
           &lt;!-- whether the cache loader writes are asynchronous --&gt;
           &lt;async&gt;false&lt;/async&gt;
           &lt;!-- only one cache loader in the chain may set fetchPersistentState to true.
           An exception is thrown if more than one cache loader sets this to true. --&gt;
           &lt;fetchPersistentState&gt;true&lt;/fetchPersistentState&gt;
           &lt;!-- determines whether this cache loader ignores writes - defaults to false. --&gt;
           &lt;ignoreModifications&gt;false&lt;/ignoreModifications&gt;
           &lt;!-- if set to true, purges the contents of this cache loader when the cache starts up.
           Defaults to false. --&gt;
           &lt;purgeOnStartup&gt;false&lt;/purgeOnStartup&gt;
           &lt;!-- defines the cache loader as a singleton store where only the coordinator of the
           cluster will store modifications. Setting pushStateWhenCoordinator to true enables a
           newly elected coordinator to push the in-memory state to the underlying cache store.
           Both default to false. --&gt;
           &lt;singletonStore pushStateWhenCoordinator="false"&gt;false&lt;/singletonStore&gt;
           &lt;/cacheloader&gt;
  
           &lt;/config&gt;
           &lt;/attribute&gt;
  
           &lt;/mbean&gt;
        </programlisting>
  
        <para>
           <emphasis role="bold">Note:</emphasis>
           In JBossCache releases
           prior to 1.3.0, the cache loader configuration block used to look like
           this. Note that this form is
           <emphasis role="deprecated">DEPRECATED</emphasis>
           and you will have to replace
           your cache loader configuration with a block similar to the one
           above.
        </para>
  
        <para>
           <programlisting>    &lt;!-- ==================================================================== --&gt;
              &lt;!-- Defines TreeCache configuration --&gt;
              &lt;!-- ==================================================================== --&gt;
  
              &lt;mbean code="org.jboss.cache.TreeCache" name="jboss.cache:service=TreeCache"&gt;
              &lt;attribute name="CacheLoaderClass"&gt;org.jboss.cache.loader.bdbje.BdbjeCacheLoader&lt;/attribute&gt;
              &lt;!-- attribute name="CacheLoaderClass"&gt;org.jboss.cache.loader.FileCacheLoader&lt;/attribute --&gt;
              &lt;attribute name="CacheLoaderConfig" replace="false"&gt;
              location=c:\\tmp\\bdbje
              &lt;/attribute&gt;
              &lt;attribute name="CacheLoaderShared"&gt;true&lt;/attribute&gt;
              &lt;attribute name="CacheLoaderPreload"&gt;/&lt;/attribute&gt;
              &lt;attribute name="CacheLoaderFetchTransientState"&gt;false&lt;/attribute&gt;
              &lt;attribute name="CacheLoaderFetchPersistentState"&gt;true&lt;/attribute&gt;
              &lt;attribute name="CacheLoaderAsynchronous"&gt;true&lt;/attribute&gt;
              &lt;/mbean&gt;
           </programlisting>
        </para>
  
        <para>The
           <literal>CacheLoaderClass</literal>
           attribute defines the
           class of the CacheLoader implementation. (Note that, because of a bug in
           the properties editor in JBoss, backslashes in variables for Windows
           filenames might not get expanded correctly, so replace="false" may be
           necessary).
        </para>
  
        <para>The currently available implementations shipped with JBossCache
           are:
        </para>
  
        <itemizedlist>
           <listitem>
              <para>
                 <literal>FileCacheLoader</literal>
                 , which is a simple
                 filesystem-based implementation. The
                 <literal>&lt;cacheloader&gt;&lt;properties&gt;</literal>
                 element
                 needs to contain a "location" property, which maps to a directory where
                 the file is located (e.g., "location=c:\\tmp"). By default, this cache
                 loader checks for any potential character portability issues in the
                 location or tree node names, for example invalid characters, producing
                 warning messages. These checks can be disabled adding
                 "check.character.portability" property and setting it to false
                 (e.g., "check.character.portability=false").
              </para>
           </listitem>
  
           <listitem>
              <para>
                 <literal>BdbjeCacheLoader</literal>
                 , which is a CacheLoader
                 implementation based on the Sleepycat DB Java Edition. The
                 <literal>&lt;cacheloader&gt;&lt;properties&gt;</literal>
                 element needs
                 to contain a "location" property, which maps to a directory,where the
                 database file for Sleepycat resides (e.g., "location=c:\\tmp").
              </para>
           </listitem>
  
           <listitem>
              <para>
                 <literal>JDBCCacheLoader</literal>
                 , which is a CacheLoader
                 implementation using JDBC to access any relational database. The
                 <literal>&lt;cacheloader&gt;&lt;properties&gt;</literal>
                 element
                 contains a number of properties needed to connect to the
                 database such as username, password, and connection URL. See the
                 section on JDBCCacheLoader for more details.
              </para>
           </listitem>
  
           <listitem>
              <para>
                 <literal>LocalDelegatingCacheLoader</literal>
                 , which enables
                 loading from and storing to another local (same VM) TreeCache.
              </para>
           </listitem>
  
           <listitem>
              <para>
                 <literal>TcpDelegatingCacheLoader</literal>
                 , which enables
                 loading from and storing to a remote (different VM) TreeCache using
                 TCP as the transport mechanism. This CacheLoader is available in
                 JBossCache version 1.3.0 and above.
              </para>
           </listitem>
  
           <listitem>
              <para>
                 <literal>ClusteredCacheLoader</literal>
                 , which allows querying
                 of other caches in the same cluster for in-memory data via the same
                 clustering protocols used to replicate data. Writes are
                 <emphasis
                         role="bold">not
                 </emphasis>
                 'stored' though, as replication would
                 take care of any updates needed. You need to specify a property
                 called "
                 <literal>timeout</literal>
                 ", a long value telling the cache
                 loader how many milliseconds to wait for responses from the cluster
                 before assuming a null value. For example, "
                 <literal>timeout =
                    3000
                 </literal>
                 " would use a timeout value of 3 seconds. This
                 CacheLoader is available in JBossCache version 1.3.0 and
                 above.
              </para>
           </listitem>
        </itemizedlist>
  
        <para>Note that the Sleepycat implementation is much more efficient than
           the filesystem-based implementation, and provides transactional
           guarantees, but requires a commercial license if distributed with an
           application (see http://www.sleepycat.com/jeforjbosscache for
           details).
        </para>
  
        <para>An implementation of CacheLoader has to have an empty constructor
           due to the way it is instantiated.
        </para>
  
        <para>The
           <literal>properties</literal>
           element defines a configuration
           specific to the given implementation. The filesystem-based
           implementation for example defines the root directory to be used,
           whereas a database implementation might define the database URL, name
           and password to establish a database connection. This configuration is
           passed to the CacheLoader implementation via
           <literal>CacheLoader.setConfig(Properties)</literal>
           . Note that
           backspaces may have to be escaped.
           <emphasis>Analogous to the
              <literal>CacheLoaderConfig</literal>
              attribute in pre-1.3.0
              configurations.
           </emphasis>
        </para>
  
        <para>
           <literal>preload</literal>
           allows us to define a list of nodes, or
           even entire subtrees, that are visited by the cache on startup, in order
           to preload the data associated with those nodes. The default ("/") loads
           the entire data available in the backend store into the cache, which is
           probably not a good idea given that the data in the backend store might
           be large. As an example,
           <literal>/a,
              /product/catalogue
           </literal>
           loads the subtrees
           <literal>/a</literal>
           and
           <literal>/product/catalogue</literal>
           into the cache, but nothing
           else. Anything else is loaded lazily when accessed. Preloading makes
           sense when one anticipates using elements under a given subtree
           frequently.
           <emphasis>Note that preloading loads all nodes and
              associated attributes from the given node, recursively up to the root
              node
           </emphasis>
           .
           <emphasis>Analogous to the
              <literal>CacheLoaderPreload</literal>
              attribute in pre-1.3.0
              configurations.
           </emphasis>
        </para>
  
        <para>
           <literal>fetchPersistentState</literal>
           determines whether or not
           to fetch the persistent state of a cache when joining a cluster. Only
           one configured cache loader may set this property to true; if more than
           one cache loader does so, a configuration exception will be thrown when
           starting your cache service.
           <emphasis>Analogous to the
              <literal>CacheLoaderFetchPersistentState</literal>
              attribute in
              pre-1.3.0 configurations.
           </emphasis>
        </para>
  
        <para>
           <literal>async</literal>
           determines whether writes to the cache
           loader block until completed, or are run on a separate thread so writes
           return immediately. If this is set to true, an instance of
           <literal>org.jboss.cache.loader.AsyncCacheLoader</literal>
           is
           constructed with an instance of the actual cache loader to be used. The
           <literal>AsyncCacheLoader</literal>
           then delegates all requests to the
           underlying cache loader, using a separate thread if necessary. See the
           Javadocs on
           <literal>org.jboss.cache.loader.AsyncCacheLoader</literal>
           for more details. If unspecified, the
           <literal>async</literal>
           element
           defaults to
           <emphasis>false</emphasis>
           .
           <emphasis>Analogous to the
              <literal>CacheLoaderAsynchronous</literal>
              attribute in pre-1.3.0
              configurations.
           </emphasis>
        </para>
  
        <para>
           <emphasis role="bold">Note on using the
              <literal>async</literal>
              element:
           </emphasis>
           there is always the possibility of dirty reads since
           all writes are performed asynchronously, and it is thus impossible to
           guarantee when (and even if) a write succeeds. This needs to be kept in
           mind when setting the
           <literal>async</literal>
           element to true.
        </para>
  
        <para>
           <literal>ignoreModifications</literal>
           determines whether write
           methods are pushed down to the specific cache loader. Situations may
           arise where transient application data should only reside in a file
           based cache loader on the same server as the in-memory cache, for
           example, with a further shared JDBC cache loader used by all servers in
           the network. This feature allows you to write to the 'local' file cache
           loader but not the shared JDBC cache loader. This property defaults to
           <literal>false</literal>
           , so writes are propagated to all cache loaders
           configured.
        </para>
  
        <para>
           <literal>purgeOnStatup</literal>
           empties the specified cache loader
           (if
           <literal>ignoreModifications</literal>
           is
           <literal>false</literal>
           )
           when the cache loader starts up.
        </para>
     </section>
  
     <para>
        <literal>singletonStore</literal>
        enables modifications to
        be stored by only one node in the cluster, the coordinator. This property
        can be set to true in all nodes, but only the coordinator of the cluster
        will store the modifications in the underlying cache loader as specified
        in the
        <literal>class</literal>
        element inside
        <literal>cacheloader
        </literal>
        element . You cannot define a cache loader as
        <literal>shared
        </literal>
        and
        <literal>singletonStore</literal>
        at the same time.
        Default value is false.
     </para>
  
     <para>
        <literal>pushStateWhenCoordinator</literal>
        allows the in-memory
        state to be pushed to the cache store when a node becomes the
        coordinator, as a result of the new election of coordinator due to a
        cluster topology change. This can be very useful in situations where the
        coordinator crashes and there's a gap in time until the new coordinator
        is elected. During this time, if this property was set to false and the
        cache was updated, these changes would never be persisted. Setting this
        property to true would ensure that any changes during this process also
        get stored in the cache loader. You would also want to set this property
        to true if each node's cache loader is configured with a different
        location. Default value is false.
     </para>
  
     <para>
        <emphasis role="bold">Note on using the
           <literal>singletonStore</literal>
           element:
        </emphasis>
        setting
        up a cache loader as a singleton and using cache passivation (via
        evictions) can lead to undesired effects. If a node is to be passivated
        as a result of an eviction, while the cluster is in the process of
        electing a new coordinator, the data will be lost. This is because no
        coordinator is active at that time and therefore, none of the nodes in
        the cluster will store the passivated node. A new coordinator is elected
        in the cluster when either, the coordinator leaves the cluster, the
        coordinator crashes or stops responding.
     </para>
  
     <section>
        <title>Cache passivation</title>
  
        <para>A CacheLoader can be used to enforce node passivation and
           activation on eviction in a TreeCache.
        </para>
  
        <para>
           <emphasis>Cache Passivation</emphasis>
           is the process of removing
           an object from in-memory cache and writing it to a secondary data store
           (e.g., file system, database) on eviction.
           <emphasis>Cache
              Activation
           </emphasis>
           is the process of restoring an object from the
           data store into the in-memory cache when it's needed to be used. In both
           cases, the configured CacheLoader will be used to read from the data
           store and write to the data store.
        </para>
  
        <para>When the eviction policy in effect calls evict() to evict a node
           from the cache, if passivation is enabled, a notification that the node
           is being passivated will be emitted to the tree cache listeners and the
           node and its children will be stored in the cache loader store. When a
           user calls get() on a node that was evicted earlier, the node is loaded
           (lazy loaded) from the cache loader store into the in-memory cache. When
           the node and its children have been loaded, they're removed from the
           cache loader and a notification is emitted to the tree cache listeners
           that the node has been activated.
        </para>
  
        <para>To enable cache passivation/activation, you can set
           <literal>passivation</literal>
           to true. The default is false. You set it
           via the XML cache configuration file. The XML above shows the
           <literal>passivation</literal>
           element when configuring a cache loader.
           When passivation is used, only the first cache loader configured is
           used. All others are ignored.
        </para>
     </section>
  
     <section>
        <title>CacheLoader use cases</title>
  
        <section>
           <title>Local cache with store</title>
  
           <para>This is the simplest case. We have a JBossCache instance, whose
              mode is
              <literal>LOCAL</literal>
              , therefore no replication is going
              on. The CacheLoader simply loads non-existing elements from the store
              and stores modifications back to the store. When the cache is started,
              depending on the
              <literal>preload</literal>
              element, certain data can
              be preloaded, so that the cache is partly warmed up.
           </para>
  
           <para>When using PojoCache, this means that entire POJOs can be
              stored to a database or a filesystem, and when accessing fields of a
              POJO, they will be lazily loaded using the CacheLoader to access a
              backend store. This feature effectively provides simple persistency
              for any POJO.
           </para>
        </section>
  
        <section>
           <title>Replicated caches with all nodes sharing the same store</title>
  
           <para>The following figure shows 2 JBossCache nodes sharing the same
              backend store:
           </para>
  
           <figure>
              <title>2 nodes sharing a backend store</title>
  
              <mediaobject>
                 <imageobject>
                    <imagedata fileref="images/SharedCacheLoader.gif"/>
                 </imageobject>
              </mediaobject>
           </figure>
  
           <para>Both nodes have a CacheLoader that accesses a common shared
              backend store. This could for example be a shared filesystem (using
              the FileCacheLoader), or a shared database. Because both nodes access
              the same store, they don't necessarily need state transfer on
              startup.
              <footnote>
                 <para>Of course they can enable state transfer, if they want to
                    have a warm or hot cache after startup.
                 </para>
              </footnote>
              Rather, the
              <literal>FetchInMemoryState</literal>
              attribute could be set to false, resulting in a 'cold' cache, that
              gradually warms up as elements are accessed and loaded for the first
              time. This would mean that individual caches in a cluster might have
              different in-memory state at any given time (largely depending on
              their preloading and eviction strategies).
           </para>
  
           <para>When storing a value, the writer takes care of storing the
              change in the backend store. For example, if node1 made change C1 and
              node2 C2, then node1 would tell its CacheLoader to store C1, and node2
              would tell its CacheLoader to store C2.
           </para>
        </section>
  
        <section>
           <title>Replicated caches with only one node having a store</title>
  
           <para/>
  
           <figure>
              <title>2 nodes but only one accesses the backend store</title>
  
              <mediaobject>
                 <imageobject>
                    <imagedata fileref="images/OnlyOneCacheLoader.gif"/>
                 </imageobject>
              </mediaobject>
           </figure>
  
           <para>This is a similar case as the previous one, but here only one
              node in the cluster interacts with a backend store via its
              CacheLoader. All other nodes perform in-memory replication. A use case
              for this is HTTP session replication, where all nodes replicate
              sessions in-memory, and - in addition - one node saves the sessions to
              a persistent backend store. Note that here it may make sense for the
              CacheLoader to store changes asynchronously, that is
              <emphasis>not</emphasis>
              on the caller's thread, in order not to slow
              down the cluster by accessing (for example) a database. This is a
              non-issue when using asynchronous replication.
           </para>
        </section>
  
        <section>
           <title>Replicated caches with each node having its own store</title>
  
           <figure>
              <title>2 nodes each having its own backend store</title>
  
              <mediaobject>
                 <imageobject>
                    <imagedata fileref="images/LocalCacheLoader.gif"/>
                 </imageobject>
              </mediaobject>
           </figure>
  
           <para>Here, each node has its own datastore. Modifications to the
              cache are (a) replicated across the cluster and (b) persisted using
              the CacheLoader. This means that all datastores have exactly the same
              state. When replicating changes synchronously and in a transaction,
              the two phase commit protocol takes care that all modifications are
              replicated and persisted in each datastore, or none is replicated and
              persisted (atomic updates).
           </para>
  
           <para>Note that currently JBossCache is
              <emphasis>not</emphasis>
              an
              XAResource, that means it doesn't implement recovery. When used with a
              TransactionManager that supports recovery, this functionality is not
              available.
           </para>
  
           <para>The challenge here is state transfer: when a new node starts it
              needs to do the following:
           </para>
  
           <orderedlist>
              <listitem>
                 <para>Tell the coordinator (oldest node in a cluster) to send it
                    the state
                 </para>
              </listitem>
  
              <listitem>
                 <para>The coordinator then needs to wait until all in-flight
                    transactions have completed. During this time, it will not allow
                    for new transactions to be started.
                 </para>
              </listitem>
  
              <listitem>
                 <para>Then the coordinator asks its CacheLoader for the entire
                    state using
                    <literal>loadEntireState()</literal>
                    . It then sends
                    back that state to the new node.
                 </para>
              </listitem>
  
              <listitem>
                 <para>The new node then tells its CacheLoader to store that state
                    in its store, overwriting the old state. This is the
                    <literal>CacheLoader.storeEntireState()</literal>
                    method
                 </para>
              </listitem>
  
              <listitem>
                 <para>As an option, the transient (in-memory) state can be
                    transferred as well during the state transfer.
                 </para>
              </listitem>
  
              <listitem>
                 <para>The new node now has the same state in its backend store as
                    everyone else in the cluster, and modifications received from
                    other nodes will now be persisted using the local
                    CacheLoader.
                 </para>
              </listitem>
           </orderedlist>
  
           <para/>
        </section>
  
        <section>
           <title>Hierarchical caches</title>
  
           <para>If you need to set up a hierarchy within a single VM, you can
              use the
              <literal>LocalDelegatingCacheLoader</literal>
              . This type of
              hierarchy can currently only be set up programmatically. The code
              below shows how a first-level cache delegates to a local second-level
              cache:
           </para>
  
           <programlisting>TreeCache firstLevel, secondLevel;
              LocalDelegatingCacheLoader cache_loader;
  
              // create and configure firstLevel
              firstLevel=new TreeCache();
  
              // create and configure secondLevel
              secondLevel=new TreeCache();
  
              // create DelegatingCacheLoader
              cache_loader=new LocalDelegatingCacheLoader(secondLevel);
  
              // set CacheLoader in firstLevel
              firstLevel.setCacheLoader(cache_loader);
  
              // start secondLevel
              secondLevel.startService();
  
              // start firstLevel
              firstLevel.startService();
  
           </programlisting>
  
           <para>If you need to set up a hierarchy across VMs but within a
              cluster, you can use the
              <literal>RpcDelegatingCacheLoader</literal>
              ,
              which delegates all cache loading requests from non-coordinator caches
              to the cluster's coordinator cache. The coordinator cache is the first
              cache in the cluster to come online. Note that if the coordinator
              cache leaves the cluster for any reason, the second cache in the
              cluster to come online becomes the coordinator and so on. The XML
              below shows how to configure a cluster using
              <literal>RpcDelegatingCacheLoader</literal>
              :
           </para>
  
           <programlisting>&lt;!-- ==================================================================== --&gt;
              &lt;!-- Defines TreeCache configuration --&gt;
              &lt;!-- ==================================================================== --&gt;
  
              &lt;mbean code="org.jboss.cache.TreeCache" name="jboss.cache:service=TreeCache"&gt;
              ...
              &lt;attribute name="CacheLoaderConfiguration"&gt;
              &lt;config&gt;
              &lt;passivation&gt;false&lt;/passivation&gt;
              &lt;preload&gt;/some/stuff&lt;/preload&gt;
              &lt;cacheloader&gt;
              &lt;class&gt;org.jboss.cache.loader.RpcDelegatingCacheLoader&lt;/class&gt;
              &lt;!-- whether the cache loader writes are asynchronous --&gt;
              &lt;async&gt;false&lt;/async&gt;
              &lt;!-- only one cache loader in the chain may set fetchPersistentState to true.
              An exception is thrown if more than one cache loader sets this to true. --&gt;
              &lt;fetchPersistentState&gt;false&lt;/fetchPersistentState&gt;
              &lt;!-- determines whether this cache loader ignores writes - defaults to false. --&gt;
              &lt;ignoreModifications&gt;false&lt;/ignoreModifications&gt;
              &lt;!-- if set to true, purges the contents of this cache loader when the cache starts up.
              Defaults to false. --&gt;
              &lt;purgeOnStartup&gt;false&lt;/purgeOnStartup&gt;
              &lt;/cacheloader&gt;
              &lt;/config&gt;
              &lt;/attribute&gt;
              ...
              &lt;/mbean&gt;</programlisting>
  
           <para>Note that currently (JBossCache 1.3.0) this cache loader is not
              well supported, and has not been tested. We suggest to use
              TcpDelegatingCacheLoader instead (see next).
           </para>
  
           <para/>
        </section>
  
  
        <section>
           <title>TcpDelegatingCacheLoader</title>
  
           <para>This cache loader allows to delegate loads and stores to another
              instance of JBossCache, which could reside (a)in the same address
              space, (b) in a different process on the same host, or (c) in a
              different process on a different host. Option (a) is mostly used for
              unit testing, and the envisaged use is (b) and (c).
           </para>
  
           <para>A TcpDelegatingCacheLoader talks to a remote TcpCacheServer,
              which can be a standalone process, or embedded as an MBean inside
              JBoss. The TcpCacheServer has a reference to another JBossCache, which
              it can create itself, or which is given to it (e.g. by JBoss, using
              dependency injection).
           </para>
  
           <para>The TcpDelegatingCacheLoader is configured with the host and
              port of the remote TcpCacheServer, and uses this to communicate to
              it.
           </para>
  
           <para/>
  
           <para>An example set of a TcpCacheServer running inside of JBoss is
              shown below:
           </para>
  
           <programlisting>&lt;server&gt;
  
              &lt;classpath codebase="./lib" archives="jboss-cache.jar"/&gt;
  
              &lt;mbean code="org.jboss.cache.loader.tcp.TcpCacheServer" name="jboss.cache:service=TcpCacheServer"&gt;
              &lt;depends optional-attribute-name="Cache"
              proxy-type="attribute"&gt;jboss.cache:service=TreeCache&lt;/depends&gt;
              &lt;attribute name="BindAddress"&gt;${jboss.bind.address:localhost}&lt;/attribute&gt;
              &lt;attribute name="Port"&gt;7500&lt;/attribute&gt;
              &lt;attribute name="MBeanServerName"&gt;&lt;/attribute&gt;
              &lt;!--&lt;attribute name="CacheName"&gt;jboss.cache:service=TreeCache&lt;/attribute&gt;--&gt;
              &lt;/mbean&gt;
  
              &lt;/server&gt;         </programlisting>
  
           <para>The BindAddress and Port define where its server socket is
              listening on, and an existing JBossCache MBean is injected into it
              (assigned to 'Cache'). This means that all requests from the
              TcpDelegatingCacheLoader will be received by this instance and
              forwarded to the JBossCache MBean.
           </para>
  
           <para>Note that there is also a 'Config' attribute which points to a
              config XML file for JBossCache. If it is set, then the TcpCacheServer
              will create its own instance of JBossCache and configure it according
              to the Config attribute.
           </para>
  
           <para>The client side looks as follow:</para>
  
           <programlisting>&lt;attribute name="CacheLoaderConfiguration"&gt;
              &lt;config&gt;
              &lt;cacheloader&gt;
              &lt;class&gt;org.jboss.cache.loader.TcpDelegatingCacheLoader&lt;/class&gt;
              &lt;properties&gt;
              host=localhost
              port=7500
              &lt;/properties&gt;
              &lt;/cacheloader&gt;
              &lt;/config&gt;
              &lt;/attribute&gt;</programlisting>
  
           <para>This means this instance of JBossCache will delegate all load
              and store requests to the remote TcpCacheServer running at
              localhost:7500.
           </para>
  
           <para>A typical use case could be multiple replicated instance of
              JBossCache in the same cluster, all delegating to the same
              TcpCacheServer instance. The TcpCacheServer might itself delegate to a
              database via JDBCCacheLoader, but the point here is that - if we have
              5 nodes all accessing the same dataset - they will load the data from
              the TcpCacheServer, which has do execute one SQL statement per
              unloaded data set. If the nodes went directly to the database, then
              we'd have the same SQL executed multiple times. So TcpCacheServer
              serves as a natural cache in front of the DB (assuming that a network
              round trip is faster than a DB access (which usually also include a
              network round trip)).
           </para>
  
           <para>To alleviate single point of failure, we could combine this with
              a ChainingCacheLoader, where the first CacheLoader is a
              ClusteredCacheLoader, the second a TcpDelegatingCacheLoader, and the
              last a JDBCacheLoader, effectively defining our cost of access to a
              cache in increasing order of cost.
           </para>
  
           <para/>
        </section>
  
        <section>
           <title>RmiDelegatingCacheLoader</title>
  
           <para>Similar to the TcpDelegatingCacheLoader, the RmiDelegatingCacheLoader uses RMI as a method of
              communicating with a remote cache.
           </para>
  
           <para>An RmiDelegatingCacheLoader talks to a remote RmiCacheServer,
              which is a standalone process. The RmiCacheServer has a reference to another JBossCache, which it can create
              itself, or which is given to it (e.g. by JBoss, using dependency injection).
           </para>
  
           <para>The RmiDelegatingCacheLoader is configured with the host, port of the remote RMI server and the bind name
              of the RmiCacheServer, and uses this to communicate.
           </para>
  
           <para/>
  
           <para>An example set of an RmiCacheServer running inside of JBoss is
              shown below:
           </para>
  
           <programlisting>&lt;server&gt;
  
              &lt;classpath codebase="./lib" archives="jboss-cache.jar"/&gt;
  
              &lt;mbean code="org.jboss.cache.loader.rmi.RmiCacheServer" name="jboss.cache:service=RmiCacheServer"&gt;
              &lt;depends optional-attribute-name="Cache"
              proxy-type="attribute"&gt;jboss.cache:service=TreeCache&lt;/depends&gt;
              &lt;!-- the address and port of the RMI server. --&gt;
              &lt;attribute name="BindAddress"&gt;${jboss.bind.address:localhost}&lt;/attribute&gt;
              &lt;attribute name="Port"&gt;1098&lt;/attribute&gt;
              &lt;attribute name="BindName"&gt;MyRmiCacheServer&lt;/attribute&gt;
              &lt;attribute name="MBeanServerName"&gt;&lt;/attribute&gt;
              &lt;!--&lt;attribute name="CacheName"&gt;jboss.cache:service=TreeCache&lt;/attribute&gt;--&gt;
              &lt;/mbean&gt;
  
              &lt;/server&gt;         </programlisting>
  
           <para>The BindAddress and Port should point to an already-running RMI server and the BindName is the name the
              object is bound to in the RMI server. An existing JBossCache MBean is injected into it
              (assigned to 'Cache'). This means that all requests from the
              TcpDelegatingCacheLoader will be received by this instance and
              forwarded to the JBossCache MBean.
           </para>
  
           <para>Note that there is also a 'Config' attribute which points to a
              config XML file for JBossCache. If it is set, then the RmiCacheServer
              will create its own instance of JBossCache and configure it according
              to the Config attribute.
           </para>
  
           <para>The client side looks as follow:</para>
  
           <programlisting>&lt;attribute name="CacheLoaderConfiguration"&gt;
              &lt;config&gt;
              &lt;cacheloader&gt;
              &lt;class&gt;org.jboss.cache.loader.RmiDelegatingCacheLoader&lt;/class&gt;
              &lt;properties&gt;
              host=localhost
              port=1098
              name=MyRmiCacheServer
              &lt;/properties&gt;
              &lt;/cacheloader&gt;
              &lt;/config&gt;
              &lt;/attribute&gt;</programlisting>
  
           <para>This means this instance of JBossCache will delegate all load
              and store requests to the remote RmiCacheServer running as MyRmiCacheServer on an RMI server running on
              localhost:1098.
           </para>
  
           <para>Very similar use case scenarios that apply to TcpDelegatingCacheLoaders above apply to
              RmiDelegatingCacheLoaders as well.
           </para>
  
           <para/>
        </section>
     </section>
  
  
     <section>
        <title>JDBC-based CacheLoader</title>
  
        <para>JBossCache is distributed with a JDBC-based CacheLoader
           implementation that stores/loads nodes' state into a relational database.
           The implementing class is
           <literal>org.jboss.cache.loader.JDBCCacheLoader</literal>
           .
        </para>
  
        <para>The current implementation uses just one table. Each row in the table
           represents one node and contains three columns:
           <itemizedlist>
              <listitem>column for FQN (which is also a primary key
                 column)
              </listitem>
  
              <listitem>column for node contents (attribute/value
                 pairs)
              </listitem>
  
              <listitem>column for parent FQN</listitem>
           </itemizedlist>
        </para>
  
        <para>FQN's are stored as strings. Node content is stored
           as a BLOB.
           <emphasis>WARNING:</emphasis>
           TreeCache does not impose any
           limitations on the types of objects used in FQN but this implementation of
           CacheLoader requires FQN to contain only objects of type
           <literal>java.lang.String</literal>
           . Another limitation for FQN is its
           length. Since FQN is a primary key, its default column type is
           <literal>VARCHAR</literal>
           which can store text values up to some
           maximum length determined by the database. FQN is also subject to any
           maximum primary key length restriction imposed by the database.
        </para>
  
        <para>See
           <ulink
                   url="???">http://wiki.jboss.org/wiki/Wiki.jsp?page=JDBCCacheLoader
           </ulink>
           for configuration tips with specific database systems.
        </para>
  
        <section>
           <title>JDBCCacheLoader configuration</title>
  
           <section>
              <title>Table configuration</title>
  
              <para>Table and column names as well as column types are
                 configurable with the following properties.
                 <itemizedlist>
                    <listitem>
                       <emphasis>cache.jdbc.table.name</emphasis>
                       - the name
                       of the table. The default value is 'jbosscache'.
                    </listitem>
  
                    <listitem>
                       <emphasis>cache.jdbc.table.primarykey</emphasis>
                       - the
                       name of the primary key for the table. The default value is
                       'jbosscache_pk'.
                    </listitem>
  
                    <listitem>
                       <emphasis>cache.jdbc.table.create</emphasis>
                       - can be
                       true or false. Indicates whether to create the table during startup.
                       If true, the table is created if it doesn't already exist. The
                       default value is true.
                    </listitem>
  
                    <listitem>
                       <emphasis>cache.jdbc.table.drop</emphasis>
                       - can be
                       true or false. Indicates whether to drop the table during shutdown. The
                       default value is true.
                    </listitem>
  
                    <listitem>
                       <emphasis>cache.jdbc.fqn.column</emphasis>
                       - FQN
                       column name. The default value is 'fqn'.
                    </listitem>
  
                    <listitem>
                       <emphasis>cache.jdbc.fqn.type</emphasis>
                       - FQN column
                       type. The default value is 'varchar(255)'.
                    </listitem>
  
                    <listitem>
                       <emphasis>cache.jdbc.node.column</emphasis>
                       - node
                       contents column name. The default value is 'node'.
                    </listitem>
  
                    <listitem>
                       <emphasis>cache.jdbc.node.type</emphasis>
                       - node
                       contents column type. The default value is 'blob'. This type must specify
                       a valid binary data type for the database being used.
                    </listitem>
                 </itemizedlist>
              </para>
           </section>
  
           <section>
              <title>DataSource</title>
  
              <para>If you are using JBossCache in a managed environment (e.g., an
                 application server) you can specify the JNDI name of the DataSource
                 you want to use.
                 <itemizedlist>
                    <listitem>
                       <emphasis>cache.jdbc.datasource</emphasis>
                       - JNDI name
                       of the DataSource. The default value is
                       'java:/DefaultDS'.
                    </listitem>
                 </itemizedlist>
              </para>
           </section>
  
           <section>
              <title>JDBC driver</title>
  
              <para>If you are
                 <emphasis>not</emphasis>
                 using DataSource you have
                 the following properties to configure database access using a JDBC
                 driver.
                 <itemizedlist>
                    <listitem>
                       <emphasis>cache.jdbc.driver</emphasis>
                       - fully
                       qualified JDBC driver name.
                    </listitem>
  
                    <listitem>
                       <emphasis>cache.jdbc.url</emphasis>
                       - URL to connect
                       to the database.
                    </listitem>
  
                    <listitem>
                       <emphasis>cache.jdbc.user</emphasis>
                       - user name to
                       connect to the database.
                    </listitem>
  
                    <listitem>
                       <emphasis>cache.jdbc.password</emphasis>
                       - password to
                       connect to the database.
                    </listitem>
                 </itemizedlist>
              </para>
           </section>
  
           <section>
              <title>Configuration example</title>
  
              <para>Below is an example of a JDBC CacheLoader using Oracle as
                 database. The CacheLoaderConfiguration XML element contains an
                 arbitrary set of properties which define the database-related
                 configuration.
              </para>
  
              <para>
                 <programlisting>&lt;attribute name="CacheLoaderConfiguration"&gt;
                    &lt;config&gt;
                    &lt;passivation&gt;false&lt;/passivation&gt;
                    &lt;preload&gt;/some/stuff&lt;/preload&gt;
                    &lt;cacheloader&gt;
                    &lt;class&gt;org.jboss.cache.loader.JDBCCacheLoader&lt;/class&gt;
                    &lt;!-- same as the old CacheLoaderConfig attribute --&gt;
                    &lt;properties&gt;
                    cache.jdbc.table.name=jbosscache
                    cache.jdbc.table.create=true
                    cache.jdbc.table.drop=true
                    cache.jdbc.table.primarykey=jbosscache_pk
                    cache.jdbc.fqn.column=fqn
                    cache.jdbc.fqn.type=varchar(255)
                    cache.jdbc.node.column=node
                    cache.jdbc.node.type=blob
                    cache.jdbc.parent.column=parent
                    cache.jdbc.driver=oracle.jdbc.OracleDriver
                    cache.jdbc.url=jdbc:oracle:thin:@localhost:1521:JBOSSDB
                    cache.jdbc.user=SCOTT
                    cache.jdbc.password=TIGER
                    &lt;/properties&gt;
                    &lt;!-- whether the cache loader writes are asynchronous --&gt;
                    &lt;async&gt;false&lt;/async&gt;
                    &lt;!-- only one cache loader in the chain may set fetchPersistentState to true.
                    An exception is thrown if more than one cache loader sets this to true. --&gt;
                    &lt;fetchPersistentState&gt;true&lt;/fetchPersistentState&gt;
                    &lt;!-- determines whether this cache loader ignores writes - defaults to false. --&gt;
                    &lt;ignoreModifications&gt;false&lt;/ignoreModifications&gt;
                    &lt;!-- if set to true, purges the contents of this cache loader when the cache starts up.
                    Defaults to false. --&gt;
                    &lt;purgeOnStartup&gt;false&lt;/purgeOnStartup&gt;
                    &lt;/cacheloader&gt;
                    &lt;/config&gt;
                    &lt;/attribute&gt;</programlisting>
              </para>
  
              <para>As an alternative to configuring the entire JDBC connection,
                 the name of an existing data source can be given:
              </para>
  
              <programlisting>&lt;attribute name="CacheLoaderConfiguration"&gt;
                 &lt;config&gt;
                 &lt;passivation&gt;false&lt;/passivation&gt;
                 &lt;preload&gt;/some/stuff&lt;/preload&gt;
                 &lt;cacheloader&gt;
                 &lt;class&gt;org.jboss.cache.loader.JDBCCacheLoader&lt;/class&gt;
                 &lt;!-- same as the old CacheLoaderConfig attribute --&gt;
                 &lt;properties&gt;
                 cache.jdbc.datasource=java:/DefaultDS
                 &lt;/properties&gt;
                 &lt;!-- whether the cache loader writes are asynchronous --&gt;
                 &lt;async&gt;false&lt;/async&gt;
                 &lt;!-- only one cache loader in the chain may set fetchPersistentState to true.
                 An exception is thrown if more than one cache loader sets this to true. --&gt;
                 &lt;fetchPersistentState&gt;true&lt;/fetchPersistentState&gt;
                 &lt;!-- determines whether this cache loader ignores writes - defaults to false. --&gt;
                 &lt;ignoreModifications&gt;false&lt;/ignoreModifications&gt;
                 &lt;!-- if set to true, purges the contents of this cache loader when the cache starts up.
                 Defaults to false. --&gt;
                 &lt;purgeOnStartup&gt;false&lt;/purgeOnStartup&gt;
                 &lt;/cacheloader&gt;
                 &lt;/config&gt;
                 &lt;/attribute&gt;</programlisting>
           </section>
        </section>
     </section>
  </chapter>
  
  
  1.1      date: 2007/01/19 17:01:00;  author: msurtani;  state: Exp;JBossCache/docs/JBossCache-UserGuide/en/modules/configuration.xml
  
  Index: configuration.xml
  ===================================================================
  <chapter id="configuration">
     <title>Configuration</title>
  
     <para>All properties of the cache are configured via setters and can be
        retrieved via getters. This can be done either manually, or via the
        <literal>PropertyConfigurator</literal>
        and an XML file.
     </para>
     <section>
        <title>Sample XML-Based Configuration</title>
        <para>
           A sample XML configuration file is shown
           below:
        </para>
        <programlisting>&lt;?xml version="1.0" encoding="UTF-8" ?&gt;
           &lt;server&gt;~/
           &lt;classpath codebase="./lib" archives="jboss-cache.jar, jgroups.jar" /&gt;
  
           &lt;!-- ==================================================================== --&gt;
           &lt;!-- Defines TreeCache configuration --&gt;
           &lt;!-- ==================================================================== --&gt;
           &lt;mbean code="org.jboss.cache.TreeCache" name="jboss.cache:service=TreeCache"&gt;
           &lt;depends&gt;jboss:service=Naming&lt;/depends&gt;
           &lt;depends&gt;jboss:service=TransactionManager&lt;/depends&gt;
  
  
           &lt;!-- Configure the TransactionManager --&gt;
           &lt;attribute name="TransactionManagerLookupClass"&gt;org.jboss.cache.DummyTransactionManagerLookup&lt;/attribute&gt;
  
           &lt;!-- Node locking scheme : PESSIMISTIC (default)
           OPTIMISTIC
           --&gt;
           &lt;attribute name="NodeLockingScheme"&gt;PESSIMISTIC&lt;/attribute&gt;
  
           &lt;!-- Node locking isolation level : SERIALIZABLE
           REPEATABLE_READ (default)
           READ_COMMITTED
           READ_UNCOMMITTED
           NONE
  
           (ignored if NodeLockingScheme is OPTIMISTIC)
           --&gt;
           &lt;attribute name="IsolationLevel"&gt;REPEATABLE_READ&lt;/attribute&gt;
  
           &lt;!-- Valid modes are LOCAL
           REPL_ASYNC
           REPL_SYNC
           INVALIDATION_ASYNC
           INVALIDATION_SYNC
           --&gt;
           &lt;attribute name="CacheMode"&gt;LOCAL&lt;/attribute&gt;
  
           &lt;!-- Whether each interceptor should have an mbean
           registered to capture and display its statistics. --&gt;
           &lt;attribute name="UseInterceptorMbeans"&gt;true&lt;/attribute&gt;
  
           &lt;!-- Name of cluster. Needs to be the same for all TreeCache nodes in a
           cluster, in order to find each other --&gt;
           &lt;attribute name="ClusterName"&gt;JBoss-Cache-Cluster&lt;/attribute&gt;
  
           &lt;!-- Uncomment next three statements to enable JGroups multiplexer.
           This configuration is dependent on the JGroups multiplexer being
           registered in an MBean server such as JBossAS. --&gt;
           &lt;!--
           &lt;depends&gt;jgroups.mux:name=Multiplexer&lt;/depends&gt;
           &lt;attribute name="MultiplexerService"&gt;jgroups.mux:name=Multiplexer&lt;/attribute&gt;
           &lt;attribute name="MultiplexerStack"&gt;udp&lt;/attribute&gt;
           --&gt;
  
           &lt;!-- JGroups protocol stack properties. ClusterConfig isn't used if the
           multiplexer is enabled and successfully initialized. --&gt;
           &lt;attribute name="ClusterConfig"&gt;
           &lt;config&gt;
           &lt;!-- UDP: if you have a multihomed machine,
           set the bind_addr attribute to the appropriate NIC IP address
           --&gt;
           &lt;!-- UDP: On Windows machines, because of the media sense feature
           being broken with multicast (even after disabling media sense)
           set the loopback attribute to true
           --&gt;
           &lt;UDP mcast_addr="228.1.2.3" mcast_port="45566" ip_ttl="64" ip_mcast="true"
           mcast_send_buf_size="150000" mcast_recv_buf_size="80000" ucast_send_buf_size="150000"
           ucast_recv_buf_size="80000" loopback="false" /&gt;
           &lt;PING timeout="2000" num_initial_members="3" up_thread="false" down_thread="false" /&gt;
           &lt;MERGE2 min_interval="10000" max_interval="20000" /&gt;
           &lt;FD shun="true" up_thread="true" down_thread="true" /&gt;
           &lt;VERIFY_SUSPECT timeout="1500" up_thread="false" down_thread="false" /&gt;
           &lt;pbcast.NAKACK gc_lag="50" max_xmit_size="8192" retransmit_timeout="600,1200,2400,4800"
           up_thread="false" down_thread="false" /&gt;
           &lt;UNICAST timeout="600,1200,2400" window_size="100" min_threshold="10" down_thread="false" /&gt;
           &lt;pbcast.STABLE desired_avg_gossip="20000" up_thread="false" down_thread="false" /&gt;
           &lt;FRAG frag_size="8192" down_thread="false" up_thread="false" /&gt;
           &lt;pbcast.GMS join_timeout="5000" join_retry_timeout="2000" shun="true"
           print_local_addr="true" /&gt;
           &lt;pbcast.STATE_TRANSFER up_thread="false" down_thread="false" /&gt;
           &lt;/config&gt;
           &lt;/attribute&gt;
  
           &lt;!-- The max amount of time (in milliseconds) we wait until the
           initial state (ie. the contents of the cache) are retrieved from
           existing members in a clustered environment
           --&gt;
           &lt;attribute name="InitialStateRetrievalTimeout"&gt;5000&lt;/attribute&gt;
  
           &lt;!-- Number of milliseconds to wait until all responses for a
           synchronous call have been received.
           --&gt;
           &lt;attribute name="SyncReplTimeout"&gt;10000&lt;/attribute&gt;
  
           &lt;!-- Max number of milliseconds to wait for a lock acquisition --&gt;
           &lt;attribute name="LockAcquisitionTimeout"&gt;15000&lt;/attribute&gt;
  
           &lt;!-- Name of the eviction policy class. --&gt;
           &lt;attribute name="EvictionPolicyClass"&gt;org.jboss.cache.eviction.LRUPolicy&lt;/attribute&gt;
  
           &lt;!-- Specific eviction policy configurations. This is LRU --&gt;
           &lt;attribute name="EvictionPolicyConfig"&gt;
           &lt;config&gt;
           &lt;attribute name="wakeUpIntervalSeconds"&gt;5&lt;/attribute&gt;
           &lt;!-- Cache wide default --&gt;
           &lt;region name="/_default_"&gt;
           &lt;attribute name="maxNodes"&gt;5000&lt;/attribute&gt;
           &lt;attribute name="timeToLiveSeconds"&gt;1000&lt;/attribute&gt;
           &lt;!-- Maximum time an object is kept in cache regardless of idle time --&gt;
           &lt;attribute name="maxAgeSeconds"&gt;120&lt;/attribute&gt;
           &lt;/region&gt;
  
           &lt;region name="/org/jboss/data"&gt;
           &lt;attribute name="maxNodes"&gt;5000&lt;/attribute&gt;
           &lt;attribute name="timeToLiveSeconds"&gt;1000&lt;/attribute&gt;
           &lt;/region&gt;
  
           &lt;region name="/org/jboss/test/data"&gt;
           &lt;attribute name="maxNodes"&gt;5&lt;/attribute&gt;
           &lt;attribute name="timeToLiveSeconds"&gt;4&lt;/attribute&gt;
           &lt;/region&gt;
           &lt;/config&gt;
           &lt;/attribute&gt;
  
           &lt;!-- New 1.3.x cache loader config block --&gt;
           &lt;attribute name="CacheLoaderConfiguration"&gt;
           &lt;config&gt;
           &lt;!-- if passivation is true, only the first cache loader is used; the rest are ignored --&gt;
           &lt;passivation&gt;false&lt;/passivation&gt;
           &lt;preload&gt;/a/b, /allTempObjects, /some/specific/fqn&lt;/preload&gt;
           &lt;shared&gt;false&lt;/shared&gt;
  
           &lt;!-- we can now have multiple cache loaders, which get chained --&gt;
           &lt;cacheloader&gt;
           &lt;class&gt;org.jboss.cache.loader.FileCacheLoader&lt;/class&gt;
           &lt;!-- same as the old CacheLoaderConfig attribute --&gt;
           &lt;properties&gt;
           location=/tmp/myFileStore
           &lt;/properties&gt;
           &lt;!-- whether the cache loader writes are asynchronous --&gt;
           &lt;async&gt;false&lt;/async&gt;
           &lt;!-- only one cache loader in the chain may set fetchPersistentState to true.
           An exception is thrown if more than one cache loader sets this to true. --&gt;
           &lt;fetchPersistentState&gt;true&lt;/fetchPersistentState&gt;
           &lt;!-- determines whether this cache loader ignores writes - defaults to false. --&gt;
           &lt;ignoreModifications&gt;false&lt;/ignoreModifications&gt;
           &lt;!-- if set to true, purges the contents of this cache loader when the cache starts up.
           Defaults to false. --&gt;
           &lt;purgeOnStartup&gt;false&lt;/purgeOnStartup&gt;
           &lt;/cacheloader&gt;
  
           &lt;cacheloader&gt;
           &lt;class&gt;org.jboss.cache.loader.JDBCCacheLoader&lt;/class&gt;
           &lt;!-- same as the old CacheLoaderConfig attribute --&gt;
           &lt;properties&gt;
           cache.jdbc.driver=com.mysql.jdbc.Driver
           cache.jdbc.url=jdbc:mysql://localhost:3306/jbossdb
           cache.jdbc.user=root
           cache.jdbc.password=
           &lt;/properties&gt;
           &lt;!-- whether the cache loader writes are asynchronous --&gt;
           &lt;async&gt;true&lt;/async&gt;
           &lt;!-- only one cache loader in the chain may set fetchPersistentState to true.
           An exception is thrown if more than one cache loader sets this to true. --&gt;
           &lt;fetchPersistentState&gt;false&lt;/fetchPersistentState&gt;
           &lt;!-- determines whether this cache loader ignores writes - defaults to false. --&gt;
           &lt;ignoreModifications&gt;true&lt;/ignoreModifications&gt;
           &lt;!-- if set to true, purges the contents of this cache loader when the cache starts up.
           Defaults to false. --&gt;
           &lt;purgeOnStartup&gt;false&lt;/purgeOnStartup&gt;
           &lt;/cacheloader&gt;
  
           &lt;/config&gt;
           &lt;/attribute&gt;
  
  
           &lt;/mbean&gt;
           &lt;/server&gt;     </programlisting>
  
        <para>The PropertyConfigurator.configure() method needs to have as
           argument a filename which is located on the classpath; it will use be used
           to configure JBoss Cache from the properties defined in it. Note that
           this configuration file is used to configure JBoss Cache both as a
           standalone cache, and as an MBean if run inside the JBoss
           container.
           <footnote>
              <para>We will switch to using an XMBean in a future release.</para>
           </footnote>
        </para>
     </section>
  
     <section>
        <title>
           Definition of XML attributes
        </title>
        <para>A list of definitions of each of the XML attributes used above:</para>
  
        <informaltable frame="all">
           <tgroup cols="2">
              <tbody>
                 <row>
                    <entry>
                       <para>Name</para>
                    </entry>
  
                    <entry>
                       <para>Description</para>
                    </entry>
                 </row>
                 <row>
                    <entry>
                       <para>MarshallerClass</para>
                    </entry>
  
                    <entry>
                       <para>An instance of org.jboss.cache.marshall.Marshaller used to serialize data to byte streams.
                          Defaults to o.j.c.m.VersionAwareMarshaller if not specified.
                       </para>
                    </entry>
                 </row>
                 <row>
                    <entry>
                       <para>BuddyReplicationConfig</para>
                    </entry>
  
                    <entry>
                       <para>An XML element that contains detailed buddy replication
                          configuration. See section above on Buddy Replication.
                       </para>
                    </entry>
                 </row>
  
                 <row>
                    <entry>
                       <para>CacheLoaderConfiguration</para>
                    </entry>
  
                    <entry>
                       <para>An XML element that contains detailed cache loader
                          configuration. See section above on Cache Loaders.
                       </para>
                    </entry>
                 </row>
  
                 <row>
                    <entry>
                       <para>CacheMode</para>
                    </entry>
  
                    <entry>
                       <para>LOCAL, REPL_SYNC, REPL_ASYNC, INVALIDATION_SYNC or
                          INVALIDATION_ASYNC
                       </para>
                    </entry>
                 </row>
  
                 <row>
                    <entry>
                       <para>ClusterConfig</para>
                    </entry>
  
                    <entry>
                       <para>The configuration of the underlying JGroups stack.
                          Ignored if
                          <literal>MultiplexerService</literal>
                          and
                          <literal>MultiplexerStack</literal>
                          are used.
                          See the various *-service.xml files in the source distribution
                          <literal>etc/META-INF</literal>
                          folder for examples.
                          See the
                          <ulink url="http://www.jgroups.org">JGroups documentation</ulink>
                          or the
                          <ulink url="http://wiki.jboss.org/wiki/Wiki.jsp?page=JGroups">JGroups wiki page</ulink>
                          for more information.
                       </para>
                    </entry>
                 </row>
  
                 <row>
                    <entry>
                       <para>ClusterName</para>
                    </entry>
  
                    <entry>
                       <para>Name of cluster. Needs to be the same for all nodes in a
                          cluster in order for them to communicate with each other.
                       </para>
                    </entry>
                 </row>
  
                 <row>
                    <entry>
                       <para>EvictionPolicyClass</para>
                    </entry>
  
                    <entry>
                       <para>The name of a class implementing EvictionPolicy. Deprecated;
                          it is preferable to configure the eviction policy class as
                          part of the
                          <literal>EvictionPolicyConfig</literal>
                          .
                       </para>
                    </entry>
                 </row>
  
                 <row>
                    <entry>
                       <para>EvictionPolicyConfig</para>
                    </entry>
  
                    <entry>
                       <para>Configuration parameter for the specified eviction policy.
                          Note that the content is provider specific.
                       </para>
                    </entry>
                 </row>
  
                 <row>
                    <entry>
                       <para>FetchInMemoryState (renamed from
                          FetchStateOnStartup)
                       </para>
                    </entry>
  
                    <entry>
                       <para>Whether or not to acquire the initial in-memory state from
                          existing members. Allows for hot/cold caches (true/false). Also
                          see the fetchPersistentState element in
                          CacheLoaderConfiguration.
                       </para>
                    </entry>
                 </row>
  
                 <row>
                    <entry>
                       <para>InactiveOnStartup</para>
                    </entry>
  
                    <entry>
                       <para>Whether or not the entire tree is inactive upon startup,
                          only responding to replication messages after
                          <literal>activateRegion()</literal>
                          is called to activate one or
                          more parts of the tree. If true, property
                          <literal>FetchInMemoryState</literal>
                          is ignored. This property
                          should only be set to true if
                          <literal>UseRegionBasedMarshalling</literal>
                          is also
                          <literal>true</literal>
                          .
                       </para>
                    </entry>
                 </row>
  
                 <row>
                    <entry>
                       <para>InitialStateRetrievalTimeout</para>
                    </entry>
  
                    <entry>
                       <para>Time in milliseconds to wait for initial state
                          retrieval. This should be longer than
                          <literal>LockAcquisitionTimeout</literal>
                          as the node
                          providing state may need to wait that long to acquire
                          necessary read locks on the cache.
                       </para>
                    </entry>
                 </row>
  
  
                 <row>
                    <entry>
                       <para>IsolationLevel</para>
                    </entry>
  
                    <entry>
                       <para>Node locking isolation level : SERIALIZABLE, REPEATABLE_READ
                          (default), READ_COMMITTED, READ_UNCOMMITTED, and NONE. Note that this is ignored if
                          NodeLockingScheme is OPTIMISTIC. Case doesn't matter. See documentation on Transactions and
                          Concurrency for more details.
                       </para>
                    </entry>
                 </row>
  
                 <row>
                    <entry>
                       <para>LockAcquisitionTimeout</para>
                    </entry>
  
                    <entry>
                       <para>Time in milliseconds to wait for a lock to be acquired. If
                          a lock cannot be acquired an exception will be thrown.
                       </para>
                    </entry>
                 </row>
  
                 <row>
                    <entry>
                       <para>MultiplexerService</para>
                    </entry>
  
                    <entry>
                       <para>The JMX object name of the service that defines the JGroups multiplexer.
                          In JBoss AS 5 this service is normally defined in the jgroups-multiplexer.sar.
                          If this attribute is defined, the cache will look up the multiplexer service
                          in JMX and will use it to obtain a multiplexed JGroups channel. The configuration
                          of the channel will be that associated with
                          <literal>MultiplexerStack</literal>
                          .
                          The
                          <literal>ClusterConfig</literal>
                          attribute will be ignored.
                       </para>
                    </entry>
                 </row>
  
                 <row>
                    <entry>
                       <para>MultiplexerStack</para>
                    </entry>
  
                    <entry>
                       <para>The name of the JGroups stack to be used with the TreeCache cluster.
                          Stacks are defined in the configuration of the external
                          <literal>MultiplexerService</literal>
                          discussed above. In JBoss AS 5 this is normally done in the
                          jgroups-multiplexer.sar\META-INF\multiplexer-stacks.xml file.
                          The default stack is
                          <literal>udp</literal>
                          . This attribute is used in conjunction with
                          <literal>MultiplexerService</literal>
                          .
                       </para>
                    </entry>
                 </row>
  
                 <row>
                    <entry>
                       <para>NodeLockingScheme</para>
                    </entry>
  
                    <entry>
                       <para>May be PESSIMISTIC (default) or OPTIMISTIC. See documentation on Transactions and Concurrency
                          for more details.
                       </para>
                    </entry>
                 </row>
  
                 <row>
                    <entry>
                       <para>ReplicationVersion</para>
                    </entry>
                    <entry>
                       <para>Tells the cache to serialize cluster traffic
                          in a format consistent with that used by the given release
                          of JBoss Cache. Different JBoss Cache versions use different
                          wire formats; setting this attribute tells a cache from a later
                          release to serialize data using the format from an earlier
                          release. This allows caches from different releases to
                          interoperate. For example, a 1.2.4.SP2 cache could have this
                          value set to "1.2.3", allowing it to interoperate with a 1.2.3
                          cache. Valid values are a dot-separated release number, with
                          any SP qualifer also separated by a dot, e.g. "1.2.3" or "1.2.4.SP2".
                       </para>
                    </entry>
                 </row>
  
                 <row>
                    <entry>
                       <para>ReplQueueInterval</para>
                    </entry>
  
                    <entry>
                       <para>Time in milliseconds for elements from the replication
                          queue to be replicated.
                       </para>
                    </entry>
                 </row>
  
                 <row>
                    <entry>
                       <para>ReplQueueMaxElements</para>
                    </entry>
  
                    <entry>
                       <para>Max number of elements in the replication queue until
                          replication kicks in.
                       </para>
                    </entry>
                 </row>
  
                 <row>
                    <entry>
                       <para>SyncCommitPhase</para>
                    </entry>
  
                    <entry>
                       <para>This option is used to control the behaviour of the commit part of a 2-phase commit protocol,
                          when
                          using REPL_SYNC (does not apply to other cache modes). By default this is set to
                          <literal>false</literal>
                          . There is a performance penalty to enabling this, especially when running
                          in a large cluster, but the upsides are greater cluster-wide data integrity. See the chapter on
                          Clustered Caches for more information on this.
                       </para>
                    </entry>
                 </row>
  
                 <row>
                    <entry>
                       <para>SyncReplTimeout</para>
                    </entry>
  
                    <entry>
                       <para>For synchronous replication: time in milliseconds to wait
                          until replication acks have been received from all nodes in the
                          cluster.
                       </para>
                    </entry>
                 </row>
  
                 <row>
                    <entry>
                       <para>SyncRollbackPhase</para>
                    </entry>
  
                    <entry>
                       <para>This option is used to control the behaviour of the rollback part of a 2-phase commit
                          protocol, when
                          using REPL_SYNC (does not apply to other cache modes). By default this is set to
                          <literal>false</literal>
                          . There is a performance penalty to enabling this, especially when running
                          in a large cluster, but the upsides are greater cluster-wide data integrity. See the chapter on
                          Clustered Caches for more information on this.
                       </para>
                    </entry>
                 </row>
  
                 <row>
                    <entry>
                       <para>TransactionManagerLookupClass</para>
                    </entry>
  
                    <entry>
                       <para>The fully qualified name of a class implementing
                          TransactionManagerLookup. Default is
                          JBossTransactionManagerLookup. There is also an option of
                          DummyTransactionManagerLookup for example.
                       </para>
                    </entry>
                 </row>
  
                 <row>
                    <entry>
                       <para>UseInterceptorMbeans</para>
                    </entry>
  
                    <entry>
                       <para>Specifies whether each interceptor should have an associated
                          mbean registered. Interceptor mbeans are used to capture statistics
                          and display them in JMX. This setting enables or disables all such interceptor
                          mbeans. Default value is
                          <emphasis>true</emphasis>
                          .
                       </para>
                    </entry>
                 </row>
  
                 <row>
                    <entry>
                       <para>UseRegionBasedMarshalling</para>
                    </entry>
  
                    <entry>
                       <para>When unmarshalling replicated data, this option specifies whether or not to use
                          different classloaders (for different cache regions). This defaults to
                          <literal>false</literal>
                          if unspecified.
                       </para>
                    </entry>
                 </row>
  
                 <row>
                    <entry>
                       <para>UseReplQueue</para>
                    </entry>
  
                    <entry>
                       <para>For asynchronous replication: whether or not to use a
                          replication queue (true/false).
                       </para>
                    </entry>
                 </row>
  
              </tbody>
           </tgroup>
        </informaltable>
     </section>
     <section>
        <title>Overriding options</title>
        <para>
           As of JBoss Cache 1.3.0, a new API has been introduced, to allow you to override certain behaviour of the cache
           on a per invocation basis.
           This involves creating an instance of
           <literal>org.jboss.cache.config.Option</literal>
           , setting the options you wish to override on the
           <literal>Option</literal>
           object and passing it in as a parameter to overloaded versions of
           <literal>get()</literal>
           ,
           <literal>put()</literal>
           and
           <literal>remove()</literal>
           . See the javadocs on the
           <literal>Option</literal>
           class for details on these options.
        </para>
     </section>
  </chapter>
  
  
  1.1      date: 2007/01/19 17:01:00;  author: msurtani;  state: Exp;JBossCache/docs/JBossCache-UserGuide/en/modules/transactions.xml
  
  Index: transactions.xml
  ===================================================================
  <chapter id="transactions">
     <title>Transactions and Concurrency</title>
     <section>
        <title>Concurrent Access</title>
  
        <para>JBoss Cache uses a pessimistic locking scheme by default to prevent concurrent
           access to the same data. Optimistic locking may alternatively be used, and is discussed later.
        </para>
  
        <section>
           <title>Locks</title>
           <para>Locking is done internally, on a node-level. For example when we
              want to access "/a/b/c", a lock will be acquired for nodes "a", "b" and
              "c". When the same transaction wants to access "/a/b/c/d", since we
              already hold locks for "a", "b" and "c", we only need to acquire a lock
              for "d".
           </para>
           <para>Lock owners are either transactions (call is made within the scope of an existing transaction)
              or threads (no transaction associated with the call).
              Regardless, a transaction or a thread is internally transformed into
              an instance of
              <literal>GlobalTransaction</literal>
              , which is used as a globally unique ID
              for modifications across a cluster. E.g. when we run a two-phase commit
              protocol (see below) across the cluster, the
              <literal>GlobalTransaction</literal>
              uniquely
              identifies the unit of work across a cluster.
           </para>
  
           <para>Locks can be read or write locks. Write locks serialize read and
              write access, whereas read-only locks only serialize read access. When a
              write lock is held, no other write or read locks can be acquired. When a
              read lock is held, others can acquire read locks. However, to acquire
              write locks, one has to wait until all read locks have been released. When
              scheduled concurrently, write locks always have precedence over read
              locks. Note that (if enabled) read locks can be upgraded to write
              locks.
           </para>
  
           <para>Using read-write locks helps in the following scenario: consider a
              tree with entries "/a/b/n1" and "/a/b/n2". With write-locks, when Tx1
              accesses "/a/b/n1", Tx2 cannot access "/a/b/n2" until Tx1 has completed
              and released its locks. However, with read-write locks this is possible,
              because Tx1 acquires read-locks for "/a/b" and a read-write lock for
              "/a/b/n1". Tx2 is then able to acquire read-locks for "/a/b" as well, plus
              a read-write lock for "/a/b/n2". This allows for more concurrency in
              accessing the cache.
           </para>
        </section>
  
  
        <section>
           <title>Pessimistic locking</title>
           <para>By default, JBoss Cache uses pessimistic locking. Locking is not exposed directly to user. Instead, a
              transaction isolation level which provides different locking behaviour is configurable.
           </para>
           <section>
              <title>Isolation levels</title>
              <para>JBoss Cache supports the following transaction isolation levels, analogous to database ACID isolation
                 levels. A user can configure an instance-wide isolation level of NONE, READ_UNCOMMITTED, READ_COMMITTED,
                 REPEATABLE_READ, or SERIALIZABLE. REPEATABLE_READ is the default isolation level used.
              </para>
  
              <orderedlist>
                 <listitem>
                    <para>NONE. No transaction support is needed. There is no locking at
                       this level, e.g., users will have to manage the data integrity.
                       Implementations use no locks.
                    </para>
                 </listitem>
  
                 <listitem>
                    <para>READ_UNCOMMITTED. Data can be read anytime while write
                       operations are exclusive. Note that this level doesn't prevent the
                       so-called "dirty read" where data modified in Tx1 can be read in Tx2
                       before Tx1 commits. In other words, if you have the following
                       sequence,
                       <programlisting>
                          Tx1 Tx2
                          W
                          R
                       </programlisting>
  
                       using this isolation level will not Tx2 read operation.
                       Implementations typically use an exclusive lock for writes while reads
                       don't need to acquire a lock.
                    </para>
                 </listitem>
  
                 <listitem>
                    <para>READ_COMMITTED. Data can be read any time as long as there is no
                       write. This level prevents the dirty read. But it doesn’t prevent the
                       so-called ‘non-repeatable read’ where one thread reads the data twice
                       can produce different results. For example, if you have the following
                       sequence,
                       <programlisting>
                          Tx1 Tx2
                          R
                          W
                          R
                       </programlisting>
                    </para>
  
                    <para>where the second read in Tx1 thread will produce different
                       result.
                    </para>
  
                    <para>Implementations usually use a read-write lock; reads succeed
                       acquiring the lock when there are only reads, writes have to wait
                       until there are no more readers holding the lock, and readers are
                       blocked acquiring the lock until there are no more writers holding the
                       lock. Reads typically release the read-lock when done, so that a
                       subsequent read to the same data has to re-acquire a read-lock; this
                       leads to nonrepeatable reads, where 2 reads of the same data might
                       return different values. Note that, the write only applies regardless
                       of transaction state (whether it has been committed or not).
                    </para>
                 </listitem>
  
                 <listitem>
                    <para>REPEATABLE_READ. Data can be read while there is no write and
                       vice versa. This level prevents "non-repeatable read" but it does not
                       prevent the so-called "phantom read" where new data can be inserted
                       into the tree from the other transaction. Implementations typically
                       use a read-write lock. This is the default isolation level used.
                    </para>
                 </listitem>
  
                 <listitem>
                    <para>SERIALIZABLE. Data access is synchronized with exclusive locks.
                       Only 1 writer or reader can have the lock at any given time. Locks are
                       released at the end of the transaction. Regarded as very poor for performance and
                       thread/transaction concurrency.
                    </para>
                 </listitem>
              </orderedlist>
  
           </section>
        </section>
  
        <section>
           <title>Optimistic locking</title>
           <para>The motivation for optimistic locking is to improve concurrency. When a lot of threads have a lot of
              contention for access to the data tree, it can be inefficient to lock portions of the tree - for reading or
              writing - for the entire duration of a transaction as we do in pessimistic locking. Optimistic locking
              allows for greater concurrency of threads and transactions by using a technique called data versioning,
              explained here. Note that isolation levels (if configured) are ignored if optimistic locking is enabled.
           </para>
           <section>
              <title>Architecture</title>
              <para>Optimistic locking treats all method calls as transactional
                 <footnote>
                    <para>Because of this requirement, you must always have a transaction manager configured when using
                       optimistic locking.
                    </para>
                 </footnote>
                 . Even if you do not invoke a call within the scope of an ongoing transaction, JBoss Cache creates an
                 implicit transaction and commits this transaction when the invocation completes. Each transaction
                 maintains a transaction workspace, which contains a copy of the data used within the transaction.
              </para>
              <para>For example, if a transaction calls get("/a/b/c"), nodes a, b and c are copied from the main data tree
                 and into the workspace. The data is versioned and all calls in the transaction work on the copy of the
                 data rather than the actual data. When the transaction commits, it's workspace is merged back into the
                 underlying tree by matching versions. If there is a version mismatch - such as when the actual data tree
                 has a higher version than the workspace, perhaps if another transaction were to access the same data,
                 change it and commit before the first transaction can finish - the transaction throws a
                 <literal>RollbackException</literal>
                 when committing and the commit fails.
              </para>
              <para>Optimistic locking uses the same locks we speak of above, but the locks are only held for a very short
                 duration - at the start of a transaction to build a workspace, and when the transaction commits and has
                 to merge data back into the tree.
              </para>
              <para>
                 So while optimistic locking may occasionally fail if version validations fail or may run slightly slower
                 than pessimistic locking due to the inevitable overhead and extra processing of maintaining workspaces,
                 versioned data and validating on commit, it does buy you a near-SERIALIZABLE degree of data integrity
                 while maintaining a very high level of concurrency.
              </para>
           </section>
           <section>
              <title>Configuration</title>
              Optimistic locking is enabled by using the NodeLockingScheme XML attribute, and setting it to "OPTIMISTIC":
              <programlisting>
                 ...
                 &lt;!--
                 Node locking scheme:
                 OPTIMISTIC
                 PESSIMISTIC (default)
                 --&gt;
                 &lt;attribute name="NodeLockingScheme"&gt;OPTIMISTIC&lt;/attribute&gt;
                 ...
              </programlisting>
           </section>
        </section>
     </section>
  
  
     <section>
        <title>Transactional Support</title>
  
        <para>JBoss Cache can be configured to use transactions to bundle units of
           work, which can then be replicated as one unit. Alternatively, if
           transaction support is disabled, it is equivalent to setting AutoCommit to
           on where modifications are potentially
           <footnote>
              <para>Depending on whether interval-based asynchronous replication is used</para>
           </footnote>
           replicated after every change (if replication is
           enabled).
        </para>
  
        <para>What JBoss Cache does on every incoming call (e.g. put()) is:</para>
        <orderedlist>
           <listitem>
              <para>get the transaction associated with the thread</para>
           </listitem>
           <listitem>
              <para>register (if not already done) with the transaction manager to be notified when a transaction commits
                 or is rolled back.
              </para>
           </listitem>
        </orderedlist>
        <para>
           In order to do this, the cache has
           to be configured with an instance of a
           <literal>TransactionManagerLookup</literal>
           which
           returns a
           <literal>javax.transaction.TransactionManager</literal>
           .
        </para>
  
        <para>JBoss Cache ships with
           <literal>JBossTransactionManagerLookup</literal>
           and
           <literal>GenericTransactionManagerLookup</literal>
           . The
           <literal>JBossTransactionManagerLookup</literal>
           is able to bind to a running JBoss Application Server and retrieve a
           <literal>TransactionManager</literal>
           while the
           <literal>GenericTransactionManagerLookup</literal>
           is able to bind to most popular Java EE application servers and provide the same functionality. A dummy
           implementation -
           <literal>DummyTransactionManagerLookup</literal>
           - is also provided, which may be used for standalone JBoss Cache applications and unit tests running outside a
           Java EE Application Server. Being a dummy, however, this is just for demo and testing purposes and is not
           recommended for production use.
        </para>
        <para>The implementation of the
           <literal>JBossTransactionManagerLookup</literal>
           is as follows:
        </para>
  
        <programlisting>public class JBossTransactionManagerLookup implements TransactionManagerLookup {
  
           public JBossTransactionManagerLookup() {}
  
           public TransactionManager getTransactionManager() throws Exception {
           Object tmp=new InitialContext().lookup("java:/TransactionManager");
           return (TransactionManager)tmp;
           }
           }
        </programlisting>
  
        <para>The implementation looks up the JBoss Transaction Manager from
           JNDI and returns it.
        </para>
  
        <para>When a call comes in, the
           <literal>TreeCache</literal>
           gets the current transaction and
           records the modification under the transaction as key. (If there is no
           transaction, the modification is applied immediately and possibly
           replicated). So over the lifetime of the transaction all modifications
           will be recorded and associated with the transaction. Also, the
           <literal>TreeCache</literal>
           registers with the transaction to be notified of transaction committed or
           aborted when it first encounters the transaction.
        </para>
  
        <para>When a transaction rolls back, we undo the changes in the cache and
           release all locks.
        </para>
  
        <para>When the transaction commits, we initiate a two-phase commit
           protocol
           <footnote>
              <para>Only with synchronous replication or invalidation.</para>
           </footnote>
           : in the first phase, a PREPARE containing all modifications
           for the current transaction is sent to all nodes in the cluster. Each node
           acquires all necessary locks and applies the changes, and then sends back
           a success message. If a node in a cluster cannot acquire all locks, or
           fails otherwise, it sends back a failure message.
        </para>
  
        <para>The coordinator of the two-phase commit protocol waits for all
           responses (or a timeout, whichever occurs first). If one of the nodes in
           the cluster responds with FAIL (or we hit the timeout), then a rollback
           phase is initiated: a ROLLBACK message is sent to all nodes in the
           cluster. On reception of the ROLLBACK message, every node undoes the
           changes for the given transaction, and releases all locks held for the
           transaction.
        </para>
  
        <para>If all responses are OK, a COMMIT message is sent to all nodes in
           the cluster. On reception of a COMMIT message, each node applies the
           changes for the given transaction and releases all locks associated with
           the transaction.
        </para>
  
        <para>When we referred to 'transaction', we actually mean a global
           representation of a local transaction, which uniquely identifies a
           transaction across a cluster.
        </para>
  
        <section>
           <title>Example</title>
  
           <para>Let's look at an example of how to use JBoss Cache in a standalone (i.e.
              outside an application server) fashion with dummy transactions:
           </para>
  
           <programlisting>Properties prop = new Properties();
              prop.put(Context.INITIAL_CONTEXT_FACTORY, "org.jboss.cache.transaction.DummyContextFactory");
              User Transaction tx=(UserTransaction)new InitialContext(prop).lookup("UserTransaction");
              TreeCache tree = new TreeCache();
              PropertyConfigurator config = new PropertyConfigurator();
              config.configure(tree, "META-INF/replSync-service.xml");
              tree.createService(); // not necessary
              tree.startService(); // kick start tree cache
  
              try {
              tx.begin();
              tree.put("/classes/cs-101", "description", "the basics");
              tree.put("/classes/cs-101", "teacher", "Ben");
              tx.commit();
              }
              catch(Throwable ex) {
              try { tx.rollback(); } catch(Throwable t) {}
              }
           </programlisting>
  
           <para>The first lines obtain a user transaction using the 'JEE way' via
              JNDI. Note that we could also say
           </para>
  
           <para>
              <programlisting>UserTransaction tx = new DummyUserTransaction(DummyTransactionManager.getInstance());
              </programlisting>
           </para>
  
           <para>Then we create a new TreeCache and configure it using a
              PropertyConfigurator class and a configuration XML file (see below for a
              list of all configuration options).
           </para>
  
           <para>Next we start the cache. Then, we start a transaction (and
              associate it with the current thread internally). Any methods invoked on
              the cache will now be collected and only applied when the transaction is
              committed. In the above case, we create a node "/classes/cs-101" and add
              2 elements to its map. Assuming that the cache is configured to use
              synchronous replication, on transaction commit the modifications are
              replicated. If there is an exception in the methods (e.g. lock
              acquisition failed), or in the two-phase commit protocol applying the
              modifications to all nodes in the cluster, the transaction is rolled
              back.
           </para>
        </section>
     </section>
  </chapter>
  
  
  1.1      date: 2007/01/19 17:01:00;  author: msurtani;  state: Exp;JBossCache/docs/JBossCache-UserGuide/en/modules/basic_api.xml
  
  Index: basic_api.xml
  ===================================================================
  <chapter id="api">
     <title>Basic API</title>
  
     <para>Here's some sample code before we dive into the API itself:</para>
  
     <programlisting>TreeCache tree = new TreeCache();
        tree.setClusterName("demo-cluster");
        tree.setClusterProperties("default.xml"); // uses defaults if not provided
        tree.setCacheMode(TreeCache.REPL_SYNC);
        tree.createService(); // not necessary, but is same as MBean lifecycle
        tree.startService(); // kick start tree cache
        tree.put("/a/b/c", "name", "Ben");
        tree.put("/a/b/c/d", "uid", new Integer(322649));
        Integer tmp = (Integer) tree.get("/a/b/c/d", "uid");
        tree.remove("/a/b");
        tree.stopService();
        tree.destroyService(); // not necessary, but is same as MBean lifecycle
     </programlisting>
  
     <para>The sample code first creates a
        <literal>TreeCache</literal>
        instance and then
        configures it. There is another constructor which accepts a number of
        configuration options. However, the
        <literal>TreeCache</literal>
        can be configured entirely
        from an XML file (shown later) and we don't recommend manual configuration
        as shown in the sample.
     </para>
  
     <para>The cluster name, properties of the underlying JGroups stack, and
        cache mode (synchronous replication) are configured first (a list of
        configuration options is shown later). Then we start the
        <literal>TreeCache</literal>
        . If
        replication is enabled, this will make the
        <literal>TreeCache</literal>
        join the cluster, and acquire initial state from an existing node.
     </para>
  
     <para>Then we add 2 items into the cache: the first element creates a node
        "a" with a child node "b" that has a child node "c". (
        <literal>TreeCache</literal>
        by default
        creates intermediary nodes that don't exist). The key "name" is then
        inserted into the "/a/b/c" node, with a value of "Ben".
     </para>
  
     <para>The other element will create just the subnode "d" of "c" because
        "/a/b/c" already exists. It binds the integer 322649 under key
        "uid".
     </para>
  
     <para>The resulting tree looks like this:</para>
  
     <figure>
        <title>Sample Tree Nodes</title>
  
        <mediaobject>
           <imageobject>
              <imagedata fileref="images/TreeNodeExample.gif"/>
           </imageobject>
        </mediaobject>
     </figure>
  
     <para>The
        <literal>TreeCache</literal>
        has 4 nodes "a", "b", "c" and "d". Nodes "/a/b/c" has
        values "name" associated with "Ben" in its map, and node "/a/b/c/d"
        has values "uid" and 322649.
     </para>
  
     <para>Each node can be retrieved by its absolute name (e.g. "/a/b/c") or
        by navigating from parent to children (e.g. navigate from "a" to "b", then
        from "b" to "c").
     </para>
  
     <para>The next method in the example gets the value associated with
        key="uid" in node "/a/b/c/d", which is the integer 322649.
     </para>
  
     <para>The remove() method then removes node "/a/b" and all subnodes
        recursively from the cache. In this case, nodes "/a/b/c/d", "/a/b/c" and
        "/a/b" will be removed, leaving only "/a".
     </para>
  
     <para>Finally, the
        <literal>TreeCache</literal>
        is stopped. This will cause it to leave the
        cluster, and every node in the cluster will be notified. Note that
        <literal>TreeCache</literal>
        can be stopped and started again. When it is stopped, all
        contents will be deleted. And when it is restarted, if it joins a cache
        group, the state will be replicated initially. So potentially you can
        recreate the contents.
     </para>
  
     <para>In the sample, replication was enabled, which caused the 2 put() and
        the 1 remove() methods to replicated their changes to all nodes in the
        cluster. The get() method was executed on the local cache only.
     </para>
  
     <para>Keys into the cache can be either strings separated by slashes
        ('/'), e.g. "/a/b/c", or they can be fully qualified names Fqns . An Fqn
        is essentially a list of Objects that need to implement hashCode() and
        equals(). All strings are actually transformed into Fqns internally. Fqns
        are more efficient than strings, for example:
     </para>
  
     <programlisting>String n1 = "/300/322649";
        Fqn n2 = new Fqn(new Object{new Integer(300), new Integer(322649)});
     </programlisting>
  
     <para>In this example, we want to access a node that has information for
        employee with id=322649 in department with id=300. The string version
        needs two map lookups on Strings, whereas the Fqn version needs two
        map lookups on Integers. In a large hashtable, the hashCode() method
        for String may have collisions, leading to actual string comparisons.
        Also, clients of the cache may already have identifiers for their objects
        in Object form, and don't want to transform between Object and Strings,
        preventing unnecessary copying.
     </para>
  
     <para>Note that the modification methods are put() and remove(). The only
        get method is get().
     </para>
  
     <para>There are 2 put() methods
        <footnote>
           <para>Plus their equivalent helper methods taking a String as node
              name.
           </para>
        </footnote>
        :
        <literal>put(Fqn node, Object key, Object key)</literal>
        and
        <literal>put(Fqn node, Map values)</literal>
        . The former takes the
        node name, creates it if it doesn't yet exist, and put the key and value
        into the node's map, returning the previous value. The latter takes a
        map of keys and values and adds them to the node's map,
        overwriting existing keys and values. Content that is not in the new
        map remains in the node's map.
     </para>
  
     <para>There are 3 remove() methods:
        <literal>remove(Fqn node, Object
           key)
        </literal>
        ,
        <literal>remove(Fqn node)</literal>
        and
        <literal>removeData(Fqn node)</literal>
        . The first removes the given key
        from the node. The second removes the entire node and all subnodes, and
        the third removes all elements from the given node's map.
     </para>
  
     <para>The get methods are:
        <literal>get(Fqn node)</literal>
        and
        <literal>get(Fqn node, Object key)</literal>
        . The former returns a
        Node
        <footnote>
           <para>This is mainly used internally, and we may decide to remove
              public access to the Node in a future release.
           </para>
        </footnote>
        object, allowing for direct navigation, the latter returns
        the value for the given key for a node.
     </para>
  
     <para>Also, the
        <literal>TreeCache</literal>
        has a number of getters and setters. Since the
        API may change at any time, we recommend the Javadoc for up-to-date
        information.
     </para>
  </chapter>
  
  



More information about the jboss-cvs-commits mailing list