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 + -
显示快捷键?