7 Replies Latest reply on Feb 1, 2010 4:39 AM by Nicolas Filotto

    How to evict a node when all its children have been evicted?

    Nicolas Filotto Novice

      Hi All,

       

      Since the last past days, I have been working on finding a memory leak in my program. I finally identified it, in fact it is due to the fact that in JBC when all the sub nodes of a JBC node are evicted, the parent node is never evicted even if it has not been declared resident.

       

      Let's take a concrete example

      We assume that I have the following configuration

      {code}

        <eviction wakeUpInterval="5000">

            <default algorithmClass="org.jboss.cache.eviction.FIFOAlgorithm" eventQueueSize="1000000">

               <property name="maxNodes" value="1" />

            </default>

         </eviction>

      {code}

       

      if I first call cache.put(Fqn.fromElements("1","1"),key,value)

      If I then call cache.put(Fqn.fromElements("2"),key,value), the node "/1/1" is evicted but its parent node "/1" is not evicted

      If I then call cache.put(Fqn.fromElements("3"),key,value), the node "/2" is evicted but node "/1" is still present.

       

      This zombie node (i.e. node "/1") is the cause of my memory leak. So my question is, is there a way to make JBC evicts those kind of nodes?

       

      To limit the memory leak, I implemented a EvictionActionPolicy, but I would like to know if there is a better solution. If I don't have any other way, could you check my code below and tell me how I could improve it, because up to now, it fixes about 95% of the memory leak but it seems that it doesn't work 100% of the time:

      {code}

      public class MyEvictionActionPolicy implements EvictionActionPolicy

      {

         Cache<?, ?> cache;

         private static final Log log = LogFactory.getLog(DefaultEvictionActionPolicy.class);

       

         public void setCache(Cache<?, ?> cache)

         {

            this.cache = cache;

         }

       

         public boolean evict(Fqn fqn)

         {

            boolean result;

            try

            {

               if (log.isTraceEnabled()) log.trace("Evicting Fqn " + fqn);

               cache.evict(fqn);

               result = true;

            }

            catch (Exception e)

            {

               if (log.isDebugEnabled()) log.debug("Unable to evict " + fqn, e);

               result = false;

            }

            if (fqn.size() != 3)

            {

               return result;

            }

            try

            {

               Fqn parentFqn = fqn.getParent();

               if (parentFqn.get(0).equals(JBossCacheWorkspaceStorageCache.CHILD_NODES) || parentFqn.get(0).equals(

                     JBossCacheWorkspaceStorageCache.CHILD_PROPS))

               {

                  // The expected data structure is of type $CHILD_NODES/${node-id}/${sub-node-name} or

                  // $CHILD_PROPS/${node-id}/${sub-property-name}

                  Set<Object> names = cache.getChildrenNames(parentFqn);

                  if (names.isEmpty() || (names.size() == 1 && names.contains(fqn.get(2))))

                  {

                     if (log.isTraceEnabled()) log.trace("Evicting Fqn " + fqn);

                     cache.evict(parentFqn);

                  }

               }

            }

            catch (Exception e)

            {

               if (log.isDebugEnabled()) log.debug("Unable to evict " + fqn, e);

            }

            return result;

         }

      }

      {code}

       

      Thank you in advance for your help,

      BR,

      Nicolas Filotto