Clover coverage report -
Coverage timestamp: Thu Jul 5 2007 20:02:32 EDT
file stats: LOC: 819   Methods: 29
NCLOC: 502   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
RegionManager.java 71.3% 77.3% 89.7% 76.5%
coverage coverage
 1    package org.jboss.cache;
 2   
 3    import net.jcip.annotations.ThreadSafe;
 4    import org.apache.commons.logging.Log;
 5    import org.apache.commons.logging.LogFactory;
 6    import org.jboss.cache.buddyreplication.BuddyManager;
 7    import org.jboss.cache.config.ConfigurationException;
 8    import org.jboss.cache.config.EvictionConfig;
 9    import org.jboss.cache.config.EvictionRegionConfig;
 10    import org.jboss.cache.eviction.EvictionTimerTask;
 11    import org.jboss.cache.eviction.RegionNameConflictException;
 12    import org.jboss.cache.lock.NodeLock;
 13    import org.jgroups.Address;
 14   
 15    import java.util.ArrayList;
 16    import java.util.Collections;
 17    import java.util.HashSet;
 18    import java.util.Iterator;
 19    import java.util.List;
 20    import java.util.Map;
 21    import java.util.Set;
 22    import java.util.concurrent.ConcurrentHashMap;
 23   
 24    /**
 25    * Manages multiple {@link Region}s for a Cache instance.
 26    *
 27    * @author <a href="mailto:manik@jboss.org">Manik Surtani</a>
 28    * @since 2.0.0
 29    */
 30    @ThreadSafe
 31    public class RegionManager
 32    {
 33    /**
 34    * The default region used in XML configuration files when defining eviction policies. Any
 35    * eviction settings bound under this 'default' Fqn is appplied to {@link org.jboss.cache.Fqn#ROOT} internally so
 36    * any region that is not explicitly defined comes under the settings defined for this default.
 37    */
 38    public static final Fqn DEFAULT_REGION = new Fqn("_default_");
 39   
 40    /**
 41    * A registry of regions that have been defined.
 42    */
 43    private Map<Fqn, Region> regionsRegistry = new ConcurrentHashMap<Fqn, Region>();
 44    private boolean defaultInactive;
 45    private Log log = LogFactory.getLog(RegionManager.class);
 46    private CacheImpl cache;
 47    private boolean usingEvictions;
 48    private EvictionConfig evictionConfig;
 49    private EvictionTimerTask evictionTimerTask = new EvictionTimerTask();
 50   
 51    protected final Set<Fqn> activationChangeNodes = Collections.synchronizedSet(new HashSet<Fqn>());
 52   
 53    /**
 54    * Constructs a new instance not attached to a cache.
 55    */
 56  61 public RegionManager()
 57    {
 58    }
 59   
 60    /**
 61    * Constructs a new instance attached to a cache.
 62    */
 63  2908 public RegionManager(CacheImpl cache)
 64    {
 65  2908 this.cache = cache;
 66    }
 67   
 68    /**
 69    * Returns true if evictions are being processed.
 70    */
 71  2480570 public boolean isUsingEvictions()
 72    {
 73  2480578 return usingEvictions;
 74    }
 75   
 76    /**
 77    * Returns true if replication is by default inactive for new {@link Region}s.
 78    */
 79  1549 public boolean isDefaultInactive()
 80    {
 81  1549 return defaultInactive;
 82    }
 83   
 84    /**
 85    * Sets if replication for new {@link Region}s is by default inactive.
 86    */
 87  2840 public void setDefaultInactive(boolean defaultInactive)
 88    {
 89  2840 this.defaultInactive = defaultInactive;
 90    }
 91   
 92    /**
 93    * Helper utility that checks for a {@link ClassLoader} registered for the
 94    * given {@link Fqn}, and if found sets it as the TCCL. If the given Fqn is
 95    * under the _BUDDY_BACKUP_ region, the equivalent region in the main
 96    * cache is used to find the {@link ClassLoader}.
 97    *
 98    * @param fqn Fqn pointing to a region for which a special classloader
 99    * may have been registered.
 100    */
 101  0 public void setContextClassLoaderAsCurrent(Fqn fqn)
 102    {
 103  0 if (fqn.isChildOf(BuddyManager.BUDDY_BACKUP_SUBTREE_FQN))
 104    {
 105  0 if (fqn.size() <= 2)
 106    {
 107  0 fqn = Fqn.ROOT;
 108    }
 109    else
 110    {
 111  0 fqn = fqn.getSubFqn(2, fqn.size());
 112    }
 113    }
 114  0 Region region = getRegion(fqn, false);
 115  0 ClassLoader regionCL = (region == null) ? null : region.getClassLoader();
 116  0 if (regionCL != null)
 117    {
 118  0 Thread.currentThread().setContextClassLoader(regionCL);
 119    }
 120   
 121    }
 122   
 123    /**
 124    * Returns a region by {@link Fqn}, creating it optionally if absent. If the region does not exist and <tt>createIfAbsent</tt>
 125    * is <tt>false</tt>, a parent region which may apply to the {@link Fqn} is sought.
 126    */
 127  1038795 public Region getRegion(Fqn fqn, boolean createIfAbsent)
 128    {
 129  1038795 return getRegion(fqn, Region.Type.ANY, createIfAbsent);
 130    }
 131   
 132    /**
 133    * An overloaded form of {@link #getRegion(Fqn,boolean)} that takes an additional {@link org.jboss.cache.Region.Type}
 134    * parameter to force regions of a specific type.
 135    *
 136    * @see org.jboss.cache.Region.Type
 137    */
 138  2622279 public Region getRegion(Fqn fqn, Region.Type type, boolean createIfAbsent)
 139    {
 140  2622279 Fqn fqnToUse = fqn;
 141  7 if (DEFAULT_REGION.equals(fqnToUse)) fqnToUse = Fqn.ROOT;
 142    // first see if a region for this specific Fqn exists
 143  2622279 if (regionsRegistry.containsKey(fqnToUse))
 144    {
 145  145764 Region r = regionsRegistry.get(fqnToUse);
 146   
 147    // this is a very poor way of telling whether a region is a marshalling one or an eviction one. :-(
 148    // mandates that class loaders be registered for marshalling regions.
 149  145764 if (type == Region.Type.ANY
 150    || (type == Region.Type.MARSHALLING && r.getClassLoader() != null)
 151    || (type == Region.Type.EVICTION && r.getEvictionPolicyConfig() != null))
 152    {
 153  145758 return r;
 154    }
 155    }
 156   
 157    // if not, attempt to create one ...
 158  2476521 if (createIfAbsent)
 159    {
 160  1549 Region r = new RegionImpl(fqnToUse, this);
 161  1549 regionsRegistry.put(fqnToUse, r);
 162  1549 if (type == Region.Type.MARSHALLING)
 163    {
 164    // insert current class loader into region so at least it is recognised as a marshalling region
 165  16 r.registerContextClassLoader(getClass().getClassLoader());
 166    }
 167  1549 return r;
 168    }
 169    else
 170    {
 171    // first test if the default region has been defined. If not, and if eviction regions
 172    // are in use, throw an exception since it is required.
 173  2474972 if (isUsingEvictions() && !regionsRegistry.containsKey(Fqn.ROOT))
 174    {
 175  1 throw new RuntimeException("No default eviction region defined!");
 176    }
 177    }
 178   
 179    // else try and find a parent which has a defined region, may return null if nothing is defined.
 180  2474971 Region nextBestThing = null;
 181  2474971 Fqn nextFqn = fqnToUse;
 182   
 183  2474971 while (nextBestThing == null)
 184    {
 185  7774419 nextFqn = nextFqn.getParent();
 186  7774419 if (regionsRegistry.containsKey(nextFqn))
 187    {
 188  2474044 Region r = regionsRegistry.get(nextFqn);
 189   
 190    // this is a very poor way of telling whether a region is a marshalling one or an eviction one. :-(
 191    // mandates that class loaders be registered for marshalling regions.
 192  2474044 if (type == Region.Type.ANY
 193    || (type == Region.Type.MARSHALLING && r.getClassLoader() != null)
 194    || (type == Region.Type.EVICTION && r.getEvictionPolicyConfig() != null))
 195    {
 196  2471832 nextBestThing = r;
 197    }
 198    }
 199  790236 if (nextFqn.isRoot()) break;
 200    }
 201   
 202  2474971 return nextBestThing;
 203    }
 204   
 205    /**
 206    * Returns a region using Fqn.fromString(fqn), calling {@link #getRegion(Fqn,boolean)}
 207    *
 208    * @param fqn
 209    * @param createIfAbsent
 210    * @see #getRegion(Fqn,boolean)
 211    */
 212  157 public Region getRegion(String fqn, boolean createIfAbsent)
 213    {
 214  157 return getRegion(Fqn.fromString(fqn), createIfAbsent);
 215    }
 216   
 217    /**
 218    * Removes a {@link org.jboss.cache.Region} identified by the given fqn.
 219    *
 220    * @param fqn fqn of the region to remove
 221    * @return true if such a region existed and was removed.
 222    */
 223  10 public boolean removeRegion(Fqn fqn)
 224    {
 225  10 Region r = regionsRegistry.remove(fqn);
 226  0 if (r == null) return false;
 227   
 228  10 if (isUsingEvictions() && r.getEvictionPolicy() != null)
 229    {
 230  0 evictionTimerTask.removeRegionToProcess(r);
 231    }
 232  10 return true;
 233    }
 234   
 235    /**
 236    * @return the eviction timer task object associated with this Region Manager.
 237    */
 238  1235 protected EvictionTimerTask getEvictionTimerTask()
 239    {
 240  1235 return evictionTimerTask;
 241    }
 242   
 243    /**
 244    * Activates unmarshalling of replication messages for the region
 245    * rooted in the given Fqn.
 246    * <p/>
 247    * <strong>NOTE:</strong> This method will cause the creation of a node
 248    * in the local cache at <code>subtreeFqn</code> whether or not that
 249    * node exists anywhere else in the cluster. If the node does not exist
 250    * elsewhere, the local node will be empty. The creation of this node will
 251    * not be replicated.
 252    * <p/>
 253    *
 254    * @param fqn representing the region to be activated.
 255    * @throws RegionNotEmptyException if the node <code>fqn</code>
 256    * exists and already has either data or children
 257    */
 258  217 public void activate(Fqn fqn) throws RegionNotEmptyException
 259    {
 260  217 activate(fqn, false);
 261    }
 262   
 263    /**
 264    * Attempts to activate a given region rooted at a given Fqn, similar to {@link #activate(Fqn)} except
 265    * that if the fqn is currently already in use (probably already been activated) this method is a no-op.
 266    *
 267    * @param fqn which represents the region to activate
 268    */
 269  0 public void activateIfEmpty(Fqn fqn)
 270    {
 271  0 activate(fqn, true);
 272    }
 273   
 274  217 private void activate(Fqn fqn, boolean suppressRegionNotEmptyException)
 275    {
 276  217 try
 277    {
 278  0 if (log.isTraceEnabled()) log.trace("Activating region " + fqn);
 279  217 Region r = getRegion(fqn, false);
 280  217 if (r != null)
 281    {
 282  208 if (!defaultInactive && r.getClassLoader() == null)
 283    {
 284    // This region's state will no match that of a non-existent one
 285    // So, there is no reason to keep this region any more
 286   
 287    // (Brian) We shouldn't do this anymore; now outside code
 288    // can have a ref to the region!!
 289  4 removeRegion(fqn);
 290    }
 291    else
 292    {
 293    //r.activate();
 294  204 r.setActive(true);
 295    // FIXME - persistent state transfer counts too!
 296  204 if (cache.getConfiguration().isFetchInMemoryState())
 297    {
 298  203 activateRegion(r.getFqn(), suppressRegionNotEmptyException);
 299    }
 300    }
 301    }
 302  9 else if (defaultInactive)
 303    {
 304    // "Active" region is not the default, so create a region
 305  7 r = getRegion(fqn, true);
 306  7 r.setActive(true);
 307    // FIXME - persistent state transfer counts too!
 308  7 if (cache.getConfiguration().isFetchInMemoryState())
 309    {
 310  2 activateRegion(r.getFqn(), suppressRegionNotEmptyException);
 311    }
 312    }
 313    }
 314    catch (RuntimeException re)
 315    {
 316  0 throw re;
 317    }
 318    catch (Exception e)
 319    {
 320  0 throw new RuntimeException(e);
 321    }
 322    }
 323   
 324    /**
 325    * Causes the cache to transfer state for the subtree rooted at
 326    * <code>subtreeFqn</code> and to begin accepting replication messages
 327    * for that subtree.
 328    * <p/>
 329    * <strong>NOTE:</strong> This method will cause the creation of a node
 330    * in the local cache at <code>subtreeFqn</code> whether or not that
 331    * node exists anywhere else in the cluster. If the node does not exist
 332    * elsewhere, the local node will be empty. The creation of this node will
 333    * not be replicated.
 334    *
 335    * @param fqn Fqn string indicating the uppermost node in the
 336    * portion of the cache that should be activated.
 337    * @throws RegionNotEmptyException if the node <code>subtreeFqn</code>
 338    * exists and has either data or children
 339    */
 340  205 private void activateRegion(Fqn fqn, boolean suppressRegionNotEmptyException)
 341    {
 342    // Check whether the node already exists and has data
 343  205 Node subtreeRoot = cache.findNode(fqn);
 344   
 345    /*
 346    * Commented out on Nov 16,2006 Manik&Vladimir
 347    *
 348    * if (!(cache.isNodeEmpty(subtreeRoot)))
 349    {
 350    throw new RegionNotEmptyException("Node " + subtreeRoot.getFqn() + " already exists and is not empty");
 351    }*/
 352   
 353  205 if (isActivatingDeactivating(fqn))
 354    {
 355  0 throw new CacheException("Region " + subtreeRoot.getFqn() + " is already being activated/deactivated");
 356    }
 357   
 358  205 if (log.isDebugEnabled())
 359    {
 360  0 log.debug("activating " + fqn);
 361    }
 362   
 363  205 try
 364    {
 365   
 366    // Add this fqn to the set of those we are activating
 367    // so calls to _getState for the fqn can return quickly
 368  205 activationChangeNodes.add(fqn);
 369   
 370  205 Region region = getRegion(fqn, true);
 371   
 372  205 BuddyManager buddyManager = cache.getBuddyManager();
 373    // Request partial state from the cluster and integrate it
 374  205 if (buddyManager == null)
 375    {
 376    // Get the state from any node that has it and put it
 377    // in the main cache
 378  195 if (subtreeRoot == null)
 379    {
 380    // We'll update this node with the state we receive
 381  189 subtreeRoot = cache.createSubtreeRootNode(fqn);
 382    }
 383   
 384  195 List<Address> members = cache.getMembers();
 385  195 cache.fetchPartialState(members, subtreeRoot.getFqn());
 386    }
 387    else
 388    {
 389    // Get the state from each DataOwner and integrate in their
 390    // respective buddy backup cache
 391  10 List<Address> buddies = buddyManager.getBuddyAddresses();
 392  10 for (Address buddy : buddies)
 393    {
 394  8 List<Address> sources = new ArrayList<Address>(1);
 395  8 sources.add(buddy);
 396  8 Fqn base = new Fqn(BuddyManager.BUDDY_BACKUP_SUBTREE_FQN, BuddyManager.getGroupNameFromAddress(buddy));
 397  8 Fqn buddyRoot = new Fqn(base, fqn);
 398  8 subtreeRoot = cache.findNode(buddyRoot);
 399  8 if (subtreeRoot == null)
 400    {
 401    // We'll update this node with the state we receive
 402  8 subtreeRoot = cache.createSubtreeRootNode(buddyRoot);
 403    }
 404  8 cache.fetchPartialState(sources, fqn, subtreeRoot.getFqn());
 405    }
 406    }
 407    }
 408    catch (Throwable t)
 409    {
 410  0 log.error("failed to activate " + fqn, t);
 411   
 412    // "Re-deactivate" the region
 413  0 try
 414    {
 415  0 inactivateRegion(fqn);
 416    }
 417    catch (Exception e)
 418    {
 419  0 log.error("failed inactivating " + fqn, e);
 420    // just swallow this one and throw the first one
 421    }
 422   
 423    // Throw the exception on, wrapping if necessary
 424  0 if (t instanceof RegionNotEmptyException)
 425    {
 426  0 if (!suppressRegionNotEmptyException) throw (RegionNotEmptyException) t;
 427    }
 428  0 else if (t instanceof CacheException)
 429    {
 430  0 throw (CacheException) t;
 431    }
 432    else
 433    {
 434  0 throw new CacheException(t.getClass().getName() + " " +
 435    t.getLocalizedMessage(), t);
 436    }
 437    }
 438    finally
 439    {
 440  201 activationChangeNodes.remove(fqn);
 441    }
 442    }
 443   
 444    /**
 445    * Convenienve method. If the region defined by fqn does not exist, {@link #isDefaultInactive()} is returned, otherwise
 446    * !{@link Region#isActive()} is returned.
 447    *
 448    * @param fqn fqn to test
 449    * @return true if inactive
 450    */
 451  1067 public boolean isInactive(Fqn fqn)
 452    {
 453  1067 Region region = getRegion(fqn, false);
 454  1067 return region == null ? defaultInactive : !region.isActive();
 455    }
 456   
 457   
 458    /**
 459    * Causes the cache to stop accepting replication events for the subtree
 460    * rooted at <code>subtreeFqn</code> and evict all nodes in that subtree.
 461    * <p/>
 462    * This is legacy code and should not be called directly. This is a private method for now and will be refactored out.
 463    * You should be using {@link #activate(Fqn)} and {@link #deactivate(Fqn)}
 464    * <p/>
 465    *
 466    * @param fqn Fqn string indicating the uppermost node in the
 467    * portion of the cache that should be activated.
 468    * @throws RegionNameConflictException if <code>subtreeFqn</code> indicates
 469    * a node that is part of another
 470    * subtree that is being specially
 471    * managed (either by activate/inactiveRegion()
 472    * or by registerClassLoader())
 473    * @throws CacheException if there is a problem evicting nodes
 474    * @throws IllegalStateException if {@link org.jboss.cache.config.Configuration#isUseRegionBasedMarshalling()} is <code>false</code>
 475    */
 476  11 private void inactivateRegion(Fqn fqn) throws CacheException
 477    {
 478  11 if (isActivatingDeactivating(fqn))
 479    {
 480  0 throw new CacheException("Region " + fqn + " is already being activated/deactivated");
 481    }
 482   
 483  11 NodeSPI parent = null;
 484  11 NodeSPI subtreeRoot = null;
 485  11 boolean parentLocked = false;
 486  11 boolean subtreeLocked = false;
 487  11 NodeLock parentLock = null;
 488  11 NodeLock subtreeLock = null;
 489   
 490  11 try
 491    {
 492    // Record that this fqn is in status change, so can't provide state
 493  11 activationChangeNodes.add(fqn);
 494   
 495  11 if (!isInactive(fqn))
 496    {
 497  0 deactivate(fqn);
 498    }
 499   
 500    // Create a list with the Fqn in the main cache and any buddy backup trees
 501  11 BuddyManager buddyManager = cache.getBuddyManager();
 502  11 ArrayList<Fqn> list = new ArrayList<Fqn>();
 503  11 list.add(fqn);
 504   
 505  11 if (buddyManager != null)
 506    {
 507  2 Set buddies = cache.getChildrenNames(BuddyManager.BUDDY_BACKUP_SUBTREE_FQN);
 508  2 if (buddies != null)
 509    {
 510  2 for (Iterator it = buddies.iterator(); it.hasNext();)
 511    {
 512  2 Fqn base = new Fqn(BuddyManager.BUDDY_BACKUP_SUBTREE_FQN, it.next());
 513  2 list.add(new Fqn(base, fqn));
 514    }
 515    }
 516    }
 517   
 518  11 long stateFetchTimeout = cache.getConfiguration().getLockAcquisitionTimeout() + 5000;
 519    // Remove the subtree from the main cache and any buddy backup trees
 520  11 for (Iterator<Fqn> it = list.iterator(); it.hasNext();)
 521    {
 522  13 Fqn subtree = it.next();
 523  13 subtreeRoot = cache.findNode(subtree);
 524  13 if (subtreeRoot != null)
 525    {
 526    // Acquire locks
 527  11 Object owner = cache.getOwnerForLock();
 528  11 subtreeLock = subtreeRoot.getLock();
 529  11 subtreeLock.acquireAll(owner, stateFetchTimeout, NodeLock.LockType.WRITE);
 530  11 subtreeLocked = true;
 531   
 532    // Lock the parent, as we're about to write to it
 533  11 parent = subtreeRoot.getParent();
 534  11 if (parent != null)
 535    {
 536  9 parentLock = parent.getLock();
 537  9 parentLock.acquire(owner, stateFetchTimeout, NodeLock.LockType.WRITE);
 538  9 parentLocked = true;
 539    }
 540   
 541    // Remove the subtree
 542  11 cache._evictSubtree(subtree);
 543   
 544    // Release locks
 545  11 if (parent != null)
 546    {
 547  9 log.debug("forcing release of locks in parent");
 548  9 parentLock.releaseAll();
 549    }
 550   
 551  11 parentLocked = false;
 552   
 553  11 log.debug("forcing release of all locks in subtree");
 554  11 subtreeLock.releaseAll();
 555  11 subtreeLocked = false;
 556    }
 557    }
 558    }
 559    catch (InterruptedException ie)
 560    {
 561  0 throw new CacheException("Interrupted while acquiring lock", ie);
 562    }
 563    finally
 564    {
 565    // If we didn't succeed, undo the marshalling change
 566    // NO. Since we inactivated, we may have missed changes
 567    //if (!success && !inactive)
 568    // marshaller_.activate(subtreeFqn);
 569   
 570    // If necessary, release locks
 571  11 if (parentLocked)
 572    {
 573  0 log.debug("forcing release of locks in parent");
 574  0 try
 575    {
 576  0 parentLock.releaseAll();
 577    }
 578    catch (Throwable t)
 579    {
 580  0 log.error("failed releasing locks", t);
 581    }
 582    }
 583  11 if (subtreeLocked)
 584    {
 585  0 log.debug("forcing release of all locks in subtree");
 586  0 try
 587    {
 588  0 subtreeLock.releaseAll();
 589    }
 590    catch (Throwable t)
 591    {
 592  0 log.error("failed releasing locks", t);
 593    }
 594    }
 595   
 596  11 activationChangeNodes.remove(fqn);
 597    }
 598    }
 599   
 600    /**
 601    * <p/>
 602    * This is legacy code and should not be called directly. This is a private method for now and will be refactored out.
 603    * You should be using {@link #activate(Fqn)} and {@link #deactivate(Fqn)}
 604    * <p/>
 605    *
 606    * @param fqn fqn of the region
 607    * @return true if the region defined by the fqn is in the process of activating/deactivating
 608    */
 609  216 private boolean isActivatingDeactivating(Fqn fqn)
 610    {
 611  216 return activationChangeNodes.contains(fqn);
 612    }
 613   
 614    /**
 615    * Returns true if the region exists
 616    *
 617    * @param fqn FQN of the region
 618    * @param type type of region to search for
 619    * @return true if the region exists
 620    */
 621  1 public boolean hasRegion(Fqn fqn, Region.Type type)
 622    {
 623  1 Region r = regionsRegistry.get(fqn);
 624  0 if (r == null) return false;
 625  1 switch (type)
 626    {
 627  0 case ANY:
 628  0 return true;
 629  0 case EVICTION:
 630  0 return r.getEvictionPolicy() != null && evictionTimerTask.isRegionRegisteredForProcessing(r);
 631  1 case MARSHALLING:
 632  1 return r.isActive() && r.getClassLoader() != null;
 633    }
 634    // should never reach here?
 635  0 return false;
 636    }
 637   
 638    /**
 639    * Disables unmarshalling of replication messages for the region
 640    * rooted in the given Fqn.
 641    *
 642    * @param fqn
 643    */
 644  23 public void deactivate(Fqn fqn)
 645    {
 646  23 try
 647    {
 648  23 Region region = getRegion(fqn, false);
 649   
 650  23 if (region != null)
 651    {
 652  14 if (defaultInactive && region.getClassLoader() == null)
 653    {
 654    // This region's state will no match that of a non-existent one
 655    // So, there is no reason to keep this region any more
 656   
 657    // FIXME (Brian) We shouldn't do this anymore; now outside code
 658    // can have a ref to the region!!
 659  3 removeRegion(fqn);
 660    }
 661    else
 662    {
 663    //region.deactivate();
 664  11 region.setActive(false);
 665    // FIXME - we should always clean up; otherwise stale data
 666    // is in memory!
 667  11 if (cache.getConfiguration().isFetchInMemoryState())
 668    {
 669  11 inactivateRegion(fqn);
 670    }
 671    }
 672    }
 673  9 else if (!defaultInactive)
 674    {
 675  5 region = getRegion(fqn, true);
 676  5 region.setActive(false);
 677    // FIXME - we should always clean up; otherwise stale data
 678    // is in memory!
 679  5 if (cache.getConfiguration().isFetchInMemoryState())
 680    {
 681  0 inactivateRegion(fqn);
 682    }
 683    }
 684    }
 685    catch (RuntimeException re)
 686    {
 687  0 throw re;
 688    }
 689    catch (Exception e)
 690    {
 691  0 throw new RuntimeException(e);
 692    }
 693    }
 694   
 695    /**
 696    * Resets the region manager's regions registry
 697    */
 698  2 public void reset()
 699    {
 700  2 regionsRegistry.clear();
 701    }
 702   
 703    /**
 704    * Returns an ordered list of all regions.
 705    * Note that the ordered list returned is sorted according to the natural order defined in the {@link Comparable} interface, which {@link org.jboss.cache.Region} extends.
 706    *
 707    * @param type Type of region to return
 708    * @return an ordered list of all regions, based on the type requested.
 709    */
 710  35 public List<Region> getAllRegions(Region.Type type)
 711    {
 712  35 List<Region> regions;
 713   
 714  35 if (type != Region.Type.ANY)
 715    {
 716  26 regions = new ArrayList<Region>();
 717    // we need to loop thru the regions and only select specific regions to rtn.
 718  26 for (Region r : regionsRegistry.values())
 719    {
 720  63 if ((type == Region.Type.EVICTION && r.getEvictionPolicy() != null && evictionTimerTask.isRegionRegisteredForProcessing(r)) ||
 721    (type == Region.Type.MARSHALLING && r.isActive() && r.getClassLoader() != null))
 722  31 regions.add(r);
 723    }
 724    }
 725    else
 726    {
 727    // put all regions
 728  9 regions = new ArrayList<Region>(regionsRegistry.values());
 729    }
 730   
 731  35 Collections.sort(regions);
 732   
 733  35 return regions;
 734    }
 735   
 736    /**
 737    * Sets if evictions are processed.
 738    */
 739  2846 public void setUsingEvictions(boolean usingEvictions)
 740    {
 741  2846 this.usingEvictions = usingEvictions;
 742    }
 743   
 744    /**
 745    * Sets the eviction configuration.
 746    */
 747  377 public void setEvictionConfig(EvictionConfig evictionConfig)
 748    {
 749  377 this.evictionConfig = evictionConfig;
 750  377 boolean setDefault = false;
 751    // create regions for the regions defined in the evictionConfig.
 752  377 for (EvictionRegionConfig erc : evictionConfig.getEvictionRegionConfigs())
 753    {
 754  1133 Fqn fqn = erc.getRegionFqn();
 755  0 if (log.isTraceEnabled()) log.trace("Creating eviction region " + fqn);
 756   
 757  1133 if (fqn.equals(DEFAULT_REGION))
 758    {
 759  377 if (setDefault)
 760    {
 761  0 throw new ConfigurationException("A default region for evictions has already been set for this cache");
 762    }
 763  0 if (log.isTraceEnabled()) log.trace("Applying settings for " + DEFAULT_REGION + " to Fqn.ROOT");
 764  377 fqn = Fqn.ROOT;
 765  377 setDefault = true;
 766    }
 767  1133 Region r = getRegion(fqn, true);
 768  1133 r.setEvictionPolicy(erc.getEvictionPolicyConfig());
 769    }
 770    }
 771   
 772    /**
 773    * Starts the eviction processing thread.
 774    */
 775  377 public void startEvictionThread()
 776    {
 777  377 evictionTimerTask.init(evictionConfig.getWakeupIntervalSeconds());
 778    }
 779   
 780    /**
 781    * Stops the eviction processing thread
 782    */
 783  358 public void stopEvictionThread()
 784    {
 785  360 evictionTimerTask.stop();
 786    }
 787   
 788   
 789    /**
 790    * Returns a string containing debug information on every region.
 791    */
 792  1 public String dumpRegions()
 793    {
 794  1 StringBuilder sb = new StringBuilder();
 795  1 for (Region r : regionsRegistry.values())
 796    {
 797  5 sb.append("\tRegion " + r);
 798  5 sb.append("\n");
 799    }
 800  1 return sb.toString();
 801    }
 802   
 803    /**
 804    * Returns a string containing debug information on every region.
 805    */
 806  0 public String toString()
 807    {
 808  0 return "RegionManager " + dumpRegions();
 809    }
 810   
 811    /**
 812    * Returns the cache for this region manager
 813    */
 814  1230 public CacheImpl getCache()
 815    {
 816  1230 return this.cache;
 817    }
 818   
 819    }