How do I start multiple caches atomically?
sirianni Apr 19, 2011 11:09 AMI'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.