Beispiel #1
0
 @Override
 public String getName() {
   if (refreshAheadConfig.getName() != null) {
     return refreshAheadConfig.getName();
   }
   return super.getName();
 }
Beispiel #2
0
  private void initSupportCache() {
    // create the support cache
    // make this cache clustered in the same way as the underlying cache,
    this.supportConfig = new CacheConfiguration();
    supportConfig.name(
        underlyingCache.getName() + "_" + getClass().getName() + "_refreshAheadSupport");
    supportConfig =
        supportConfig.persistence(new PersistenceConfiguration().strategy(Strategy.NONE));
    int activeSize =
        2 * refreshAheadConfig.getBatchSize() * refreshAheadConfig.getNumberOfThreads();
    supportConfig = supportConfig.maxEntriesLocalHeap(activeSize);
    supportConfig = supportConfig.memoryStoreEvictionPolicy(MemoryStoreEvictionPolicy.LRU);
    supportConfig = supportConfig.timeToLiveSeconds(DEFAULT_SUPPORT_TTL_SECONDS);

    // TC stuff
    if (underlyingCache.getCacheConfiguration().isTerracottaClustered()) {
      supportConfig =
          supportConfig.persistence(new PersistenceConfiguration().strategy(Strategy.DISTRIBUTED));

      TerracottaConfiguration newTerracottaConfig = new TerracottaConfiguration().clustered(true);

      newTerracottaConfig.consistency(Consistency.STRONG);

      supportConfig.addTerracotta(newTerracottaConfig);
    } else {
      supportConfig.setMaxElementsOnDisk(activeSize);
    }

    // here we try to create the support cache.
    this.supportCache = new Cache(supportConfig);

    Ehcache prior = underlyingCache.getCacheManager().addCacheIfAbsent(supportCache);
    if (prior != supportCache) {
      throw new IllegalStateException(
          "Unable to add refresh ahead support cache due to name collision: "
              + refreshAheadConfig.getName());
    }

    // wipe it on startup. might wobble in a clustered case, but clears out orphans.
    prior.removeAll();

    // catch the dispose. not sure this is the best way to do it at all.
    // we could register a listener alternatively
    underlyingCache.registerCacheExtension(
        new CacheExtension() {

          @Override
          public void init() {}

          @Override
          public Status getStatus() {
            return underlyingCache.getStatus();
          }

          @Override
          public void dispose() throws CacheException {
            RefreshAheadCache.this.localDispose();
          }

          @Override
          public CacheExtension clone(Ehcache cache) throws CloneNotSupportedException {
            throw new CloneNotSupportedException();
          }
        });
  }
Beispiel #3
0
 @Override
 public Element get(Serializable key) throws IllegalStateException, CacheException {
   Element elem = super.get(key);
   possiblyTriggerRefresh(elem, refreshAheadConfig.getTimeToRefreshMillis());
   return elem;
 }
Beispiel #4
0
  private void initWorkQueue() {
    BatchWorker<Object> batchWorker =
        new BatchWorker<Object>() {

          @Override
          public void process(Collection<? extends Object> collection) {

            // only fetch this once for each process() call
            long accessTime = System.currentTimeMillis();

            HashSet<Object> keysToProcess = new HashSet<Object>();
            for (Object key : collection) {

              // check if it was loaded by someone else in the meantime -- does it still qualify for
              // refresh ahead?
              Element quickTest = underlyingCache.getQuiet(key);
              if (quickTest == null
                  || checkForRefresh(
                      quickTest, accessTime, refreshAheadConfig.getTimeToRefreshMillis())) {
                final Element ersatz = new Element(key, REFRESH_VALUE);

                if (supportCache.putIfAbsent(ersatz) == null) {
                  // work, work, work
                  keysToProcess.add(key);
                }
              }
            }
            try {
              // iterate through the loaders
              for (CacheLoader loader : underlyingCache.getRegisteredCacheLoaders()) {
                // if we are out of keys, punt
                if (keysToProcess.isEmpty()) {
                  break;
                }

                // try and load them all
                Map<? extends Object, ? extends Object> values = loader.loadAll(keysToProcess);
                // subtract the ones that were loaded
                keysToProcess.removeAll(values.keySet());
                try {
                  for (Map.Entry<? extends Object, ? extends Object> entry : values.entrySet()) {
                    Element newElement = new Element(entry.getKey(), entry.getValue());
                    underlyingCache.put(newElement);
                    refreshSuccessCount.incrementAndGet();
                  }
                } finally {
                  // subtract from the support cache
                  supportCache.removeAll(values.keySet());
                }
              }
              // assume we got here ok, now evict any that don't evict
              if (refreshAheadConfig.isEvictOnLoadMiss() && !keysToProcess.isEmpty()) {
                underlyingCache.removeAll(keysToProcess);
              }
            } finally {
              // this is utterly paranoid. but still.
              supportCache.removeAll(keysToProcess);
            }
          }
        };

    this.refreshWorkQueue =
        new ThreadedWorkQueue<Object>(
            batchWorker,
            refreshAheadConfig.getNumberOfThreads(),
            new ThreadFactory() {

              @Override
              public Thread newThread(Runnable r) {
                Thread t = new Thread(r);
                t.setDaemon(true);
                return t;
              }
            },
            refreshAheadConfig.getMaximumRefreshBacklogItems(),
            refreshAheadConfig.getBatchSize());
  }