cachestore.java
来自「很棒的web服务器源代码」· Java 代码 · 共 1,263 行 · 第 1/3 页
JAVA
1,263 行
// CacheStore.java// $Id: CacheStore.java,v 1.65 2003/02/14 16:22:31 ylafon Exp $// (c) COPYRIGHT MIT, INRIA and Keio, 1999.// Please first read the full copyright statement in file COPYRIGHT.htmlpackage org.w3c.www.protocol.http.cache;import java.util.Enumeration;import java.util.Hashtable;import java.util.Vector;import java.io.BufferedReader;import java.io.BufferedWriter;import java.io.File;import java.io.FileNotFoundException;import java.io.FileReader;import java.io.FileWriter;import java.io.FilenameFilter;import java.io.IOException;import java.io.PrintStream;import java.io.Reader;import java.io.Writer;import org.w3c.util.LRUAble;import org.w3c.util.ObservableProperties;import org.w3c.util.PropertyMonitoring;import org.w3c.util.SyncLRUList;import org.w3c.tools.sorter.Sorter;public class CacheStore implements PropertyMonitoring { /** * Name of the property giving the cache's directory. * This property defaults to the current directory. */ public static final String CACHE_DIRECTORY_P = "org.w3c.www.protocol.http.cache.directory"; /** * The name of the properties indicating the storesize of the cache * (in bytes). * This property will give the value of the disk-based cache size. This * value only takes into account the size of the entities saved, not * the size of the associated headers, and not the physical size on the * disc. * <p>This property defaults to <strong>20</strong> Mbytes. */ public static final String STORE_SIZE_P = "org.w3c.www.protocol.http.cache.storesize"; /** * Name of the property used to knkow the percentage of bytes to be * kept after a garbage collection * It defaults to 0.80 (80% of the cache size) */ public static final String GARBAGE_COLLECTION_THRESHOLD_P = "org.w3c.www.protocol.http.cache.gc_threshold"; /** * Name of the property indicating the max size for files to be cached. * This property gives the ratio (relative to the cache size) of * the number of bytes a single entry is able to occupy. * <p>The ratio should be given as a floating point value between * <strong>0</strong> and <strong>1</strong>. If set to <strong>0.1 * </strong> and the cache size is <strong>5000000</strong>, files larger * then <strong>500000</strong> will not be cached (except if garbage * collection is disbabled). * <p>This property defaults to <strong>0.1</strong>. * Note that the generation size will be taken from this threshold */ public static final String FILE_SIZE_RATIO_P = "org.w3c.www.protocol.http.cache.fileSizeRatio"; /** * Name of the property enabling garbage collection of the cache. * This property defaults to <strong>true</strong>. */ public static final String GARBAGE_COLLECTION_ENABLED_P = "org.w3c.www.protocol.http.cache.garbageCollectionEnabled"; /** * Name of the property indicating the amount of time in second between * two synchronization of the database (aka dump on disk) * Milliseconds */ public static final String SYNCHRONIZATION_DELAY_P = "org.w3c.www.protocol.http.cache.SynchronizationDelay"; /** * Name of the property indicating the amount of time in second between * two attempts to compact generations. In milliseconds */ public static final String GENERATION_COMPACT_DELAY_P = "org.w3c.www.protocol.http.cache.GenerationCompactDelay"; /** * Name of the property indicating the maximal number of resources * the cache can load in memory (not the content of the resources) */ public static final String MAX_CACHED_RESOURCES_P = "org.w3c.www.protocol.http.cache.MaxCachedResources"; /** * Name of the property indicating the maximal number of generations * in this cache store */ public static final String MAX_GENERATIONS_P = "org.w3c.www.protocol.http.cache.MaxGenerations"; //Generation file name. public static final String GENERATION_FILENAME = "gen-"; // the store state private StoreState state = null; // the state file private File statefile = null; private SyncLRUList generations = null; // the capacity of this cache private long bytelimit = 0; // the store capacity of this cache private long storelimit = 0; // the usual length of a generation private long generationlimit = 0; // the maximum number of CachedResource in memory private int cr_limit = 0; // the file ratio (threshold) private double threshold = 0.1; // the ratio kept after a garbage collection private double gc_kept_ratio = 0.80; // the number of directories used (default 128) private int nb_dir = 128; // The cache directory private File cache_dir = null; // the directories where bodies are stored private File dirs[] = null; // the garbage collection flag private boolean garbageCollectionEnabled = true; // our father private CacheFilter filter = null; // the traditional debug flag private boolean debug = false; // the maximal number of generations private int max_generation = 10; // the delay between two store sync private long sync_delay = 60000; // the delay between two attempts to compact the database private long gencomp_delay = 60000; /** * The properties we initialized ourself from. */ protected ObservableProperties props = null; /** * Property monitoring for the CacheStore. * The CacheStore allows you to dynamically (typically through the property * setter) change the class of the sweeper, the validator, the size... * @param name The name of the property that has changed. * @return A boolean, <strong>true</strong> if the change was made, * <strong>false</strong> otherwise. */ public boolean propertyChanged (String name) { double dval; if ( name.equals(CacheFilter.CACHE_SIZE_P) ) { bytelimit = props.getLong(name, bytelimit); return true; } else if (name.equals(STORE_SIZE_P)) { storelimit = props.getLong(name, storelimit); return true; } else if ( name.equals(CacheFilter.DEBUG_P) ) { debug = props.getBoolean(name, debug); return true; } else if ( name.equals(GARBAGE_COLLECTION_ENABLED_P) ) { garbageCollectionEnabled = props.getBoolean(name, true); return true; } else if ( name.equals(FILE_SIZE_RATIO_P) ) { dval = props.getDouble(name, threshold); if ((dval <= (double) 0.00001) || (dval >= (double) 1.0)) return false; threshold = dval; return true; } else if ( name.equals(GARBAGE_COLLECTION_THRESHOLD_P) ) { dval = props.getDouble(name, gc_kept_ratio); if ((dval <= (double) 0.00001) || (dval >= (double) 1.0)) return false; gc_kept_ratio = dval; return true; } else if ( name.equals(MAX_GENERATIONS_P) ) { int new_nb = props.getInteger(name, max_generation); if (new_nb <= 0 ) { return false; } // not that we won't do too much if it is reduced // the user will have to clean the cache... max_generation = new_nb; return true; } else if ( name.equals(MAX_CACHED_RESOURCES_P) ) { int new_nb = props.getInteger(name, cr_limit); if (new_nb <= 0 ) { return false; } // not that we won't do too much if it is reduced // the user will have to clean the cache... cr_limit = new_nb; return true; } else if ( name.equals(SYNCHRONIZATION_DELAY_P) ) { long new_nb = props.getLong(name, sync_delay); if (new_nb <= 0 ) { return false; } // not that we won't do too much if it is reduced // the user will have to clean the cache... sync_delay = new_nb; return true; } else if ( name.equals(GENERATION_COMPACT_DELAY_P) ) { long new_nb = props.getLong(name, gencomp_delay); if (new_nb <= 0 ) { return false; } // not that we won't do too much if it is reduced // the user will have to clean the cache... gencomp_delay = new_nb; return true; } // nothing changed, everything is ok! return true; } public StoreState getState() { return state; } /** * return the cache sweeper used by the cache * @return an instance of CacheSweeper */ public CacheSweeper getSweeper() { return filter.sweeper; } /** * return the serializer used by the cache * @return an instance of Serializer */ public CacheSerializer getSerializer() { return filter.serializer; } /** * return the cache validator used by the cache * @return an instance of CacheValidator */ public CacheValidator getValidator() { return filter.validator; } /** * Get the next generation (in LRU order). * @param gen the current generation * @return a generation */ public CacheGeneration getNextGeneration(CacheGeneration gen) { if (generations != null) { return (CacheGeneration) generations.getNext(gen); } return null; } /** * Get the previous generation (in LRU order). * @param gen the current generation * @return a generation */ public CacheGeneration getPrevGeneration(CacheGeneration gen) { if (generations != null) { return (CacheGeneration) generations.getPrev(gen); } return null; } /** * Get the last generation, ie the Most recently used generation * @return a CacheGeneration, the most recently used one */ public CacheGeneration getMRUGeneration() { return (CacheGeneration) generations.getHead(); } /** * Get the fill ratio of the last generation (the most recently used) */ public float getMRUGenerationRatio() { CacheGeneration last = (CacheGeneration)generations.getHead(); return (last == null) ? (float)0.0 : last.getFillRatio(); } /** * Get the LRU generation, ie the Least recently used generation * @return a CacheGeneration, the least recently used one */ public CacheGeneration getLRUGeneration() { return (CacheGeneration) generations.getTail(); } /** * Get the oldest loaded generation * @return a generation */ public CacheGeneration getLRULoadedGeneration() { CacheGeneration gen = (CacheGeneration) generations.getTail(); while ((gen != null) && (! gen.isLoaded())) { gen = (CacheGeneration) generations.getPrev(gen); } return gen; } /** * Get the synchronization delay between to sync, in milliseconds * @return a long, the number of milliseconds */ public long getSyncDelay() { return sync_delay; } /** * Get the delay between two attempts to compact the generations. * @return a long, the number of milliseconds */ public long getCompactGenerationDelay() { return gencomp_delay; } /** * Create and add a new Generation. WARNING, this method is not * synchronized. * @return the newly created generation or null if the max number * of generations is reached or it the current size of the cache * (in memory) is too big to accept a new generation. * @exception InvalidCacheException if the cache is corrupted */ protected CacheGeneration addNewGeneration() throws InvalidCacheException { long byteleft = bytelimit - state.getByteCount(); if ((state.getNbGeneration() < max_generation) && (byteleft > generationlimit)) { CacheGeneration newgen = new CacheGeneration(this, generationlimit); setGenerationFile(newgen); state.notifyGenerationCreated(newgen); generations.toHead(newgen); return newgen; } else { return null; } } /** * Load the given generation and unload the LRU loaded * generation if necessary. * @param cg the generation to load * @exception InvalidCacheException if the cache is corrupted */ protected CacheGeneration loadGeneration(CacheGeneration cg) throws InvalidCacheException { // load this generation and unload the LRU loaded // generation CacheGeneration cglru = getLRULoadedGeneration(); synchronized(this) { // FIRST, unload the LRU loaded generation if (getCachedByteFree() < generationlimit) { if (cglru != null) unloadGeneration(cglru); } return _loadGeneration(cg); } } /** * Load a "unloaded" generation * @return the loaded generation * @exception InvalidCacheException if the cache is corrupted */ private CacheGeneration _loadGeneration(CacheGeneration cg) throws InvalidCacheException { try { Reader reader = new BufferedReader(new FileReader(cg.getGenerationFile())); cg = getSerializer().readGeneration(cg, reader); state.notifyGenerationLoaded(cg); return cg; } catch (FileNotFoundException ex) { String msg = "Generation file does not exists: "+ cg.getGenerationFile().getAbsolutePath(); throw new InvalidCacheException(msg); } catch (IOException ex) { String msg = "IOError reading "+ cg.getGenerationFile().getAbsolutePath(); throw new InvalidCacheException(msg); }
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?