package edu.gatech.oad.rocket.findmythings.server.db;
import com.google.appengine.api.memcache.AsyncMemcacheService;
import com.google.appengine.api.memcache.Expiration;
import com.google.appengine.api.memcache.MemcacheServiceFactory;
import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.CacheException;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.ExecutionException;
/**
* Shiro cache for App Engine memcached. Some simplifications are made as Memcached
* is global and these caches are meant to be local, with a name and all. I've sorted
* this by wrapping keys in a class to avoid string clashes. We lose efficiency of course
* as it will get serialized.
* <p> I'm using the asynchronous service as it will be a little faster on the puts.
* <p> Memcached on GAE is pretty slow, so I don't think this will speed stuff up, but it
* will save on Datastore accesses, which are expensive.
* @param <K> The raw key class
* @param <V> The value class
*/
class Memcache<K, V> implements Cache<K, V> {
private static final int EXPIRES = 300; // default to 5 minutes
private final AsyncMemcacheService memcacheService;
Memcache(String name) {
this.memcacheService = MemcacheServiceFactory.getAsyncMemcacheService(name);
}
@SuppressWarnings("unchecked")
public V get(K k) throws CacheException {
try {
return (V) memcacheService.get(k).get();
} catch (InterruptedException e) {
return null;
} catch (ExecutionException e) {
return null;
}
}
public V put(K k, V v) throws CacheException {
memcacheService.put(k, v, Expiration.byDeltaSeconds(EXPIRES));
return null;
}
public V remove(K k) throws CacheException {
memcacheService.delete(k);
return null;
}
// broken+unimplementable
public void clear() throws CacheException {
// can't do this as it would clear the whole cache for this app, which could be very expensive
}
public int size() {
return 0; // we can't get a count of just our keys
}
public Set<K> keys() {
return new HashSet<>(); // you just can't list a distributed cache
}
public Collection<V> values() {
return new HashSet<>(); // you can't list a distributed cache
}
}