1 Reply Latest reply on Apr 7, 2009 11:20 AM by Brian Stansberry

    Resource cleanup upon eviction -- change in behaviour in 1.4

    Paul Cowan Newbie

      Hi all,

      We have recently upgraded JBoss Cache from 1.3 to 1.4 (yes, yes! I know!), and have encountered a behaviour change which has us stumped. We want to perform (non-critical but useful) resource cleanup and lifecycle measurements/logging for the objects in one region of the cache when they're evicted. Previously, in 1.3, we had our own class which extended LRUPolicy, and effectively did the following:

      public void evict(Fqn fqn) {
       ...
       try {
       OurClass obj = cache.peek(fqn, KEY);
       obj.cleanUp();
       } finally {
       super.evict(fqn);
       }
      }
      


      which seemed to work fine. What we're finding in 1.4, though, is that this behaviour doesn't actually evict the node correctly. I've written a small test case for this and it seems that the call to cache.peek returns the correct object, we close it OK, and the object is evicted but it remains in the eviction queue. That is, if we have a region size of 10, and put 20 objects in the cache, then 10 get thrown out on the first eviction run; however, those FQNs don't seem to get completely thrown out and then they get evicted AGAIN next cycle. Because super.evict() removed the node, this second time around the cache.peek() call doesn't find the object, calls to the CacheLoader, and recreates the object. Therefore, we're continually cycling over and over again, creating and throwing away new objects (and killing our performance!)

      This behaviour does not happen in 1.3; nor does it happen in 1.4 if we remove the .peek call, so this presumably is what's causing the problem.

      I have tried converting to 2.2 to see what happens there, but the same process occurs. If our custom LRUPolicy calls:

      NodeSPI node = cache_.peek(fqn, false, false);


      then that's fine, but if we call

      node.get(KEY);


      then that seems to prevent the FQN being cleared out and we enter the loop again.

      I have tried the (much less hacky!) technique of using a @CacheListener instead, using something like:

       @NodeEvicted
       public void nodeEvicted(NodeEvictedEvent event) {
       if (event.isPre()) {
       Node n = ((CacheSPI) event.getCache()).peek(event.getFqn(), false);
       if (n != null) {
       n.get(KEY);
       }
       }
      


      then the same behaviour occurs, a continual eviction loop. If the n.get(KEY) line is commented out (JUST leaving the peek) this behaviour goes away.

      What's the "correct" way, if there is one, to retrieve data from nodes that are being evicted without interfering with the eviction behaviour?

      Thanks in advance for your help.