Package org.exoplatform.services.jcr.impl.core.lock.jbosscache

Source Code of org.exoplatform.services.jcr.impl.core.lock.jbosscache.ControllerCacheLoader

/*
* Copyright (C) 2003-2010 eXo Platform SAS.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Affero General Public License
* as published by the Free Software Foundation; either version 3
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see<http://www.gnu.org/licenses/>.
*/
package org.exoplatform.services.jcr.impl.core.lock.jbosscache;

import org.exoplatform.services.jcr.impl.util.SecurityHelper;
import org.jboss.cache.CacheSPI;
import org.jboss.cache.CacheStatus;
import org.jboss.cache.Fqn;
import org.jboss.cache.Modification;
import org.jboss.cache.NodeSPI;
import org.jboss.cache.RegionManager;
import org.jboss.cache.config.CacheLoaderConfig.IndividualCacheLoaderConfig;
import org.jboss.cache.loader.CacheLoader;
import org.jboss.cache.lock.TimeoutException;

import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
* This {@link CacheLoader} is used to encapsulate the {@link CacheLoader} used to persist the data of the Locks.
* This is used to prevent {@link TimeoutException} that occur when several threads try to access the same data
* at the same time and the data is missing in the local cache which is the case most of the time, since no data
* means that the node is not locked. Since all the lock data will be loaded at startup, this {@link CacheLoader}
* will only call the nested {@link CacheLoader} for read operations when the cache status is CacheStatus.STARTING,
* for all other status, we don't call the nested cache loader since if no data cans be found in the local cache,
* it means that there is no data to load because all the lock data has been loaded at startup.
*
* Created by The eXo Platform SAS
* Author : Nicolas Filotto
*          nicolas.filotto@exoplatform.com
* 9 f�vr. 2010 
*/
@SuppressWarnings("unchecked")
public class ControllerCacheLoader implements CacheLoader
{
   /**
    * The nested cache loader
    */
   private final CacheLoader cl;

   /**
    * The related cache
    */
   private CacheSPI cache;

   /**
    * The configuration of the current cache loader
    */
   private IndividualCacheLoaderConfig config;

   /**
    * The default constructor
    * @param cl the cache loader that will be managed by the controller
    */
   public ControllerCacheLoader(CacheLoader cl)
   {
      this.cl = cl;
   }

   /**
    * @see org.jboss.cache.loader.CacheLoader#commit(java.lang.Object)
    */
   public void commit(final Object tx) throws Exception
   {
      PrivilegedExceptionAction<Object> action = new PrivilegedExceptionAction<Object>()
      {
         public Object run() throws Exception
         {
            cl.commit(tx);
            return null;
         }
      };
      try
      {
         AccessController.doPrivileged(action);
      }
      catch (PrivilegedActionException pae)
      {
         Throwable cause = pae.getCause();

         if (cause instanceof Exception)
         {
            throw (Exception)cause;
         }
         else
         {
            throw new RuntimeException(cause);
         }
      }
   }

   /**
    * @see org.jboss.cache.loader.CacheLoader#exists(org.jboss.cache.Fqn)
    */
   public boolean exists(Fqn name) throws Exception
   {
      if (cache.getCacheStatus() == CacheStatus.STARTING)
      {
         // Before calling the nested cache loader we first check if the data exists in the local cache
         // in order to prevent multiple call to the cache store        
         NodeSPI<?, ?> node = cache.peek(name, false);
         if (node != null)
         {
            // The node already exists in the local cache, so we return true
            return true;
         }
         else
         {
            // The node doesn't exist in the local cache, so we need to check through the nested
            // cache loader
            return cl.exists(name);
         }
      }
      // All the data is loaded at startup, so no need to call the nested cache loader for another
      // cache status other than CacheStatus.STARTING
      return false;
   }

   /**
    * @see org.jboss.cache.loader.CacheLoader#get(org.jboss.cache.Fqn)
    */
   public Map<Object, Object> get(Fqn name) throws Exception
   {
      if (cache.getCacheStatus() == CacheStatus.STARTING)
      {
         // Before calling the nested cache loader we first check if the data exists in the local cache
         // in order to prevent multiple call to the cache store                 
         NodeSPI node = cache.peek(name, false);
         if (node != null)
         {
            // The node already exists in the local cache, so we return the corresponding data
            return node.getDataDirect();
         }
         else
         {
            // The node doesn't exist in the local cache, so we need to check through the nested
            // cache loader           
            return cl.get(name);
         }
      }
      // All the data is loaded at startup, so no need to call the nested cache loader for another
      // cache status other than CacheStatus.STARTING
      return null;
   }

   /**
    * @see org.jboss.cache.loader.CacheLoader#getChildrenNames(org.jboss.cache.Fqn)
    */
   public Set<?> getChildrenNames(Fqn fqn) throws Exception
   {
      if (cache.getCacheStatus() == CacheStatus.STARTING)
      {
         // Try to get the list of children name from the nested cache loader
         return cl.getChildrenNames(fqn);
      }
      // All the data is loaded at startup, so no need to call the nested cache loader for another
      // cache status other than CacheStatus.STARTING
      return null;
   }

   /**
    * @see org.jboss.cache.loader.CacheLoader#getConfig()
    */
   public IndividualCacheLoaderConfig getConfig()
   {
      return config;
   }

   /**
    * @see org.jboss.cache.loader.CacheLoader#loadEntireState(java.io.ObjectOutputStream)
    */
   public void loadEntireState(ObjectOutputStream os) throws Exception
   {
      cl.loadEntireState(os);
   }

   /**
    * @see org.jboss.cache.loader.CacheLoader#loadState(org.jboss.cache.Fqn, java.io.ObjectOutputStream)
    */
   public void loadState(Fqn subtree, ObjectOutputStream os) throws Exception
   {
      cl.loadState(subtree, os);
   }

   /**
    * @see org.jboss.cache.loader.CacheLoader#prepare(java.lang.Object, java.util.List, boolean)
    */
   public void prepare(final Object tx, final List<Modification> modifications, final boolean onePhase)
      throws Exception
   {
      PrivilegedExceptionAction<Object> action = new PrivilegedExceptionAction<Object>()
      {
         public Object run() throws Exception
         {
            cl.prepare(tx, modifications, onePhase);
            return null;
         }
      };
      try
      {
         AccessController.doPrivileged(action);
      }
      catch (PrivilegedActionException pae)
      {
         Throwable cause = pae.getCause();

         if (cause instanceof Exception)
         {
            throw (Exception)cause;
         }
         else
         {
            throw new RuntimeException(cause);
         }
      }
   }

   /**
    * @see org.jboss.cache.loader.CacheLoader#put(java.util.List)
    */
   public void put(List<Modification> modifications) throws Exception
   {
      cl.put(modifications);
   }

   /**
    * @see org.jboss.cache.loader.CacheLoader#put(org.jboss.cache.Fqn, java.util.Map)
    */
   public void put(Fqn name, Map<Object, Object> attributes) throws Exception
   {
      cl.put(name, attributes);
   }

   /**
    * @see org.jboss.cache.loader.CacheLoader#put(org.jboss.cache.Fqn, java.lang.Object, java.lang.Object)
    */
   public Object put(final Fqn name, final Object key, final Object value) throws Exception
   {
      return SecurityHelper.doPriviledgedIOExceptionAction(new PrivilegedExceptionAction<Object>()
      {
         public Object run() throws Exception
         {
            return cl.put(name, key, value);
         }
      });
   }

   /**
    * @see org.jboss.cache.loader.CacheLoader#remove(org.jboss.cache.Fqn)
    */
   public void remove(Fqn fqn) throws Exception
   {
      cl.remove(fqn);
   }

   /**
    * @see org.jboss.cache.loader.CacheLoader#remove(org.jboss.cache.Fqn, java.lang.Object)
    */
   public Object remove(Fqn fqn, Object key) throws Exception
   {
      return cl.remove(fqn, key);
   }

   /**
    * @see org.jboss.cache.loader.CacheLoader#removeData(org.jboss.cache.Fqn)
    */
   public void removeData(Fqn fqn) throws Exception
   {
      cl.removeData(fqn);
   }

   /**
    * @see org.jboss.cache.loader.CacheLoader#rollback(java.lang.Object)
    */
   public void rollback(final Object tx)
   {
      PrivilegedAction<Object> action = new PrivilegedAction<Object>()
      {
         public Object run()
         {
            cl.rollback(tx);
            return null;
         }
      };
      AccessController.doPrivileged(action);
   }

   /**
    * @see org.jboss.cache.loader.CacheLoader#setCache(org.jboss.cache.CacheSPI)
    */
   public void setCache(CacheSPI c)
   {
      cl.setCache(c);
      this.cache = c;
   }

   /**
    * @see org.jboss.cache.loader.CacheLoader#setConfig(org.jboss.cache.config.CacheLoaderConfig.IndividualCacheLoaderConfig)
    */
   public void setConfig(IndividualCacheLoaderConfig config)
   {
      this.config = config;
   }

   /**
    * @see org.jboss.cache.loader.CacheLoader#setRegionManager(org.jboss.cache.RegionManager)
    */
   public void setRegionManager(RegionManager manager)
   {
      cl.setRegionManager(manager);
   }

   /**
    * @see org.jboss.cache.loader.CacheLoader#storeEntireState(java.io.ObjectInputStream)
    */
   public void storeEntireState(ObjectInputStream is) throws Exception
   {
      cl.storeEntireState(is);
   }

   /**
    * @see org.jboss.cache.loader.CacheLoader#storeState(org.jboss.cache.Fqn, java.io.ObjectInputStream)
    */
   public void storeState(Fqn subtree, ObjectInputStream is) throws Exception
   {
      cl.storeState(subtree, is);
   }

   /**
    * @see org.jboss.cache.Lifecycle#create()
    */
   public void create() throws Exception
   {
      cl.create();
   }

   /**
    * @see org.jboss.cache.Lifecycle#destroy()
    */
   public void destroy()
   {
      cl.destroy();
   }

   /**
    * @see org.jboss.cache.Lifecycle#start()
    */
   public void start() throws Exception
   {
      cl.start();
   }

   /**
    * @see org.jboss.cache.Lifecycle#stop()
    */
   public void stop()
   {
      cl.stop();
   }

}
TOP

Related Classes of org.exoplatform.services.jcr.impl.core.lock.jbosscache.ControllerCacheLoader

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.