Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) 1997-2012 Oracle and/or its affiliates. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common Development
* and Distribution License("CDDL") (collectively, the "License"). You
* may not use this file except in compliance with the License. You can
* obtain a copy of the License at
* https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
* or packager/legal/LICENSE.txt. See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each
* file and include the License file at packager/legal/LICENSE.txt.
*
* GPL Classpath Exception:
* Oracle designates this particular file as subject to the "Classpath"
* exception as provided by Oracle in the GPL Version 2 section of the License
* file that accompanied this code.
*
* Modifications:
* If applicable, add the following below the License Header, with the fields
* enclosed by brackets [] replaced by your own identifying information:
* "Portions Copyright [year] [name of copyright owner]"
*
* Contributor(s):
* If you wish your version of this file to be governed by only the CDDL or
* only the GPL Version 2, indicate your decision by adding "[Contributor]
* elects to include this software in this distribution under the [CDDL or GPL
* Version 2] license." If you don't indicate a single choice of license, a
* recipient has the option to distribute your version of this file under
* either the CDDL, the GPL Version 2 or to extend the choice of license to
* its licensees as provided above. However, if you add GPL Version 2 code
* and therefore, elected the GPL Version 2 license, then the option applies
* only if the new code is made subject to such option by the copyright
* holder.
*/
// Portions Copyright [2019] Payara Foundation and/or affiliates
package com.sun.appserv.util.cache;
import com.sun.enterprise.util.CULoggerInfo;
import java.text.MessageFormat;
import java.util.*;
/**
* BaseCache
* Generic in-memory, abstract cache
*/
public class BaseCache implements Cache {
/**
* The resource bundle containing the localized message strings.
*/
static final int MAX_ENTRIES = 1 << 30;
static final float DEFAULT_LOAD_FACTOR = 0.75f;
// maximum number of entries this cache may ever hold
protected int maxEntries;
// the number of cache entries in this cache
protected int entryCount;
private Object entryCountLk = new Object();
/** threshold for the cache; once the threshold is reached
* entries are removed to accomodate newer inserts
*/
protected int threshold = 0;
// the number of cache hits
protected int hitCount;
private Object hitCountLk = new Object();
// the number of cache misses
protected int missCount;
private Object missCountLk = new Object();
// the number of cache item removals
protected int removalCount;
private Object removalCountLk = new Object();
// the number of cache item refreshes
private int refreshCount;
private Object refreshCountLk = new Object();
// the number of times an item was added to cache
private int addCount;
private Object addCountLk = new Object();
// the number of times the cache overflowed
private int overflowCount;
private Object overflowCountLk = new Object();
// table size
protected int maxBuckets;
// cache entries hash table
protected CacheItem[] buckets;
// bucket-wide locks
protected Object[] bucketLocks;
// boolean status and locks for item thread-safe refreshes
protected boolean[] refreshFlags;
protected ArrayList listeners = new ArrayList();
/**
* initialize the cache
* @param maxEntries maximum number of entries expected in the cache
* @param props opaque list of properties for a given cache implementation
* @throws a generic Exception if the initialization failed
*/
@Override
public void init(int maxEntries, Properties props) throws Exception {
init(maxEntries, DEFAULT_LOAD_FACTOR, props);
}
/**
* initialize the cache
* @param maxEntries maximum number of entries expected in the cache
* @param loadFactor the load factor
* @param props opaque list of properties for a given cache implementation
* @throws a generic Exception if the initialization failed
*/
@Override
public void init(int maxEntries, float loadFactor, Properties props) {
if (maxEntries <= 0) {
String msg = CULoggerInfo.getString(CULoggerInfo.illegalMaxEntries);
Integer obj = maxEntries;
Object[] params = { obj };
msg = MessageFormat.format(msg, params);
throw new IllegalArgumentException(msg);
}
if (maxEntries > MAX_ENTRIES)
maxEntries = MAX_ENTRIES;
this.maxEntries = maxEntries;
// find a power of 2 >= maxEntries
maxBuckets = 1;
while (maxBuckets < maxEntries)
maxBuckets <<= 1;
//Cannot have the loadfactor as a negative value
if( loadFactor < 0 )
loadFactor = 0;
/** initialize the threshold; a zero value for maxEntries
* implies no caching.
*/
if (maxEntries != 0) {
threshold = (int)(maxEntries * loadFactor) + 1;
}
// create the cache and the bucket locks
entryCount = 0;
buckets = new CacheItem[maxBuckets];
bucketLocks = new Object[maxBuckets];
refreshFlags = new boolean[maxBuckets];
for (int i=0; iCacheListener implementation
*/
@Override
public void addCacheListener(CacheListener listener) {
listeners.add(listener);
}
/**
* Returns a hash code for non-null Object x.
* @See also HashMap
*/
protected int hash(Object x) {
int h = x.hashCode();
return h - (h << 7); // i.e., -127 * h
}
/**
* Check for equality of non-null reference x and possibly-null y.
*/
protected boolean eq(Object x, Object y) {
return x == y || x.equals(y);
}
/**
* increase the threshold
*/
protected void handleOverflow() {
// just double the threshold; this may degenerate the cache.
threshold = (threshold * 2);
incrementOverflowCount();
}
/**
* this item is just added to the cache
* @param item CacheItem that was created
* @return a overflow item; may be null
* Cache bucket is already synchronized by the caller
*
* Here, if cache is overflowing (i.e. reached threshold); this class
* simply makes the cache unbounded by raising the threshold. Subclasses
* are expected to provide a robust cache replacement algorithm.
*
* Subclasses should enhance this implemntation.
*/
protected CacheItem itemAdded(CacheItem item) {
if (isThresholdReached()) {
handleOverflow();
}
return null;
}
/**
* this item is accessed
* @param item CacheItem accessed
*
* Cache bucket is already synchronized by the caller
*/
protected void itemAccessed(CacheItem item) { }
/**
* item value has been refreshed
* @param item CacheItem that was refreshed
* @param oldSize size of the previous value that was refreshed
* Cache bucket is already synchronized by the caller
*/
protected void itemRefreshed(CacheItem item, int oldSize) { }
/**
* item value has been removed from the cache
* @param item CacheItem that was just removed
*
* Cache bucket is already synchronized by the caller
*/
protected void itemRemoved(CacheItem item) { }
/**
* Cannot find an item with the given key and hashCode
* @param key Object that is not found
* @param hashCode int its hashCode
*
* @returns the Object value associated with the item
* Cache bucket is already synchronized by the caller
*/
protected Object loadValue(Object key, int hashCode) {
return null;
}
/**
* create new item
* @param hashCode for the entry
* @param key Object key
* @param value Object value
* @param size size in bytes of the item
* subclasses may override to provide their own CacheItem extensions
* e.g. one that permits persistence.
*/
protected CacheItem createItem(int hashCode, Object key,
Object value, int size) {
return new CacheItem(hashCode, key, value, size);
}
/**
* has cache reached its threshold
* @return true when the cache reached its threshold
*/
protected boolean isThresholdReached() {
return (entryCount > threshold);
}
/**
* get the index of the item in the cache
* @param hashCode of the entry
* @return the index to be used in the cache
*/
protected final int getIndex(int hashCode) {
return (hashCode & (maxBuckets - 1));
}
/**
* get the index of the item given a key
* @param key of the entry
* @return the index to be used in the cache
*/
@Override
public final int getIndex(Object key) {
return getIndex(hash(key));
}
/**
* get the item stored at the key.
* @param key lookup key
* @returns the item stored at the key; null if not found.
*/
@Override
public Object get(Object key) {
int hashCode = hash(key);
return get(hashCode, key);
}
/**
* get the item stored at the given pre-computed hash code and the key.
* @param key lookup key
* @returns the item stored at the key; null if not found.
*/
public Object get(int hashCode, Object key) {
int index = getIndex(hashCode);
Object value;
CacheItem item = null;
synchronized (bucketLocks[index]) {
item = buckets[index];
for (; item != null; item = item.next) {
if ((hashCode == item.hashCode) && eq(key, item.key)) {
break;
}
}
// update the stats in line
if (item != null) {
value = item.getValue();
itemAccessed(item);
} else {
value = loadValue(key, hashCode);
}
}
if (item != null) {
incrementHitCount();
} else {
incrementMissCount();
}
return value;
}
/**
* check if the cache contains the item at the key
* @param key lookup key
* @returns true if there is an item stored at the key; false if not.
*/
@Override
public boolean contains(Object key) {
return (get(key) != null);
}
/**
* get all the items stored at the key.
* @param key lookup key
* @returns an Iterator over the items with the given key.
*/
@Override
public Iterator getAll(Object key) {
int hashCode = hash(key);
int index = getIndex(hashCode);
ArrayList valueList = new ArrayList(entryCount);
synchronized (bucketLocks[index]) {
CacheItem item = buckets[index];
for (; item != null; item = item.next) {
if ((hashCode == item.hashCode) && eq(key, item.key)) {
incrementHitCount();
valueList.add(item.getValue());
}
}
}
return valueList.iterator();
}
/**
* get an Iterator for the keys stored in the cache
* @returns an Iterator
*/
@Override
public Iterator keys() {
ArrayList keyList = new ArrayList(entryCount);
for (int index=0; index < maxBuckets; index++) {
synchronized (bucketLocks[index]) {
for (CacheItem item = buckets[index]; item != null;
item = item.next) {
keyList.add(item.key);
}
}
}
return keyList.iterator();
}
/**
* get an Enumeration for the keys stored in the cache
* @returns an Enumeration
* XXX: should use Iterator which is based on Collections
*/
@Override
public Enumeration elements() {
List