Пример #1
0
 @Override
 public EhCache buildCache(CacheSetting setting) throws CacheException {
   String name = StringUtil.joinString(setting.getRegion(), setting.getConfigKey());
   EhCache ehcache = cacheManager.get(name);
   if (ehcache == null) {
     try {
       synchronized (cacheManager) {
         ehcache = cacheManager.get(name);
         if (ehcache == null) {
           // log.debug("Could not find configuration [" + name
           // + "]; using defaults.");
           Ehcache ehcache2 = manager.addCacheIfAbsent(name);
           if (ehcache2 != null) {
             if (setting.getCacheExpire() == CacheExpire.SlidingTime) {
               ehcache2.getCacheConfiguration().setTimeToIdleSeconds(setting.getExpireTime());
               ehcache2.getCacheConfiguration().setTimeToLiveSeconds(0);
             } else if (setting.getCacheExpire() == CacheExpire.AbsoluteTime) {
               ehcache2.getCacheConfiguration().setTimeToLiveSeconds(setting.getExpireTime());
               ehcache2.getCacheConfiguration().setTimeToIdleSeconds(0);
             }
           }
           Cache cache = manager.getCache(name);
           // log.debug("started EHCache region: " + name);
           LoggerFactory.getLogger(this.getClass()).info("init ehcache " + cache);
           ehcache = new EhCache(cache, setting);
           cacheManager.put(name, ehcache);
         }
       }
     } catch (Exception e) {
       throw new CacheException(e);
     }
   }
   return ehcache;
 }
Пример #2
0
  /**
   * Checks whether the cache has reached the limit configured for in-memory storage
   *
   * @param cache The cache being loaded and to be checked for limit being reached
   * @param loadedElements amounts of elements loaded so far
   * @return true if on-heap or off-heap limit has been reached, false otherwise
   */
  protected boolean isInMemoryLimitReached(final Ehcache cache, final int loadedElements) {

    long maxBytesInMem;
    long maxElementsInMem;
    final boolean overflowToOffHeap = cache.getCacheConfiguration().isOverflowToOffHeap();
    maxElementsInMem =
        cache.getCacheConfiguration().getMaxEntriesLocalHeap() == 0
            ? Integer.MAX_VALUE
            : cache.getCacheConfiguration().getMaxEntriesLocalHeap();
    if (overflowToOffHeap) {
      maxBytesInMem = cache.getCacheConfiguration().getMaxBytesLocalOffHeap();
    } else {
      maxBytesInMem = cache.getCacheConfiguration().getMaxBytesLocalHeap();
    }

    if (maxBytesInMem != 0) {
      final long inMemoryCount =
          overflowToOffHeap
              ? cache.getStatistics().getLocalOffHeapSize()
              : cache.getStatistics().getLocalHeapSize();
      if (inMemoryCount == 0L) {
        return false;
      } else {
        final long inMemorySizeInBytes =
            overflowToOffHeap
                ? cache.getStatistics().getLocalOffHeapSizeInBytes()
                : cache.getStatistics().getLocalHeapSizeInBytes();
        final long avgSize = inMemorySizeInBytes / inMemoryCount;
        return inMemorySizeInBytes + (avgSize * 2) >= maxBytesInMem;
      }
    } else {
      return loadedElements >= maxElementsInMem;
    }
  }
  /** Tests the expiry notifier. Check a reported scenario */
  @Test
  public void testExpiryNotifications() throws InterruptedException {
    Serializable key = "1";
    Element element = new Element(key, new Date());

    TestCacheEventListener cacheEventListener = new TestCacheEventListener();
    cache.getCacheEventNotificationService().registerListener(cacheEventListener);

    // Put
    cache.put(element);

    // expire
    Thread.sleep(15000);
    for (int i = 0; i < cache.getCacheConfiguration().getMaxEntriesLocalHeap(); i++) {
      cache.put(new Element(i, i));
      cache.get(i); // makes sure the entry is flushed
    }
    assertThat(cacheEventListener.counter.get(), equalTo(1));

    // the TestCacheEventListener does a put of a new Element with the same key on expiry
    assertNotNull(cache.get(key));
    Element newElement = cache.get(key);
    assertNotNull(newElement);
    assertEquals("set on notify", newElement.getValue());

    // Check counting listener
    CountingCacheEventListener listener = getCountingCacheEventListener(cache);
    List<CacheEvent> notifications = listener.getCacheElementsExpired();
    assertThat(notifications, hasSize(1));
    assertEquals(element, notifications.get(0).getElement());

    // check for NPE
    cache.remove(null);
  }
Пример #4
0
  /**
   * Creates a disk store.
   *
   * @param cache the {@link net.sf.ehcache.Cache} that the store is part of
   * @param diskPath the directory in which to create data and index files
   */
  public DiskStore(Ehcache cache, String diskPath) {
    status = Status.STATUS_UNINITIALISED;
    this.cache = cache;
    name = cache.getName();
    this.diskPath = diskPath;
    expiryThreadInterval = cache.getDiskExpiryThreadIntervalSeconds();
    persistent = cache.isDiskPersistent();
    maxElementsOnDisk = cache.getMaxElementsOnDisk();
    eternal = cache.isEternal();
    diskSpoolBufferSizeBytes =
        cache.getCacheConfiguration().getDiskSpoolBufferSizeMB() * ONE_MEGABYTE;

    try {
      initialiseFiles();

      active = true;

      // Always start up the spool thread
      spoolAndExpiryThread = new SpoolAndExpiryThread();
      spoolAndExpiryThread.start();

      status = Status.STATUS_ALIVE;
    } catch (final Exception e) {
      // Cleanup on error
      dispose();
      LOG.error(
          name + "Cache: Could not create disk store. Initial cause was " + e.getMessage(), e);
    }
  }
Пример #5
0
  /**
   * Chooses the Policy from the cache configuration
   *
   * @param cache
   */
  protected void determineEvictionPolicy(Ehcache cache) {
    MemoryStoreEvictionPolicy policySelection =
        cache.getCacheConfiguration().getMemoryStoreEvictionPolicy();

    if (policySelection.equals(MemoryStoreEvictionPolicy.LRU)) {
      policy = new LruPolicy();
    } else if (policySelection.equals(MemoryStoreEvictionPolicy.FIFO)) {
      policy = new FifoPolicy();
    } else if (policySelection.equals(MemoryStoreEvictionPolicy.LFU)) {
      policy = new LfuPolicy();
    }
  }
Пример #6
0
 /** Flush to disk only if the cache is diskPersistent. */
 public final void flush() {
   if (cache.getCacheConfiguration().isDiskPersistent()) {
     if (LOG.isLoggable(Level.FINE)) {
       LOG.fine(
           cache.getName()
               + " is persistent. Spooling "
               + map.size()
               + " elements to the disk store.");
     }
     spoolAllToDisk();
   }
   // should be emptied in any case
   clear();
 }
Пример #7
0
  /**
   * Constructs things that all MemoryStores have in common.
   *
   * @param cache
   * @param diskStore
   */
  protected MemoryStore(Ehcache cache, Store diskStore) {
    status = Status.STATUS_UNINITIALISED;
    this.cache = cache;
    this.maximumSize = cache.getCacheConfiguration().getMaxElementsInMemory();
    this.diskStore = diskStore;
    determineEvictionPolicy(cache);

    map = new ConcurrentHashMap(maximumSize, DEFAULT_LOAD_FACTOR, CONCURRENCY_LEVEL);
    if (maximumSize > TOO_LARGE_TO_EFFICIENTLY_ITERATE) {
      useKeySample = true;
      keyArray = new AtomicReferenceArray<Object>(maximumSize);
      keySamplePointer = new AtomicInteger(0);
    }

    status = Status.STATUS_ALIVE;

    if (LOG.isLoggable(Level.FINE)) {
      LOG.fine("Initialized " + this.getClass().getName() + " for " + cache.getName());
    }
  }
Пример #8
0
  /**
   * Evict the <code>Element</code>.
   *
   * <p>Evict means that the <code>Element</code> is:
   *
   * <ul>
   *   <li>if, the store is diskPersistent, the <code>Element</code> is spooled to the DiskStore
   *   <li>if not, the <code>Element</code> is removed.
   * </ul>
   *
   * @param element the <code>Element</code> to be evicted.
   */
  protected final void evict(Element element) throws CacheException {
    boolean spooled = false;
    if (cache.getCacheConfiguration().isOverflowToDisk()) {
      if (!element.isSerializable()) {
        if (LOG.isLoggable(Level.FINE)) {
          LOG.log(
              Level.FINE,
              new StringBuffer("Object with key ")
                  .append(element.getObjectKey())
                  .append(" is not Serializable and cannot be overflowed to disk")
                  .toString());
        }
      } else {
        spoolToDisk(element);
        spooled = true;
      }
    }

    if (!spooled) {
      cache.getCacheEventNotificationService().notifyElementEvicted(element, false);
    }
  }
Пример #9
0
  /**
   * Validates that the supplied Ehcache instance is valid for use as a Hibernate cache.
   *
   * @param cache The cache instance
   * @throws CacheException If any explicit settings on the cache are not validate
   */
  public static void validateEhcache(Ehcache cache) throws CacheException {
    final CacheConfiguration cacheConfig = cache.getCacheConfiguration();

    if (cacheConfig.isTerracottaClustered()) {
      final TerracottaConfiguration tcConfig = cacheConfig.getTerracottaConfiguration();
      switch (tcConfig.getValueMode()) {
        case IDENTITY:
          {
            throw new CacheException(
                "The clustered Hibernate cache "
                    + cache.getName()
                    + " is using IDENTITY value mode.\n"
                    + "Identity value mode cannot be used with Hibernate cache regions.");
          }
        case SERIALIZATION:
        default:
          {
            // this is the recommended valueMode
            break;
          }
      }
    }
  }
  /**
   * @param cacheName
   * @param legacyMode If true always create a new Cache. If false, cache must be defined in bean
   *     factory.
   * @return
   */
  private Ehcache instantiateCache(String cacheName) {
    if (M_log.isDebugEnabled()) M_log.debug("createNewCache(String " + cacheName + ")");

    String name = cacheName;
    if (name == null || "".equals(name)) {
      name = "DefaultCache" + UUID.randomUUID().toString();
    }

    // Cache creation should all go to the cache manager and be
    // configured via the cache manager setup.

    if (cacheManager.cacheExists(name)) {
      return cacheManager.getEhcache(name);
    }

    Ehcache cache = null;

    try {
      Ehcache defaultCache = getDefaultCache();
      if (defaultCache != null) {
        cache = (Ehcache) defaultCache.clone();
        cache.setName(cacheName);

        // Not look for any custom configuration.
        // Check for old configuration properties.
        if (serverConfigurationService().getString(name) == null) {
          M_log.warn("Old cache configuration " + name + " must be changed to memory." + name);
        }
        String config = serverConfigurationService().getString("memory." + name);
        if (config != null && config.length() > 0) {
          M_log.debug("Found configuration for cache: " + name + " of: " + config);
          new CacheInitializer().configure(config).initialize(cache.getCacheConfiguration());
        }

        cacheManager.addCache(cache);
      }
    } catch (Exception ex) {
      M_log.warn("Unable to access or close default cache", ex);
    }

    if (cache == null) {
      cacheManager.addCache(name);
      cache = cacheManager.getEhcache(name);
    }

    // KNL-1292: do not set if the cache is not yet init'ed
    if (cache != null && cache.getStatus().equals(Status.STATUS_ALIVE)) {
      // KNL-532 - Upgraded Ehcache 2.5.1 (2.1.0+) defaults to no stats collection.
      // We may choose to allow configuration per-cache for performance tuning.
      // For now, we default everything to on, while this property allows a system-wide override.
      cache.setStatisticsEnabled(
          !(serverConfigurationService()
              .getBoolean("memory.cache.statistics.force.disabled", false)));
    }

    return cache;

    /*


    if(legacyMode)
    {
    	if (cacheManager.cacheExists(name)) {
    		M_log.warn("Cache already exists and is bound to CacheManager; creating new cache from defaults: "
    				+ name);
    		// favor creation of new caches for backwards compatibility
    		// in the future, it seems like you would want to return the same
    		// cache if it already exists
    		name = name + UUID.randomUUID().toString();
    	}
    }

    Ehcache cache = null;

    // try to locate a named cache in the bean factory
    try {
    	cache = (Ehcache) ComponentManager.get(name);
    } catch (Exception e) {
    	cache = null;
    	M_log.error("Error occurred when trying to load cache from bean factory!", e);
    }


    if(cache != null) // found the cache
    {
    	M_log.info("Loaded Named Cache " + cache);

    	return cache;
    }
    else // did not find the cache
    {
    	if(legacyMode)
    	{
    		cacheManager.addCache(name); // create a new cache
    		cache = cacheManager.getEhcache(name);
    		M_log.info("Loaded Default Cache " + cache);
    	}
    	else
    	{
    		M_log.error("Could not find named cache in the bean factory!:"
    						+ name);
    	}

    	return cache;
    }
    */
  }
Пример #11
0
 @Override
 public long getTimeToLive(final TimeUnit unit) {
   final long maxAge = self.getCacheConfiguration().getTimeToLiveSeconds();
   return unit.convert(maxAge, SECONDS);
 }
Пример #12
0
  /**
   * @param cacheName the name of the cache
   * @param configuration [OPTIONAL] a config to use when building the cache, if null then use
   *     default methods to create cache
   * @return an Ehcache
   */
  private Ehcache makeEhcache(
      String cacheName, org.sakaiproject.memory.api.Configuration configuration) {
    /** Indicates a cache is a new one and should be configured */
    boolean newCache = false;
    String name = cacheName;
    if (name == null || "".equals(name)) {
      name = "DefaultCache" + UUID.randomUUID().toString();
      log.warn("Creating cache without a name, generating dynamic name: (" + name + ")");
      newCache = true;
    }

    Ehcache cache;
    // fetch an existing cache first if possible
    if (!newCache && cacheManager.cacheExists(name)) {
      cache = cacheManager.getEhcache(name);
      if (log.isDebugEnabled()) log.debug("Retrieved existing ehcache (" + name + ")");
    } else {
      // create a new defaulted cache
      cacheManager.addCache(name);
      cache = cacheManager.getEhcache(name);
      newCache = true;
      log.info("Created ehcache (" + name + ") using defaults");
    }

    if (newCache) {
      if (log.isDebugEnabled())
        log.debug("Prepared to configure new ehcache (" + name + "): " + cache);
      // warn people if they are using an old config style
      if (serverConfigurationService.getString(name) == null) {
        log.warn(
            "Old cache configuration for cache ("
                + name
                + "), must be changed to memory."
                + name
                + " or it will be ignored");
      }

      // load the ehcache config from the Sakai config service
      String config = serverConfigurationService.getString("memory." + name);
      if (StringUtils.isNotBlank(config)) {
        log.info("Configuring ehcache (" + name + ") from Sakai config: " + config);
        try {
          // ehcache specific code here - no exceptions thrown
          //noinspection deprecation
          new CacheInitializer().configure(config).initialize(cache.getCacheConfiguration());
        } catch (Exception e) {
          // nothing to do here but proceed
          log.error("Failure configuring cache (" + name + "): " + config + " :: " + e, e);
        }
      }

      /* KNL-532 - Upgraded Ehcache 2.5.1 (2.1.0+) defaults to no stats collection.
       * We may choose to allow configuration per-cache for performance tuning.
       * For now, we default everything to on, while this property allows a system-wide override.
       */
      boolean enabled = true;
      if (serverConfigurationService != null) {
        enabled =
            !serverConfigurationService.getBoolean("memory.cache.statistics.force.disabled", false);
      }
      if (cache.isStatisticsEnabled() != enabled) {
        cache.setStatisticsEnabled(enabled);
      }
    }

    // apply config to the cache (every time)
    if (configuration != null) {
      if (configuration.getMaxEntries() >= 0) {
        cache.getCacheConfiguration().setMaxEntriesLocalHeap(configuration.getMaxEntries());
      }
      if (configuration.isEternal()) {
        cache.getCacheConfiguration().setTimeToLiveSeconds(0l);
        cache.getCacheConfiguration().setTimeToIdleSeconds(0l);
      } else {
        if (configuration.getTimeToLiveSeconds() >= 0) {
          cache.getCacheConfiguration().setTimeToLiveSeconds(configuration.getTimeToLiveSeconds());
        }
        if (configuration.getTimeToIdleSeconds() >= 0) {
          cache.getCacheConfiguration().setTimeToIdleSeconds(configuration.getTimeToIdleSeconds());
        }
      }
      cache.getCacheConfiguration().setEternal(configuration.isEternal());
      cache.setStatisticsEnabled(configuration.isStatisticsEnabled());
      log.info("Configured ehcache (" + name + ") from inputs: " + configuration);
    }

    if (log.isDebugEnabled()) log.debug("Returning initialized ehcache (" + name + "): " + cache);
    return cache;
  }
Пример #13
0
  @Override
  public String getStatus() {
    // MIRRORS the OLD status report
    final StringBuilder buf = new StringBuilder();
    buf.append("** Memory report\n");
    buf.append("freeMemory: ").append(Runtime.getRuntime().freeMemory());
    buf.append(" totalMemory: ");
    buf.append(Runtime.getRuntime().totalMemory());
    buf.append(" maxMemory: ");
    buf.append(Runtime.getRuntime().maxMemory());
    buf.append("\n\n");

    String[] allCacheNames = cacheManager.getCacheNames();
    Arrays.sort(allCacheNames);
    ArrayList<Ehcache> caches = new ArrayList<Ehcache>(allCacheNames.length);
    for (String cacheName : allCacheNames) {
      Ehcache cache = cacheManager.getCache(cacheName);
      caches.add(cache);
    }

    // summary (cache descriptions)
    for (Ehcache cache : caches) {
      Cache c = new EhcacheCache(cache);
      buf.append(c.getDescription()).append("\n");
    }

    // extended report
    // TODO probably should remove this
    buf.append("\n** Extended Cache Report\n");
    for (Ehcache cache : caches) {
      buf.append(cache.toString());
      buf.append("\n");
    }

    // config report
    buf.append("\n** Current Cache Configurations\n");
    // determine whether to use old or new form keys
    boolean legacyKeys = true; // set true for a 2.9/BasicMemoryService compatible set of keys
    String maxKey = "maxEntries";
    String ttlKey = "timeToLive";
    String ttiKey = "timeToIdle";
    String eteKey = "eternal";
    //noinspection ConstantConditions
    if (legacyKeys) {
      maxKey = "maxElementsInMemory";
      ttlKey = "timeToLiveSeconds";
      ttiKey = "timeToIdleSeconds";
    }
    // DEFAULT cache config
    CacheConfiguration defaults = cacheManager.getConfiguration().getDefaultCacheConfiguration();
    long maxEntriesDefault = defaults.getMaxEntriesLocalHeap();
    long ttlSecsDefault = defaults.getTimeToLiveSeconds();
    long ttiSecsDefault = defaults.getTimeToIdleSeconds();
    boolean eternalDefault = defaults.isEternal();
    buf.append("# DEFAULTS: ")
        .append(maxKey)
        .append("=")
        .append(maxEntriesDefault)
        .append(",")
        .append(ttlKey)
        .append("=")
        .append(ttlSecsDefault)
        .append(",")
        .append(ttiKey)
        .append("=")
        .append(ttiSecsDefault)
        .append(",")
        .append(eteKey)
        .append("=")
        .append(eternalDefault)
        .append("\n");
    // new: timeToLive=600,timeToIdle=360,maxEntries=5000,eternal=false
    // old: timeToLiveSeconds=3600,timeToIdleSeconds=900,maxElementsInMemory=20000,eternal=false
    for (Ehcache cache : caches) {
      long maxEntries = cache.getCacheConfiguration().getMaxEntriesLocalHeap();
      long ttlSecs = cache.getCacheConfiguration().getTimeToLiveSeconds();
      long ttiSecs = cache.getCacheConfiguration().getTimeToIdleSeconds();
      boolean eternal = cache.getCacheConfiguration().isEternal();
      if (maxEntries == maxEntriesDefault
          && ttlSecs == ttlSecsDefault
          && ttiSecs == ttiSecsDefault
          && eternal == eternalDefault) {
        // Cache ONLY uses the defaults
        buf.append("# memory.").append(cache.getName()).append(" *ALL DEFAULTS*\n");
      } else {
        // NOT only defaults cache, show the settings that differ from the defaults
        buf.append("memory.").append(cache.getName()).append("=");
        boolean first = true;
        if (maxEntries != maxEntriesDefault) {
          //noinspection ConstantConditions
          first = addKeyValueToConfig(buf, maxKey, maxEntries, first);
        }
        if (ttlSecs != ttlSecsDefault) {
          first = addKeyValueToConfig(buf, ttlKey, ttlSecs, first);
        }
        if (ttiSecs != ttiSecsDefault) {
          first = addKeyValueToConfig(buf, ttiKey, ttiSecs, first);
        }
        if (eternal != eternalDefault) {
          addKeyValueToConfig(buf, eteKey, eternal, first);
        }
        buf.append("\n");
        // TODO remove the overflow to disk check
        //noinspection deprecation
        if (cache.getCacheConfiguration().isOverflowToDisk()) {
          // overflowToDisk. maxEntriesLocalDisk
          buf.append("# NOTE: ")
              .append(cache.getName())
              .append(" is configured for Overflow(disk), ")
              .append(cache.getCacheConfiguration().getMaxEntriesLocalDisk())
              .append(" entries\n");
        }
      }
    }

    final String rv = buf.toString();
    log.info(rv);

    return rv;
  }