Skip to content
thanhvc edited this page Jul 27, 2011 · 8 revisions

Caching Context

Using the FactoryStorageCacheService and CacheType to build the kind of ExoCache and FutureExoCache.

FactoryStorageCacheService: The Factory which uses the CacheService to create the region caching for management in itself.

CacheType: Initialize the FutureCache from eXoCache but, it is also create the CacheLoader in the FutureCache. When you need to load data from the data source. You only invoke the cacheLoader.retrieve(ServiceContext) method such as the decorator more functions into the FutureCache. (Visitor DP). and then the ServiceContext.execute() method will execute to load the data from data source.

Model

FooKey: which keeps in the eXoCache such as Key

FooFilterKey: which keeps in the FutureCache with the ServiceContext for next time when you want to query by fooFilter.

ListFoosKey: which keeps in the FutureCache with the ServiceContext for next time when you want to query by fooFilter, offset and limit.

FoodData: which wraps the Foo model such as Value in the eXoCache.

Data Caching

Using the eXoCache to keep the FooKey, FooData

Service Context Caching

Using the FutureExoCache<ServiceContext, Key, Value>

Key: FooKey, FooFilterKey, ListFoosKey.

Data: FooData, ListFoosData.

In CachedFooStorage:

private final ExoCache<FooKey, FooData> etkFooCache;
private final FutureETKCache<FooKey, FooData, ServiceContext<FooData>> fooCache;
public CachedFooStorage(final FooStorageImpl storage, final FactoryStorageCacheService cacheService) {
   this.etkFooCache = cacheService.getFooCache();
   //Initializes the EtkFutureCache which executes for caching ServiceContext
   this.fooCache = CacheType.FOO.createFutureCache(etkFooCache);
} 

FutureETKCache:

public <K extends CacheKey, V extends Serializable> FutureETKCache<K, V, ServiceContext<V>> createFutureCache(ExoCache<K,V> cache) {
 return new FutureETKCache<K, V, ServiceContext<V>>(new CacheLoader<K, V>(), cache);
}

And ClassLoader class:

public class CacheLoader<K extends CacheKey, V> implements Loader<K, V, ServiceContext<V>> {
  @Override
  public V retrieve(ServiceContext<V> context, K key) throws Exception {
    return context.execute();
  }
 }

Caching Processing

CachedFooStorage which is middle layer to communicate with Service layer and Database layer. It executes following the priority: first check in caching and second check in database and delegate the task to FutureCache.get() method.

public final V get(final C context, final K key) {
// First we try a simple cache get
V value = get(key);
 // If it does not succeed then we go through a process that will avoid to
// load
// the same resource concurrently
if (value == null) {
  // Create our future
  FutureTask<V> future = new FutureTask<V>(new Callable<V>() {
    public V call() throws Exception {
      // Retrieve the value from the loader
      V value = loader.retrieve(context, key);//CacheLoader.retrieve() invokes, pass ServiceContext params

      //
      if (value != null) {
        // Cache it, it is made available to other threads (unless someone
        // removes it)
        put(key, value);

        // Return value
        return value;
      } else {
        return null;
      }
    }
  });
  // This boolean means we inserted in the local
  boolean inserted = true;
  //
  try {
    FutureTask<V> phantom = futureEntries.putIfAbsent(key, future);

    // Use the value that could have been inserted by another thread
    if (phantom != null) {
      future = phantom;
      inserted = false;
    } else {
      future.run();
    }
    // Returns the value
    value = future.get();
  } catch (ExecutionException e) {
    if (e.getCause() != null) {
      throw new UndeclaredThrowableException(e.getCause());
    } else {
      log.error("Computing of resource " + key + " threw an exception", e.getCause());
    }
  } catch (Exception e) {
    log.error("Retrieval of resource " + key + " threw an exception", e);
  } finally {
    // Clean up the per key map but only if our insertion succeeded and with
    // our future
    if (inserted) {
      futureEntries.remove(key, future);
    }
  }
 }
 //
 return value;
}

Clone this wiki locally