/******************************************************************************* * LastCalc - The last calculator you'll ever need * Copyright (C) 2011, 2012 Uprizer Labs LLC * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Affero General Public License as published * by the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU Affero General Public License for more * details. ******************************************************************************/ package com.lastcalc.cache; import java.io.Serializable; import java.util.*; import java.util.logging.Logger; import javax.cache.*; import com.google.common.collect.*; import com.google.appengine.api.memcache.jsr107cache.GCacheFactory; public class ObjectCache { private static final Logger log = Logger.getLogger(ObjectCache.class.getName()); static Map<Integer, CachedObject> softMap = new MapMaker().softValues().makeMap(); public static <T> T getFast(final long oldestAllowed, final Object... key) { return getFastWithHash(oldestAllowed, Arrays.hashCode(key)); } @SuppressWarnings("unchecked") private static <T> T getFastWithHash(final long oldestAllowed, final int hash) { final CachedObject co = softMap.get(hash); if (co == null) return null; if (System.currentTimeMillis() - oldestAllowed > co.cacheTime) return (T) co.object; else return null; } @SuppressWarnings("unchecked") public static <T> T getSlow(final long oldestAllowed, final Object... key) { final int keyHash = Arrays.hashCode(key); final T o = getFastWithHash(oldestAllowed, keyHash); if (o != null) { log.info("Got from local RAM"); return o; } else { CacheFactory cacheFactory; try { cacheFactory = CacheManager.getInstance().getCacheFactory(); final Cache memcache = cacheFactory.createCache(Collections.emptyMap()); final CachedObject co = (CachedObject) memcache.get(keyHash); if (co != null) { log.info("Got from memcache"); return (T) co.object; } else return null; } catch (final CacheException e) { log.warning("Exception retrieving object from cache: " + e); return null; } } } @SuppressWarnings("unchecked") public static void put(final long expirationDelta, final Object value, final Object... key) { final int keyHash = Arrays.hashCode(key); final CachedObject co = new CachedObject(value); softMap.put(keyHash, co); CacheFactory cacheFactory; try { cacheFactory = CacheManager.getInstance().getCacheFactory(); final Map<Object, Object> props = Maps.newHashMap(); props.put(GCacheFactory.EXPIRATION_DELTA, 3600); final Cache memcache = cacheFactory.createCache(props); memcache.put(keyHash, co); } catch (final CacheException e) { log.warning("Exception retrieving object from cache: " + e); } } public static class CachedObject implements Serializable { /** * */ private static final long serialVersionUID = 2851269118906160513L; public final long cacheTime; public final Object object; public CachedObject(final Object object) { this.object = object; cacheTime = System.currentTimeMillis(); } } }