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

📄 clock.java

📁 derby database source code.good for you.
💻 JAVA
📖 第 1 页 / 共 4 页
字号:
		<BR>		Unless there is a good reason to do otherwise, release should be used		to release a cachable and not directly call cachedItem unkeep, since		unkeep does not handle the case of remove.		<P>MT - must be MT-safe.  Getting and deleteing item from the hashtable		is in the same synchronized block.  If the cacheable object is waiting		to be removed, that is synchronized thru the cachedItem itself		(RESOLVE: need to move this sync block to cachedItem instead)		@param entry the cached entry	 */	public void release(Cacheable entry)  {		boolean removeItem;		CachedItem item;		long toShrink = 0;		synchronized (this) {			item = (CachedItem) get(entry.getIdentity());			if (SanityManager.DEBUG) {				SanityManager.ASSERT(item != null, "item null");				SanityManager.ASSERT(item.getEntry() == entry, "entry not equals keyed entry");				SanityManager.ASSERT(item.isKept(), "item is not kept in release(Cachable)");			}			removeItem = item.unkeep();			if (removeItem) {								remove(entry.getIdentity());				// we keep the item here to stop another thread trying to evict it				// while we are destroying it.				item.keepForClean();			}			if (cleaner == null) {				// try to shrink the cache on a release				toShrink = shrinkSize( getCurrentSize());			}		}		if (removeItem) {			item.notifyRemover();		}		if (toShrink > 0)			performWork(true /* shrink only */);	}	protected void release(CachedItem item) {		boolean removeItem;		synchronized (this) {			if (SanityManager.DEBUG) {				SanityManager.ASSERT(item.isKept(), "item is not kept in released(CachedItem)");			}			removeItem = item.unkeep();			if (removeItem) {								remove(item.getEntry().getIdentity());				// we keep the item here to stop another thread trying to evict it				// while we are destroying it.				item.keepForClean();			}		}		if (removeItem) {			item.notifyRemover();		}	}	/**		Remove an object from the cache. The item will be placed into the NoIdentity		state through clean() (if required) and clearIdentity(). The removal of the		object will be delayed until it is not kept by anyone.		After this call the caller must throw away the reference to item.		<P>MT - must be MT-safe.  Single thread thru finding and setting the		remove state of the item, the actual removal of the cacheable is		synchronized on the cachedItem itself.		@exception StandardException Standard Cloudscape error policy.	*/	public void remove(Cacheable entry) throws StandardException {		boolean removeNow;		CachedItem item;        long origItemSize = 0;		stat.remove++;		synchronized (this) {						item = (CachedItem) get(entry.getIdentity());			if (SanityManager.DEBUG) {				SanityManager.ASSERT(item != null);				SanityManager.ASSERT(item.getEntry() == entry);				SanityManager.ASSERT(item.isKept());			}            if( useByteCount)                origItemSize = getItemSize( item);			item.setRemoveState();			removeNow = item.unkeep();				if (removeNow) {				remove(entry.getIdentity());				item.keepForClean();			}		}		try {			// if removeNow is false then this thread may sleep			item.remove(removeNow);		} finally {			synchronized (this)			{				// in the case where this thread didn't call keepForClean() the thread				// that woke us would have called keepForClean.				item.unkeep();				item.setValidState(false);                validItemCount--;				item.getEntry().clearIdentity();                if( useByteCount)                    currentByteCount += getItemSize( item) - origItemSize;			}		}	}	/**		Clean all objects in the cache.	*/	public void cleanAll() throws StandardException {		stat.cleanAll++;		cleanCache((Matchable) null);	}	/**		Clean all objects that match a partial key.	*/	public void clean(Matchable partialKey) throws StandardException {		cleanCache(partialKey);	}	/**		Age as many objects as possible out of the cache.  		<BR>MT - thread safe		@see CacheManager#ageOut	*/	public void ageOut() {		stat.ageOut++;		synchronized (this) {			int size = holders.size();			long toShrink = shrinkSize( getCurrentSize());			boolean shrunk = false;			for (int position = 0; position < size; position++) {				CachedItem item = (CachedItem) holders.get(position);				if (item.isKept())					continue;				if (!item.isValid())					continue;				if (item.getEntry().isDirty()) {					continue;				}				long itemSize = removeIdentity(item);				if (toShrink > 0) {					if (SanityManager.DEBUG) {						if (SanityManager.DEBUG_ON(ClockFactory.CacheTrace)) {						SanityManager.DEBUG(ClockFactory.CacheTrace, name + 											" shrinking item " + item + " at position " + position);						}					}										toShrink -= itemSize;					shrunk = true;				}			} // end of for loop			if (shrunk)				trimToSize();		} // out of sync block	} // end of ageOut	/**		MT - synchronization provided by caller		@exception StandardException Standard Cloudscape error policy.	*/	public void shutdown() throws StandardException {		if (cleaner != null) {			cleaner.unsubscribe(myClientNumber);			cleaner = null;		}		synchronized (this) {			active = false;		}		ageOut();		cleanAll();		ageOut();	}	/**		MT - synchronization provided by caller		can use this Daemomn service if needed	*/	public void useDaemonService(DaemonService daemon)	{		// if we were using another cleaner, unsubscribe first		if (cleaner != null)			cleaner.unsubscribe(myClientNumber);		cleaner = daemon;		myClientNumber = cleaner.subscribe(this, true /* onDemandOnly */);	}	/**		Discard all objects that match the partial key.		<BR>MT - thread safe	*/	public boolean discard(Matchable partialKey) {		// we miss something because it was kept		boolean noMisses = true;		synchronized (this) {			int size = holders.size();			long toShrink = shrinkSize( getCurrentSize());			boolean shrunk = false;			for (int position = 0; position < size; position++) {				CachedItem item = (CachedItem) holders.get(position);				if (!item.isValid())					continue;				Object key = item.getEntry().getIdentity();				if (partialKey != null && !partialKey.match(key))					continue;				if (item.isKept())				{					noMisses = false;					continue;				}				long itemSize = removeIdentity(item);				if (toShrink > 0) {					if (SanityManager.DEBUG) {						if (SanityManager.DEBUG_ON(ClockFactory.CacheTrace)) {						SanityManager.DEBUG(ClockFactory.CacheTrace, name + 											" shrinking item " + item + " at position " + position);						}					}					// and we shrunk one item					toShrink -= itemSize;					shrunk = true;				}			}			if (shrunk)				trimToSize();		}		return noMisses;	}	/**		Add a new CachedItem and a holder object to the cache. The holder object		is returned kept.		<P>MT - need to be MT-safe.  The insertion of the key into the hash		table is synchronized on this.	*/	private Cacheable addEntry(CachedItem item, Object key, boolean forCreate, Object createParameter)		throws StandardException {		Cacheable entry = null;        long origEntrySize = 0;        if( useByteCount)            origEntrySize = getItemSize( item);		try		{			if (SanityManager.DEBUG) {			  if (SanityManager.DEBUG_ON(ClockFactory.CacheTrace))			  {				SanityManager.DEBUG(ClockFactory.CacheTrace, name + 									" item " + item + " take on identity " + key);			  }			}						// tell the object it needs to create itself			entry = item.takeOnIdentity(this, holderFactory, key, forCreate, createParameter);		}		finally		{			boolean	notifyWaiters;			synchronized (this) {				Object removed = remove(key);				if (SanityManager.DEBUG) {					SanityManager.ASSERT(removed == item);				}				if (entry != null) {					// put the actual key into the hash table, not the one that was passed in					// for the find or create. This is because the caller may re-use the key					// for another cache operation, which would corrupt our hashtable					put(entry.getIdentity(), item);                    if( useByteCount)                        currentByteCount += ((SizedCacheable) entry).getSize() - origEntrySize;					item.setValidState(true);                    validItemCount++;					notifyWaiters = true;				} else {					item.unkeep();					notifyWaiters = item.isKept();				}			}			// whatever the outcome, we have to notify waiters ...			if (notifyWaiters)				item.settingIdentityComplete();		}		return entry;	}   	protected CachedItem findFreeItem() throws StandardException {		// Need to avoid thrashing the cache when we start out		// so if the cache is smaller than its maximum size		// then that's a good indication we should grow.		long currentSize = getCurrentSize();		if (currentSize >= maximumSize) {			// look at 20%			CachedItem item = rotateClock(0.2f);			if (item != null)				return item;		}		// However, if the cache contains a large number of invalid		// items then we should see if we can avoid growing.		// This avoids simple use of Cloudscape looking like		// a memory leak, as the page cache fills the holders array		// with page objects including the 4k (or 32k) pages.		// size() is the number of valid entries in the hash table		// no need to sync on getting the sizes since if they are		// wrong we will discover it in the loop.		if (validItemCount < holders.size()) {			synchronized (this) {				// 1) find out how many invalid items there are in the				//    cache				// 2) search for a free invalid item				// 3) stop searching when there are no more invalid				//    items to find				int invalidItems = holders.size() - validItemCount;				// Invalid items might occur in the cache when				//   a) a new item is created in growCache(), but it				//      is not in use yet, or				//   b) an item is deleted (usually when a table is				//      dropped)				// It is critical to break out of the loop as soon as				// possible since we are blocking others trying to				// access the page cache. New items are added to the				// end of the page cache, so the search for invalid				// items should start from the end.				for (int i = holders.size() - 1; (invalidItems > 0) && (i >= 0) ; i--) {					CachedItem item = (CachedItem) holders.get(i);					if (item.isKept()) {						if (!item.isValid()) invalidItems--;						continue;					}					// found a free item, just use it					if (!item.isValid()) {						item.keepForCreate();						return item;					}				}			}		}		return growCache();	}	/**		Go through the list of holder objects and find a free one.		<P>MT - must be MT-safe.  The moving of the clockHand and finding of an		eviction candidate is synchronized.  The cleaning of the cachable is		handled by the cacheable itself.	*/	protected CachedItem rotateClock(float percentOfClock) throws StandardException	{		// statistics -- only used in debug		int evictions = 0;		int cleaned = 0;		int resetUsed = 0;		int iskept = 0;        // When we are managing the entry count (useByteCount == false) this method just        // has to find or manufacture an available item (a cache slot). When we are managing        // the total byte count then this method must find both available space and an        // available item.        CachedItem availableItem = null;		boolean kickCleaner = false;

⌨️ 快捷键说明

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