<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>