Clover coverage report -
Coverage timestamp: Thu Jul 5 2007 20:02:32 EDT
file stats: LOC: 377   Methods: 15
NCLOC: 225   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
CacheLoaderManager.java 82.6% 93.3% 100% 91%
coverage coverage
 1    /*
 2    * JBoss, Home of Professional Open Source
 3    *
 4    * Distributable under LGPL license.
 5    * See terms of license at gnu.org.
 6    */
 7    package org.jboss.cache.loader;
 8   
 9    import org.apache.commons.logging.Log;
 10    import org.apache.commons.logging.LogFactory;
 11    import org.jboss.cache.Cache;
 12    import org.jboss.cache.CacheException;
 13    import org.jboss.cache.CacheSPI;
 14    import org.jboss.cache.Fqn;
 15    import org.jboss.cache.config.CacheLoaderConfig;
 16    import org.jboss.cache.config.CacheLoaderConfig.IndividualCacheLoaderConfig;
 17   
 18    import java.util.ArrayList;
 19    import java.util.Iterator;
 20    import java.util.Set;
 21    import java.util.StringTokenizer;
 22   
 23    /**
 24    * Manages all cache loader functionality. This class is typically initialised with an XML DOM Element,
 25    * represeting a cache loader configuration, or a {@link org.jboss.cache.config.CacheLoaderConfig} object.
 26    * <p/>
 27    * Usage:
 28    * <p/>
 29    * <code>
 30    * CacheLoaderManager manager = new CacheLoaderManager();
 31    * manager.setConfig(myXmlSnippet, myTreeCache);
 32    * CacheLoader loader = manager.getCacheLoader();
 33    * </code>
 34    * <p/>
 35    * The XML configuration passed in would typically look like:
 36    * <p/>
 37    * <code><![CDATA[
 38    * <p/>
 39    * <config>
 40    * <passivation>false</passivation>
 41    * <preload>/</preload>
 42    * <p/>
 43    * <cacheloader>
 44    * <class>org.jboss.cache.loader.FileCacheLoader</class>
 45    * <async>true</async>
 46    * <fetchPersistentState>false</fetchPersistentState>
 47    * <ignoreModifications>false</ignoreModifications>
 48    * <properties>
 49    * location=/tmp/file
 50    * </properties>
 51    * </cacheloader>
 52    * </config>
 53    * ]]>
 54    * </code>
 55    *
 56    * @author <a href="mailto:manik@jboss.org">Manik Surtani (manik@jboss.org)</a>
 57    */
 58    public class CacheLoaderManager
 59    {
 60    private static Log log = LogFactory.getLog(CacheLoaderManager.class);
 61    private CacheLoaderConfig config;
 62    private CacheSPI cache;
 63    private CacheLoader loader;
 64    private boolean fetchPersistentState;
 65   
 66    /**
 67    * Sets a configuration object and creates a cacheloader accordingly.
 68    *
 69    * @param config
 70    * @param cache
 71    * @throws CacheException
 72    */
 73  1062 public void setConfig(CacheLoaderConfig config, CacheSPI cache) throws CacheException
 74    {
 75  1062 this.config = config == null ? new CacheLoaderConfig() : config;
 76  1062 this.cache = cache;
 77  1062 try
 78    {
 79  1062 loader = createCacheLoader();
 80    }
 81    catch (Exception e)
 82    {
 83  3 throw new CacheException("Unable to create cache loaders", e);
 84    }
 85    }
 86   
 87    /**
 88    * Creates the cache loader based on a cache loader config passed in.
 89    *
 90    * @return a configured cacheloader
 91    * @throws IllegalAccessException
 92    * @throws InstantiationException
 93    * @throws ClassNotFoundException
 94    */
 95  1062 private CacheLoader createCacheLoader() throws Exception
 96    {
 97  1062 CacheLoader tmpLoader = null;
 98    // if we only have a single cache loader configured in the chaining cacheloader then
 99    // don't use a chaining cache loader at all.
 100   
 101  1062 ArrayList<IndividualCacheLoaderConfig> finalConfigs =
 102    new ArrayList<IndividualCacheLoaderConfig>();
 103   
 104    // also if we are using passivation then just directly use the first cache loader.
 105  1062 if (config.useChainingCacheLoader())
 106    {
 107    // create chaining cache loader.
 108  76 tmpLoader = new ChainingCacheLoader();
 109  76 ChainingCacheLoader ccl = (ChainingCacheLoader) tmpLoader;
 110  76 Iterator it = config.getIndividualCacheLoaderConfigs().iterator();
 111   
 112    // only one cache loader may have fetchPersistentState to true.
 113  76 int numLoadersWithFetchPersistentState = 0;
 114  76 while (it.hasNext())
 115    {
 116  152 CacheLoaderConfig.IndividualCacheLoaderConfig cfg = (CacheLoaderConfig.IndividualCacheLoaderConfig) it.next();
 117  152 if (cfg.isFetchPersistentState())
 118    {
 119  71 numLoadersWithFetchPersistentState++;
 120  71 fetchPersistentState = true;
 121    }
 122  152 if (numLoadersWithFetchPersistentState > 1)
 123    {
 124  1 throw new Exception("Invalid cache loader configuration!! Only ONE cache loader may have fetchPersistentState set to true. Cache will not start!");
 125    }
 126  151 if (cfg.isSingletonStore() && config.isShared())
 127    {
 128  0 throw new Exception("Invalid cache loader configuration!! If a cache loader is configured as a singleton, the cache loader cannot be shared in a cluster!");
 129    }
 130   
 131  151 CacheLoader l = createCacheLoader(cfg, cache);
 132  151 cfg = l.getConfig();
 133  151 finalConfigs.add(cfg);
 134    // Only loaders that deal w/ state transfer factor into
 135    // whether the overall chain supports ExtendedCacheLoader
 136  151 ccl.addCacheLoader(l, cfg);
 137   
 138    }
 139    }
 140    else
 141    {
 142  986 CacheLoaderConfig.IndividualCacheLoaderConfig cfg = config.getIndividualCacheLoaderConfigs().get(0);
 143  985 tmpLoader = createCacheLoader(cfg, cache);
 144  984 finalConfigs.add(tmpLoader.getConfig());
 145  984 fetchPersistentState = cfg.isFetchPersistentState();
 146    }
 147   
 148    // Update the config with those actually used by the loaders
 149  1059 config.setIndividualCacheLoaderConfigs(finalConfigs);
 150   
 151  1059 return tmpLoader;
 152    }
 153   
 154    /**
 155    * Creates the cache loader based on the configuration.
 156    *
 157    * @param cfg
 158    * @param cache
 159    * @return a cache loader
 160    * @throws Exception
 161    */
 162  1136 private CacheLoader createCacheLoader(CacheLoaderConfig.IndividualCacheLoaderConfig cfg, CacheSPI cache) throws Exception
 163    {
 164    // create loader
 165  1136 CacheLoader tmpLoader = createInstance(cfg.getClassName());
 166   
 167  1136 if (tmpLoader != null)
 168    {
 169    // async?
 170  1136 if (cfg.isAsync())
 171    {
 172  21 CacheLoader asyncDecorator;
 173  21 asyncDecorator = new AsyncCacheLoader(tmpLoader);
 174  21 tmpLoader = asyncDecorator;
 175    }
 176   
 177    // singleton?
 178  1136 if (cfg.isSingletonStore())
 179    {
 180  10 SingletonStoreCacheLoader singletonDecorator = new SingletonStoreCacheLoader(tmpLoader, cfg.isPushStateWhenCoordinator());
 181  10 addCacheListener(cache, singletonDecorator.getCacheListener());
 182  9 tmpLoader = singletonDecorator;
 183    }
 184   
 185    // load props
 186  1135 tmpLoader.setConfig(cfg);
 187   
 188  1135 tmpLoader.setCache(cache);
 189    // we should not be creating/starting the cache loader here - this should be done in the separate
 190    // startCacheLoader() method.
 191    // tmpLoader.create();
 192    // tmpLoader.start();
 193  1135 if (cache != null && cache.getConfiguration().isUseRegionBasedMarshalling())
 194    {
 195  29 tmpLoader.setRegionManager(cache.getRegionManager());
 196    }
 197    }
 198  1135 return tmpLoader;
 199    }
 200   
 201  7 protected void addCacheListener(Cache c, Object listener)
 202    {
 203  7 c.addCacheListener(listener);
 204    }
 205   
 206  1136 private CacheLoader createInstance(String className) throws ClassNotFoundException, IllegalAccessException, InstantiationException
 207    {
 208  1136 Class cl = Thread.currentThread().getContextClassLoader().loadClass(className);
 209  1136 return (CacheLoader) cl.newInstance();
 210    }
 211   
 212    /**
 213    * Performs a preload on the cache based on the cache loader preload configs used when configuring the cache.
 214    *
 215    * @throws Exception
 216    */
 217  1029 public void preloadCache() throws CacheException
 218    {
 219  1005 if (config.getPreload() == null || config.getPreload().equals("")) return;
 220  0 if (log.isDebugEnabled()) log.debug("preloading transient state from cache loader " + loader);
 221  24 StringTokenizer st = new StringTokenizer(config.getPreload(), ",");
 222  24 String tok;
 223  24 Fqn fqn;
 224  24 long start, stop, total;
 225  24 start = System.currentTimeMillis();
 226  24 while (st.hasMoreTokens())
 227    {
 228  24 tok = st.nextToken();
 229  24 fqn = Fqn.fromString(tok.trim());
 230  0 if (log.isTraceEnabled()) log.trace("preloading " + fqn);
 231  24 preload(fqn, true, true);
 232    }
 233   
 234  24 stop = System.currentTimeMillis();
 235  24 total = stop - start;
 236  24 if (log.isDebugEnabled())
 237    {
 238  0 log.debug("preloading transient state from cache loader was successful (in " + total + " milliseconds)");
 239    }
 240    }
 241   
 242    /**
 243    * Preloads a specific Fqn into the cache from the configured cacheloader
 244    *
 245    * @param fqn fqn to preload
 246    * @param preloadParents whether we preload parents
 247    * @param preloadChildren whether we preload children
 248    * @throws CacheException if we are unable to preload
 249    */
 250  40 public void preload(Fqn fqn, boolean preloadParents, boolean preloadChildren) throws CacheException
 251    {
 252   
 253    // 1. Load the attributes first
 254    // but this will go down the entire damn chain!! :S
 255  40 cache.get(fqn, "bla");
 256   
 257    // 2. Then load the parents
 258  40 if (preloadParents)
 259    {
 260  38 Fqn tmp_fqn = Fqn.ROOT;
 261  38 for (int i = 0; i < fqn.size() - 1; i++)
 262    {
 263  56 tmp_fqn = new Fqn(tmp_fqn, fqn.get(i));
 264  56 cache.get(tmp_fqn, "bla");
 265    }
 266    }
 267   
 268  40 if (preloadChildren)
 269    {
 270    // 3. Then recursively for all child nodes, preload them as well
 271  40 Set children = null;
 272  40 try
 273    {
 274  40 children = loader.getChildrenNames(fqn);
 275    }
 276    catch (Exception e)
 277    {
 278  0 throw new CacheException("Unable to preload from cache loader", e);
 279    }
 280  40 if (children != null)
 281    {
 282  2 for (Object aChildren : children)
 283    {
 284  2 String child_name = (String) aChildren;
 285  2 Fqn child_fqn = new Fqn(fqn, child_name);
 286  2 preload(child_fqn, false, true);
 287    }
 288    }
 289    }
 290    }
 291   
 292    /**
 293    * Returns the configuration element of the cache loaders
 294    */
 295  2558 public CacheLoaderConfig getCacheLoaderConfig()
 296    {
 297  2558 return config;
 298    }
 299   
 300    /**
 301    * Returns the cache loader
 302    */
 303  6521 public CacheLoader getCacheLoader()
 304    {
 305  6521 return loader;
 306    }
 307   
 308    /**
 309    * Overrides generated cache loader with the one provided,for backward compat.
 310    *
 311    * @param loader
 312    */
 313  113 public void setCacheLoader(CacheLoader loader)
 314    {
 315  113 this.loader = loader;
 316    }
 317   
 318    /**
 319    * Tests if we're using passivation
 320    */
 321  1042 public boolean isPassivation()
 322    {
 323  1042 return config.isPassivation();
 324    }
 325   
 326    /**
 327    * Returns true if at least one of the configured cache loaders has set fetchPersistentState to true.
 328    */
 329  373 public boolean isFetchPersistentState()
 330    {
 331  373 return fetchPersistentState;
 332    }
 333   
 334  1024 public void stopCacheLoader()
 335    {
 336  0 if (loader == null) throw new RuntimeException("Problem with configured cache loader - it has been set to null!");
 337    // stop the cache loader
 338  1024 loader.stop();
 339    // destroy the cache loader
 340  1023 loader.destroy();
 341    }
 342   
 343  1032 public void startCacheLoader() throws CacheException
 344    {
 345  0 if (loader == null) throw new RuntimeException("Improperly configured cache loader - cache loader is null!");
 346  1032 try
 347    {
 348    // create the cache loader
 349  1032 loader.create();
 350    // start the cache loader
 351  1032 loader.start();
 352   
 353  1031 purgeLoaders(false);
 354    }
 355    catch (Exception e)
 356    {
 357  1 throw new CacheException("Unable to start cache loaders", e);
 358    }
 359    }
 360   
 361  1031 public void purgeLoaders(boolean force) throws Exception
 362    {
 363  1031 if ((loader instanceof ChainingCacheLoader) && !force)
 364    {
 365  68 ((ChainingCacheLoader) loader).purgeIfNecessary();
 366    }
 367    else
 368    {
 369  963 CacheLoaderConfig.IndividualCacheLoaderConfig first = getCacheLoaderConfig().getFirstCacheLoaderConfig();
 370  963 if (force ||
 371    (first != null && first.isPurgeOnStartup()))
 372    {
 373  2 loader.remove(Fqn.ROOT);
 374    }
 375    }
 376    }
 377    }