1 Reply Latest reply on Apr 12, 2011 12:34 PM by jaysmith

    CacheLoader store not recreating keys/values

    jaysmith

      Hi there,

       

      I have a simple proof of concept JUnit that creates a cache, creates a node, creates a test object and adds this object to the node.  The cache is configured with a FileCacheLoader, passivation disabled and eviction happens after 2 seconds.

      What I would expect to see is that when the object is added to the node, both RAM and disk are written to, after 2 seconds then memory should be cleared. After that time, a read should load the node and the object that the node contains back into memory.

      However, what I'm actually seeing is different. After 2 seconds has elapsed and the node has been evicted from RAM, a read recreates the node from the persistent store but it is empty i.e. the object that the node orginally stored is no longer there.

       

      My configuration:

      <?xml version="1.0" encoding="UTF-8"?>

      <jbosscache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:jboss:jbosscache-core:config:3.2">


         <!--
            isolation levels supported: READ_COMMITTED and REPEATABLE_READ
            nodeLockingSchemes: mvcc, pessimistic (deprecated), optimistic (deprecated)
         -->
         <locking
               isolationLevel="REPEATABLE_READ"
               lockParentForChildInsertRemove="false"
               lockAcquisitionTimeout="20000"
               nodeLockingScheme="mvcc"
               writeSkewCheck="false"
               useLockStriping="true"
               concurrencyLevel="500"/>

         <!--
            Used to register a transaction manager and participate in ongoing transactions.
            -->
         <transaction
               transactionManagerLookupClass="org.jboss.cache.transaction.GenericTransactionManagerLookup"
               syncRollbackPhase="false"
               syncCommitPhase="false"/>

         <!--
            Used to register JMX statistics in any available MBean server
            -->
         <jmxStatistics enabled="false"/>

         <!--
            If region based marshalling is used, defines whether new regions are inactive on startup.
         -->
         <startup regionsInactiveOnStartup="true"/>

         <!--
            Used to register JVM shutdown hooks.
            hookBehavior: DEFAULT, REGISTER, DONT_REGISTER
         -->
         <shutdown hookBehavior="DEFAULT"/>

         <!--
            Used to define async listener notification thread pool size
         -->
         <listeners asyncPoolSize="1" asyncQueueSize="100000"/>

         <!--
            Used to enable invocation batching and allow the use of Cache.startBatch()/endBatch() methods.
         -->
         <invocationBatching enabled="false"/>

         <!--
            serialization related configuration, used for replication and cache loading
         -->
         <serialization objectInputStreamPoolSize="12" objectOutputStreamPoolSize="14" version="3.0.0"
               marshallerClass="org.jboss.cache.marshall.VersionAwareMarshaller" useLazyDeserialization="false"
               useRegionBasedMarshalling="false"/>

         <!--
            Eviction configuration.  WakeupInterval defines how often the eviction thread runs, in milliseconds.  0 means
            the eviction thread will never run.
         -->
         <eviction wakeUpInterval="500">
            <default algorithmClass="org.jboss.cache.eviction.LRUAlgorithm" eventQueueSize="200000">
               <property name="maxNodes" value="5000" />
               <property name="timeToLive" value="1000" />
            </default>
            <region name="/griffin_peter">
               <property name="timeToLive" value="2000" />
               <!--<property name="maxAge" value="10000" />-->
            </region>
            <region name="/org/jboss/data2" algorithmClass="org.jboss.cache.eviction.FIFOAlgorithm" eventQueueSize="100000">
               <property name="maxNodes" value="3000" />
               <property name="minTimeToLive" value="4000" />
            </region>
         </eviction>

         <!--
            Cache loaders.

            If passivation is enabled, state is offloaded to the cache loaders ONLY when evicted.  Similarly, when the state
            is accessed again, it is removed from the cache loader and loaded into memory.

            Otherwise, state is always maintained in the cache loader as well as in memory.

            Set 'shared' to true if all instances in the cluster use the same cache loader instance, e.g., are talking to the
            same database.
         -->
         <loaders passivation="false" shared="false">
            <preload>
               <node fqn="/griffin_peter"/>
            </preload>

            <loader class="org.jboss.cache.loader.FileCacheLoader" async="true" fetchPersistentState="true"
                    ignoreModifications="false" purgeOnStartup="true">
               <properties>
                  check.character.portability=false
                  location=/web/dev/jboss-cache
               </properties>
               <singletonStore enabled="false" class="org.jboss.cache.loader.SingletonStoreCacheLoader">
                  <properties>
                     pushStateWhenCoordinator=true
                     pushStateWhenCoordinatorTimeout=20000
                  </properties>
               </singletonStore>
            </loader>
         </loaders>
      </jbosscache>

       

      Here is the code I have (based on code in JBoss Cache User Guide 3.x.x)

       

      package tests.cache.loader;

       

      import org.jboss.cache.Cache;
      import org.jboss.cache.CacheFactory;
      import org.jboss.cache.DefaultCacheFactory;
      import org.jboss.cache.Fqn;
      import org.jboss.cache.Node;

      import org.junit.AfterClass;
      import org.junit.BeforeClass;
      import org.junit.Test;

       

      public class CustomCacheLoaderTest {
          /** cache. */
          private static Cache<String, Object> cache = null;

          class TestTO {
              private String field1;
              public String toString() {
                  return this.getClass().getSimpleName() + ": field1=" + field1;
              }
          }

          @AfterClass
          public final static void afterClass() throws Exception {
              cache.stop();
              cache.destroy();
              cache = null;
          }

          @BeforeClass
          public final static void beforeClass() throws Exception {
              CacheFactory cacheFactory = new DefaultCacheFactory();
              cache = cacheFactory.createCache("jboss-cache-configuration.xml");
              cache.create();
              cache.start();
          }

          @Test
          public final void put() throws Exception {
              Object listener = new CustomCacheListener();
              cache.addCacheListener(listener);
              Node rootNode = cache.getRoot();
              Fqn peterGriffinFqn = Fqn.fromString("/griffin_peter");
              Node peterGriffinNode = rootNode.addChild(peterGriffinFqn);

       

              TestTO testTO = new TestTO();
              testTO.field1 = "This is a test string!";
              peterGriffinNode.put("testTO", testTO);
              System.out.println("Fqn: /griffin_peter: Key=testTO; Value="
                      + cache.get("/griffin_peter", "testTO"));

       

              System.out.println("\nWaiting for 4000 milliseconds ...");
              Thread.sleep(4000);
              java.util.Map data = cache.getData(Fqn.fromString("/griffin_peter"));
              System.out.println("data.size()=" + data.size());
              System.out.println("Fqn: /griffin_peter: Key=testTO; Value="
                      + cache.get("/griffin_peter", "testTO"));
          }

      }

       

      this outputs:

      Fqn: /griffin_peter: Key=testTO; Value=TestTO: field1=This is a test string!

       

      Waiting for 4000 milliseconds ...

      data.size()=0

      Fqn: /griffin_peter: Key=testTO; Value=null

      When I plug a Cache Listener in, the output is:

      09:04:07.678 [CustomCacheListener] Created node: /griffin_peter

      09:04:07.803 [CustomCacheListener] Created node: /griffin_peter

      09:04:07.819 [CustomCacheListener] Visited node: /griffin_peter

      09:04:07.819 [CustomCacheListener] Visited node: /griffin_peter

      Fqn: /griffin_peter: Key=testTO; Value=TestTO: field1=This is a test string!

       

      Waiting for 4000 milliseconds ...

      09:04:09.866 [CustomCacheListener] Evicted node: /griffin_peter

      09:04:09.866 [CustomCacheListener] Evicted node: /griffin_peter

      09:04:11.819 [CustomCacheListener] Created node: /griffin_peter

      09:04:11.819 [CustomCacheListener] Created node: /griffin_peter

      data.size()=0

      09:04:11.819 [CustomCacheListener] Visited node: /griffin_peter

      09:04:11.819 [CustomCacheListener] Visited node: /griffin_peter

      Fqn: /griffin_peter: Key=testTO; Value=null

      So, the RAM is evicted at 09:04:09.866, node is recreated from backend store at 09:04:11.819 but the value for key testTO is null when it should be a TestTO object with field1 populated.

      Any ideas why the backend store isn't storing keys and values?

        • 1. Re: CacheLoader store not recreating keys/values
          jaysmith

          Problem was with the

          <serialization objectInputStreamPoolSize="12" objectOutputStreamPoolSize="14" version="3.0.0"

                   marshallerClass="org.jboss.cache.marshall.VersionAwareMarshaller" useLazyDeserialization="false"

                   useRegionBasedMarshalling="false"/>

          portion of the configuration XML.

           

          Removing this from the configuration works and The class is persisting to the file location like a demon now he he

           

          17:04:46.383 [CustomCacheListener] Created node: /griffin_peter

          17:04:46.399 [CustomCacheListener] Created node: /griffin_peter

          17:04:46.399 [CustomCacheListener] Loaded node: /griffin_peter

          17:04:46.399 [CustomCacheListener] Loaded node: /griffin_peter

          17:04:46.399 [CustomCacheListener] Visited node: /griffin_peter

          17:04:46.399 [CustomCacheListener] Visited node: /griffin_peter

          Fqn: /griffin_peter: Key=testTO; Value=TestTO: field1=This is a test string!

           

          Waiting for 4000 milliseconds ...

          17:04:48.602 [CustomCacheListener] Evicted node: /griffin_peter

          17:04:48.602 [CustomCacheListener] Evicted node: /griffin_peter

          17:04:50.399 [CustomCacheListener] Created node: /griffin_peter

          17:04:50.399 [CustomCacheListener] Created node: /griffin_peter

          data.size()=1

          17:04:50.399 [CustomCacheListener] Visited node: /griffin_peter

          17:04:50.399 [CustomCacheListener] Visited node: /griffin_peter

          Fqn: /griffin_peter: Key=testTO; Value=TestTO: field1=This is a test string!