use of org.apache.derby.iapi.services.cache.Cacheable in project derby by apache.
the class DataDictionaryImpl method getPermissions.
private Object getPermissions(PermissionsDescriptor key) throws StandardException {
// RESOLVE get a READ COMMITTED (shared) lock on the permission row
Cacheable entry = getPermissionsCache().find(key);
if (entry == null)
return null;
Object perms = entry.getIdentity();
getPermissionsCache().release(entry);
return perms;
}
use of org.apache.derby.iapi.services.cache.Cacheable in project derby by apache.
the class ConcurrentCache method find.
// Implementation of the CacheManager interface
/**
* Find an object in the cache. If it is not present, add it to the
* cache. The returned object is kept until <code>release()</code> is
* called.
*
* @param key identity of the object to find
* @return the cached object, or <code>null</code> if it cannot be found
*/
public Cacheable find(Object key) throws StandardException {
if (stopped) {
return null;
}
CacheEntry entry = getEntry(key);
Cacheable item;
try {
item = entry.getCacheable();
if (item != null) {
// The object is already cached. Increase the use count and
// return it.
entry.keep(true);
countHit();
return item;
} else {
// The object is not cached. Insert the entry into a free
// slot and retrieve a reusable Cacheable.
item = insertIntoFreeSlot(key, entry);
countMiss();
}
} finally {
entry.unlock();
}
// Set the identity without holding the lock on the entry. If we
// hold the lock, we may run into a deadlock if the user code in
// setIdentity() re-enters the buffer manager.
Cacheable itemWithIdentity = null;
try {
itemWithIdentity = item.setIdentity(key);
} finally {
// Always invoke settingIdentityComplete(), also on error,
// otherwise other threads may wait forever. If setIdentity()
// fails, itemWithIdentity is going to be null.
settingIdentityComplete(key, entry, itemWithIdentity);
}
return itemWithIdentity;
}
use of org.apache.derby.iapi.services.cache.Cacheable in project derby by apache.
the class ConcurrentCache method discard.
/**
* Discard all unused objects that match a partial key. Dirty objects will
* not be cleaned before their removal.
*
* @param partialKey the partial (or exact) key, or <code>null</code> to
* match all keys
* @return <code>true</code> if all matching objects were removed,
* <code>false</code> otherwise
*/
public boolean discard(Matchable partialKey) {
boolean allRemoved = true;
for (CacheEntry entry : cache.values()) {
entry.lock();
try {
Cacheable c = entry.getCacheable();
if (c == null) {
// not in the cache - no need to remove it
continue;
}
if (partialKey != null && !partialKey.match(c.getIdentity())) {
// not a match, don't remove it
continue;
}
if (entry.isKept()) {
// still in use, don't remove it
allRemoved = false;
continue;
}
removeEntry(c.getIdentity());
} finally {
entry.unlock();
}
}
return allRemoved;
}
use of org.apache.derby.iapi.services.cache.Cacheable in project derby by apache.
the class ClockPolicy method rotateClock.
/**
* Rotate the clock in order to find a free space for a new entry. If
* <code>allowEvictions</code> is <code>true</code>, an not recently used
* object might be evicted to make room for the new entry. Otherwise, only
* unused entries are searched for. When evictions are allowed, entries are
* marked as not recently used when the clock hand sweeps over them. The
* search stops when a reusable entry is found, or when more than a certain
* percentage of the entries have been visited. If there are
* free (unused) entries, the search will continue until a reusable entry
* is found, regardless of how many entries that need to be checked.
*
* @param entry the entry to insert
* @param allowEvictions tells whether evictions are allowed (normally
* <code>true</code> if the cache is full and <code>false</code> otherwise)
* @return a holder that we can reuse, or <code>null</code> if we didn't
* find one
*/
private Holder rotateClock(CacheEntry entry, boolean allowEvictions) throws StandardException {
// Calculate how many items we need to check before we give up
// finding an evictable one. If we don't allow evictions, none should
// be checked (however, we may search for unused entries in the loop
// below).
int itemsToCheck = 0;
if (allowEvictions) {
synchronized (clock) {
itemsToCheck = Math.max(MIN_ITEMS_TO_CHECK, (int) (clock.size() * MAX_ROTATION));
}
}
// if we know there are unused entries.
while (itemsToCheck-- > 0 || freeEntries.get() > 0) {
final Holder h = moveHand();
if (h == null) {
// reusable entry.
return null;
}
final CacheEntry e = h.getEntry();
if (e == null) {
if (h.takeIfFree(entry)) {
return h;
}
// getEntry() and takeIfFree(). Just move on to the next entry.
continue;
}
if (!allowEvictions) {
// Evictions are not allowed, so we can't reuse this entry.
continue;
}
// This variable will hold a dirty cacheable that should be cleaned
// after the try/finally block.
final Cacheable dirty;
e.lock();
try {
if (!isEvictable(e, h, true)) {
continue;
}
// The entry is not in use, and has not been used for at least
// one round on the clock. See if it needs to be cleaned.
Cacheable c = e.getCacheable();
if (!c.isDirty()) {
// Not in use and not dirty. Take over the holder.
h.switchEntry(entry);
cacheManager.evictEntry(c.getIdentity());
return h;
}
// Ask the background cleaner to clean the entry.
BackgroundCleaner cleaner = cacheManager.getBackgroundCleaner();
if (cleaner != null && cleaner.scheduleClean(e)) {
// operation to finish.
continue;
}
// There is no background cleaner, or the background cleaner
// has no free capacity. Let's clean the object ourselves.
// First, mark the entry as kept to prevent eviction until
// we have cleaned it, but don't mark it as accessed (recently
// used).
e.keep(false);
dirty = c;
} finally {
e.unlock();
}
// Clean the entry and unkeep it.
cacheManager.cleanAndUnkeepEntry(e, dirty);
// If no one has touched the entry while we were cleaning it, we
// could reuse it at this point. The old buffer manager (Clock)
// would however under high load normally move on to the next
// entry in the clock instead of reusing the one it recently
// cleaned. Some of the performance tests performed as part of
// DERBY-2911 indicated that not reusing the entry that was just
// cleaned made the replacement algorithm more efficient. For now
// we try to stay as close to the old buffer manager as possible
// and don't reuse the entry immediately.
}
return null;
}
use of org.apache.derby.iapi.services.cache.Cacheable in project derby by apache.
the class ClockPolicy method shrinkMe.
/**
* Perform the shrinking of the clock. This method should only be called
* by a single thread at a time.
*/
private void shrinkMe() {
if (SanityManager.DEBUG) {
SanityManager.ASSERT(isShrinking.get(), "Called shrinkMe() without ensuring exclusive access");
}
// Max number of candidates to look at (always at least 1).
int maxLooks = Math.max(1, (int) (maxSize * PART_OF_CLOCK_FOR_SHRINK));
// Since we don't scan the entire cache, start at the clock hand so
// that we don't always scan the first 10% of the cache.
int pos;
synchronized (clock) {
pos = hand;
}
while (maxLooks-- > 0) {
final Holder h;
final int size;
// Fetch the next holder from the clock.
synchronized (clock) {
size = clock.size();
if (pos >= size) {
pos = 0;
}
h = clock.get(pos);
}
// The index of the holder we're looking at. Since no one else than
// us can remove elements from the clock while we're in this
// method, and new elements will be added at the end of the list,
// the index for a holder does not change until we remove it.
final int index = pos;
// Let pos point at the index of the holder we'll look at in the
// next iteration.
pos++;
// No need to shrink if the size isn't greater than maxSize.
if (size <= maxSize) {
break;
}
final CacheEntry e = h.getEntry();
if (e == null) {
// The holder does not hold an entry. Try to remove it.
if (h.evictIfFree()) {
removeHolder(index, h);
// move position back because of the removal so that we
// don't skip one clock element
pos = index;
}
// to the next holder.
continue;
}
e.lock();
try {
if (!isEvictable(e, h, false)) {
continue;
}
final Cacheable c = e.getCacheable();
if (c.isDirty()) {
// Don't evict dirty entries.
continue;
}
// mark as evicted to prevent reuse
h.setEvicted();
// remove from cache manager
cacheManager.evictEntry(c.getIdentity());
// remove from clock
removeHolder(index, h);
// move position back because of the removal so that we don't
// skip one clock element
pos = index;
} finally {
e.unlock();
}
}
}
Aggregations