⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 clock.java

📁 derby database source code.good for you.
💻 JAVA
📖 第 1 页 / 共 4 页
字号:
/*   Derby - Class org.apache.derby.impl.services.cache.Clock   Copyright 1997, 2004 The Apache Software Foundation or its licensors, as applicable.   Licensed under the Apache License, Version 2.0 (the "License");   you may not use this file except in compliance with the License.   You may obtain a copy of the License at      http://www.apache.org/licenses/LICENSE-2.0   Unless required by applicable law or agreed to in writing, software   distributed under the License is distributed on an "AS IS" BASIS,   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   See the License for the specific language governing permissions and   limitations under the License. */package org.apache.derby.impl.services.cache;import org.apache.derby.iapi.services.cache.CacheManager;import org.apache.derby.iapi.services.cache.Cacheable;import org.apache.derby.iapi.services.cache.CacheableFactory;import org.apache.derby.iapi.services.cache.SizedCacheable;import org.apache.derby.iapi.services.context.ContextManager;import org.apache.derby.iapi.services.daemon.DaemonService;import org.apache.derby.iapi.services.daemon.Serviceable;import org.apache.derby.iapi.error.StandardException;import org.apache.derby.iapi.services.monitor.Monitor;import org.apache.derby.iapi.services.sanity.SanityManager;import org.apache.derby.iapi.services.cache.ClassSize;import org.apache.derby.iapi.util.Matchable;import org.apache.derby.iapi.util.Operator;import org.apache.derby.iapi.reference.SQLState;import java.util.ArrayList;import java.util.Hashtable;import java.util.Properties;/**	A cache manager that uses a Hashtable and a ArrayList. The ArrayList holds	CachedItem objects, each with a holder object. The Hashtable is keyed	by the identity of the holder object (Cacheable.getIdentity()) and	the data portion is a pointer to the CachedItem. CachedItems that have	holder objects with no identity do not have entries in the hashtable.	<P>	CachedItems can in various state.	<UL>	<LI>isValid - the entry has a valid identity	<LI>inCreate - the entry is being created or being faulted in from persistent store	<LI>inClean - the entry is being written out to persistent store	<LI>isKept - the entry is currently being looked at/updated, do not remove or				clean it.	</OL>	<P>Multithreading considerations:<BR>	A clock cache manager must be MT-safe.	All member variables are accessed single threaded (synchronized on this) or	set once or readonly. Assumptions: holders size() and addElement must be	synchronized.	<BR>	CachedItem is never passed out of the clock cache manager, only the	Cacheable object is.  The cachedItem is responsible for the setting and	clearing of its own member fields (RESOLVE: now they are done in cache	manager, need to be moved to the cachedItem).  The cache manager will	following the following rules while accessing a cacheditem:	<UL>	<LI>invalid item is never returned from the cache	<LI>setValidState and isValid() is only called single threaded through the cache manager.	<LI>keep() and isKept() is only called single threaded through the cache	manager once the item has been added to the holders array	<LI>item that isKept() won't be cleaned or removed or invalidated from the cache.	<LI>item that is inClean() or inCreate(), the cache manager	will wait on the cachedItem to finish cleaning or creating before it	returns the cached item outside of the cache.	</UL>	<BR>	The cacheable must be cleaned thru the cache if it is managed by a cache.	On CacheItem, a inClean state is maintain to stablelize the content of the	cacheable while it is being cleaned.  Only unkept items are cleaned.  If an	item is found to be inClean, it will wait until it exits the inClean state.	If a cached item calls it own clean method without notifying the cache, it	has to stablize its content for the duration of the clean.	<BR>	It is assumed that the cacheable object maintain its own MT-safeness.<BR>	@see CachedItem	@see Cacheable*/final class Clock extends Hashtable implements CacheManager, Serviceable {	/*	** Fields	*/	public final CacheStat			stat;	private DaemonService		cleaner;	// the background worker thread who is going to									// do pre-flush for this cache. 	private final ArrayList		holders;    private int validItemCount = 0;	private long			maximumSize;    private boolean useByteCount; // regulate the total byte count or the entry count    private long currentByteCount = 0;    /* currentByteCount should be the sum of entry.getSize() for all entries in the cache.     * That is, it should be the sum of getItemSize( item, false) for each item in the holders     * vector.     */    private static final int ITEM_OVERHEAD = ClassSize.estimateBaseFromCatalog( CachedItem.class)        + ClassSize.getRefSize() // one ref per item in the holder ArrayList        + ClassSize.estimateHashEntrySize();	private final CacheableFactory holderFactory;	private boolean		active;		// true if active for find/create	private String		name;		// name of the cache, mainly for debugging purposes.	private int			clockHand;             // the sweep of the clock hand		private	int			myClientNumber;	// use this number to talk to cleaner service	private boolean	wokenToClean;	// true if the client was woken to clean, false if to shrink	private boolean   cleanerRunning;	private boolean	  needService;	/**		Construct a new clock cache manager.		<P>MT - not needed for constructor.		@param holderClass the cacheable object class		@param name the name of the cache		@param initParam parameter to call the cacheable object the first time		it is being initialized.		@param initialSize the initial number of cachable object this cache		holds.		@param maximumSize the maximum size of the cache.  The cache may grow		from initialSize to maximumSize if the cache policy notices that there		is not enough free buffers availiable.  Once the cache hits maximumSize		it will not grow.  If the cache is full, an exception will be thrown	*/	Clock(CacheableFactory holderFactory,                  String name,                  int initialSize,                  long maximumSize,                  boolean useByteCount)    {        super(initialSize, (float) 0.95);		this.maximumSize = maximumSize;		this.holderFactory = holderFactory;        this.useByteCount = useByteCount;		if (SanityManager.DEBUG) {		  if (SanityManager.DEBUG_ON(ClockFactory.CacheTrace)) {			SanityManager.DEBUG(ClockFactory.CacheTrace, "initializing " + name + " cache to size " + initialSize);		  }		}		//int delta = initialSize / 2;		//if (delta < 5)		//	delta = 5;		holders = new ArrayList(initialSize);		this.name = name;		active = true;		this.stat = new CacheStat();		stat.initialSize = initialSize;		stat.maxSize = maximumSize;    }	/**		Find the object or materialize one in the cache.  If it has not been		created in the persistent store yet, return null.		<P>MT - must be MT-safe.  The cache is single threaded through finding		the item in cache and finding a free item if it is not in cache, thus		preventing another thread from creating the same item while is is being		faulted in.  (RESOLVE - this is really low performance if the cache		cleaner cannot keep a steady supply of free items and we have to do an		I/O while blocking the cache).   If it needs to be faulted in, the		inCreate bit is set.  The item is kept before it exits the sync block. 		<BR>		If the item is in cache but in the middle of being faulted in or		cleaned, it needs to wait until this is done being before returning.		<BR>		The keep status prevents other threads from removing this item.  		The inCreate status prevents other threads from looking at or writing		out this item while it is being faulted in.		(RESOLVE: need to handle the case where the object is marked for		removal and being waited on)		@param key the key to the object		@return a cacheable object that is kept in the cache.		@exception StandardException Cloudscape Standard error policy	*/	public Cacheable find(Object key) throws StandardException {		CachedItem item;		boolean		add;		/*		** We will only loop if someone else tried to add the		** same key as we did and they failed.  In this case		** we start all over.  An example of this would be an		** attempt to cache an object that failed due to a 		** transient error (e.g. deadlock), which should not		** prevent another thread from trying to add the 		** key to the cache (e.g. it might be the one holding		** the lock that caused the other thread to deadlock).		*/		while (true)		{			add = false;			synchronized (this) {					if (!active)					return null;					item = (CachedItem) get(key);					if (item != null) {					item.keepAfterSearch();										stat.findHit++;					if (SanityManager.DEBUG) {					  if (SanityManager.DEBUG_ON(ClockFactory.CacheTrace)) 					  {						SanityManager.DEBUG(ClockFactory.CacheTrace, name + ": Found key " +											key + " already in cache, item " + item);					  }					}				}			}				// no entry was found, need to add one			if (item == null) {					// get a free item				item = findFreeItem();				stat.findMiss++;					if (SanityManager.DEBUG) {				  if (SanityManager.DEBUG_ON(ClockFactory.CacheTrace)) 				  {					SanityManager.DEBUG(ClockFactory.CacheTrace, name + ": Find key " +										key + " Not in cache, get free item " + item);				  }				}						if (SanityManager.DEBUG)					SanityManager.ASSERT(item != null, "found null item");					synchronized (this) {					CachedItem inCacheItem = (CachedItem) get(key);						if (inCacheItem != null) {						// some-one beat us to adding an item into the cache,						// just use that one						item.unkeepForCreate();							item = inCacheItem;						item.keepAfterSearch();					} else {						// yes, we really are the ones to add it						put(key, item);						add = true;						if (SanityManager.DEBUG) {							if (SanityManager.DEBUG_ON("memoryLeakTrace")) {								if (size() > ((11 * maximumSize) / 10))									System.out.println("memoryLeakTrace:Cache:" + name + " " + size());							}						}					}				}			}						if (add) {					if (SanityManager.DEBUG) {				  if (SanityManager.DEBUG_ON(ClockFactory.CacheTrace))				  {					SanityManager.DEBUG(ClockFactory.CacheTrace, name + " Added " + 										key + " to cache, item " + item);				  }				}					stat.findFault++;				return addEntry(item, key, false, (Object) null);			}							Cacheable entry = item.use();			if (entry == null) {				// item was not added by the other user successfully ...				synchronized (this) {					item.unkeep();				}				// try to hash the key again (see				// comment at head of loop)				continue;			}				return entry;		}	}	/**		Find an object in the cache.  Do not fault in or create the object if		is is not found in the cache.		<P>MT - must be MT-safe.  The cache is single threaded through finding		the item in cache.  If it needs to wait for it to be faulted in or		cleaned it is synchronized/waited on the cached item itself.		@param key the key to the object		@return a cacheable object that is kept in the cache.	*/	public Cacheable findCached(Object key) throws StandardException {		CachedItem item;		synchronized (this) {			if (!active)				return null;					item = (CachedItem) get(key);			if (item == null) {				stat.findCachedMiss++;				return null;			} else				stat.findCachedHit++;						item.keepAfterSearch();		}		Cacheable entry = item.use();		if (entry == null) {			// item was not added by the other user successfully ...			synchronized (this) {				item.unkeep();			}		}		return entry;	}    /**     * Mark a set of  entries as having been used. Normally this is done as a side effect     * of find() or findCached. Entries that are no longer in the cache are ignored.     *     * @param key the key of the used entry.     */    public void setUsed( Object[] keys)    {		CachedItem item;        for( int i = 0; i < keys.length;)        {            // Do not hold the synchronization lock for too long.            synchronized (this)            {                if (!active)                    return;                int endIdx = i + 32;                if( endIdx > keys.length)                    endIdx = keys.length;                for( ; i < endIdx; i++)                {                    if( keys[i] == null)                        return;                                        item = (CachedItem) get(keys[i]);                    if( null != item)                        item.setUsed( true);                }            }        }    } // end of setUsed	/**		Create a new object with the said key.		<P>MT - must be MT-safe.  Single thread thru verifying no such item		exist in cache and finding a free item, keep the item and set inCreate		state.  The actual creating of the  object is done outside		the sync block and is protected by the isKept and inCreate bits.		@param key the key to the object		@return a cacheable object that is kept in the cache.  		@exception StandardException Cloudscape Standard error policy	*/	public Cacheable create(Object key, Object createParameter) throws StandardException {		// assume the item is not already in the cache		CachedItem item = findFreeItem();		stat.create++;		synchronized (this) {			if (!active)				return null;			if (get(key) != null) {				item.unkeepForCreate();				throw StandardException.newException(SQLState.OBJECT_EXISTS_IN_CACHE, this.name, key);			}			put(key, item);			if (SanityManager.DEBUG) {				if (SanityManager.DEBUG_ON("memoryLeakTrace")) {					if (size() > ((11 * maximumSize) / 10))						System.out.println("memoryLeakTrace:Cache:" + name + " " + size());				}			}		}		Cacheable entry = addEntry(item, key, true, createParameter);			if (SanityManager.DEBUG) {			if (entry != null)				SanityManager.ASSERT(item.getEntry() == entry);		}		return entry;	}	/**		The caller is no longer looking at or updating the entry.  Since there		could be more than one piece of code looking at this entry, release		does not mean nobody is looking at or updating the entry, just one		less.  If the cacheable is marked for remove (someone is waiting to		remove the persistent object once nobody is looking at it), then notify		the waiter if this is the last one looking at it.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -