package org.cdlib.xtf.cache; /** * Copyright (c) 2004, Regents of the University of California * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of the University of California nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /** * A cache that generates an entry if one isn't found. The generate() * method must be supplied by the derived class. */ public abstract class GeneratingCache<K,V> extends Cache<K,V> { /** * Constructor - sets up the parameters of the cache. * * @param maxEntries Maximum # of entries. Beyond this, older ones * will be removed. Zero means no limit. * @param maxTime Time (in seconds) an entry can stay in the cache * without being used. Entries older than this will * be removed. Zero means no limit. */ public GeneratingCache(int maxEntries, int maxTime) { super(maxEntries, maxTime); } /** * Check the cache for an entry matching the given key. If not found, * one is generated. * * @param key The key to look up * @return Value corresponding to that key. Never null. */ public synchronized V find(K key) throws Exception { // If we have already generated the value for this key, freshen the // entry and return it. // if (has(key)) { ListEntry entry = (ListEntry)keyMap.get(key); return entry.value; } // Otherwise, create an entry and generate a value for it. curEntry = new ListEntry(); curEntry.key = key; curEntry.value = generate(key); // Add it to the age list (at the tail, since it's the most recently // used). curEntry.lastUsedTime = curEntry.setTime = System.currentTimeMillis(); ageList.addTail(curEntry); // Add it to the key map and log the action. keyMap.put(key, curEntry); logAction("Generated", key, curEntry.value); // Clear the current entry to prevent any future refs to it. V value = curEntry.value; curEntry = null; // Since we've modified the age list, clean up if necessary. cleanup(); // And return the generated value. return value; } // find() /** * Can be called by the generate() method to add a dependency to the * key being generated. * * @param d The dependency to add */ public void addDependency(Dependency d) { assert curEntry != null : "addDependency() may only be called from within generate()"; curEntry.dependencies.add(d); } /** * Called when find() fails to locate an entry for the given key. This * method must be supplied by the derived class, and must produce a value * for the key, or throw an exception if it can't. * * @param key The key to generate a value for. * @return The value for that key * @throws Exception If a value cannot be generated for any reason. */ protected abstract V generate(K key) throws Exception; /** The entry being generated */ private ListEntry curEntry; } // class GeneratingCache