2 Replies Latest reply on May 17, 2011 10:26 AM by galder.zamarreno

    How do I start multiple caches atomically?

    sirianni

      I'm getting NamedCacheNotFoundException errors in my application. 

       

      It looks this issue is what this code was added for:

       

      {code}

               if (embeddedCacheManager.getGlobalConfiguration().isStrictPeerToPeer()) {

                  // lets see if the cache is *defined* and perhaps just not started.

                  if (isDefined(cacheName)) {

                     log.info("Will try and wait for the cache to start");

                     long giveupTime = System.currentTimeMillis() + 30000; // arbitrary (?) wait time for caches to start

                     while (cr == null && System.currentTimeMillis() < giveupTime) {

                        Thread.sleep(100);

                        cr = gcr.getNamedComponentRegistry(cacheName);

                     }

                  }

               }

      {code}

       

      The problem is similar to that discussed here:

      http://lists.jboss.org/pipermail/infinispan-dev/2010-September/006379.html

       

      Basically, the CacheManager is starting (and connecting to the underlying JGroups channel) before all the named caches are created.  It seems that the first call to getCache() implicitly starts the GlobalComponentRegistry which starts the JGroups channel.

       

      My use case is slightly different though.  I know ahead of time what caches I'm creating.  Here's how I have it currently written:

       

      {code}

      Cache foo = cacheManager.getCache("foo"); // Starts JChannel - bar and baz not yet defined/created

      ...

      // Until bar is defined/created, other nodes in the cluster get NamedCacheNotFoundException when trying to replicate updates to bar

      Cache bar = cacheManager.getCache("bar");

       

      ...

      cacheManager.start(); // Does some JMX registration but doesn't really start() the cache manager - that happened already

      {code}

       

       

      Here is my current workaround

      {code}

      cacheManager.defineConfiguration("foo", new Configuration());  // Hack to define the cache but not start it

      ...

      cacheManager.defineConfiguration("bar", new Configuration());

       

      ...

      cacheManager.start(); // Does some JMX stuff but doesn't really start the cache subsystem

       

      ...

      Cache foo = cacheManager.getCache("foo"); // Implicitly starts the cache subsystem - JChannel connected

       

      // Cross my fingers that 30 seconds doesn't elapse so that the retry loop in InboundInvocationHandlerImpl works

       

      Cache bar = cacheManager.getCache("bar");

      {code}

       

       

      Here is how I'd like it to work:

      {code}

      Cache foo = cacheManager.getCache("foo");  // Defines the cache and creates the object, but doesn't actually "start" it

      ...

      Cache bar = cacheManager.getCache("bar");

       

      ...

      cacheManager.start(); // Both caches started atomically

      {code}

       

      Is there a better way to do it than my workaround?  If not, does the above seem like a good suggestion to you guys? 

       

      It seems like there should be a way for me to explicitly start the CacheManager (and by implication the underlying JGroups channel) *after* I've defined and created all the caches, rather than implicitly happening on the first call to getCache() and then relying on the hardcoded 30 second timeout/retry loop.

        • 1. Re: How do I start multiple caches atomically?
          sirianni

          This problem is actually worse than I thought.  Since the state transfers happen inline with the call to getCache(), my workaround below doesn't really work if the state transfer for the 'foo' cache takes longer than the hardcoded 30 second timeout:

           

          {code}

          cacheManager.defineConfiguration("foo", new Configuration());  // Hack to define the cache but not start it

          ...

          cacheManager.defineConfiguration("bar", new Configuration());

           

          ...

          cacheManager.start(); // Does some JMX stuff but doesn't really start the cache subsystem

           

          ...

          Cache foo = cacheManager.getCache("foo"); // Implicitly starts the cache subsystem - JChannel connected

          // State transfer for "foo" cache happens here.  Could take a long time

           

          Cache bar = cacheManager.getCache("bar");

          {code}

          • 2. Re: How do I start multiple caches atomically?
            galder.zamarreno

            What you probably should be doing is to avoid requests coming in for your caches until all caches have started up. Also, remember that asymmetric clusters are not supported, so all caches need to be defined in all nodes in the cluster.

             

            Finally, if state transfer is an issue for you, why not hook up a cluster cache loader and so load the data into memory lazily by requesting the data from other nodes when this is actually requested?