001: /*
002: * (c) Copyright 2003, 2004, 2005, 2006, 2007, 2008 Hewlett-Packard Development Company, LP
003: *
004: * All rights reserved.
005: *
006: * See end of file.
007: */
008:
009: package com.hp.hpl.jena.util.cache;
010:
011: import java.util.Collection;
012: import java.util.HashMap;
013: import java.util.Iterator;
014:
015: import org.apache.commons.logging.Log;
016: import org.apache.commons.logging.LogFactory;
017:
018: /**
019: *
020: * @author bwm
021: */
022: public class RandCache implements Cache, CacheControl {
023: int size;
024: int threshhold;
025: boolean enabled = true;
026: // so we can identify caches
027: String name; // e.g. when logging
028:
029: HashMap map;
030: Collection collection;
031:
032: protected static Log logger = LogFactory.getLog(RandCache.class);
033:
034: long gets = 0;
035: long puts = 0;
036: long hits = 0;
037:
038: /** Creates new RandCache */
039: RandCache(String name, int size) {
040: this .size = size;
041: try {
042: map = new HashMap(size * 100 / 75); // based on .75 loadfactor
043: } catch (IllegalArgumentException e) {
044: if ("Illegal load factor: NaN".equals(e.getMessage())) {
045: // This strange construction needs explanation.
046: // When we implemented XSDbase64Binary/XSDhexBinary support involving use
047: // of byte[] we started seeing this error here. Since the default loadfactor
048: // is a static final constant in HashMap this should never be possible.
049: // It only happens under JDK 1.4.1 not under 1.3.1 nor 1.4.2.
050: // The retry, however does seem to work and hence gives us a work around
051: // which is completely mysterious but at least enables the unit tests to pass.
052: // - der 4/5/04
053: logger
054: .warn("Detected a NaN anomaly believed to be due to use of JDK 1.4.1");
055: map = new HashMap(size * 100 / 75, 0.75f);
056: } else {
057: throw e;
058: }
059: }
060: threshhold = size;
061: if (threshhold < 2) {
062: throw new Error("Cache size too small: " + size);
063: }
064: collection = map.values();
065: }
066:
067: public synchronized Object get(Object key) {
068: if (enabled) {
069: if (gets == Long.MAX_VALUE) {
070: forgetStats();
071: }
072: gets++;
073: Object result = map.get(key);
074: if (result != null) {
075: hits++;
076: }
077: return result;
078: } else {
079: return null;
080: }
081: }
082:
083: public synchronized void put(Object key, Object value) {
084:
085: // don't allow null values
086: if (value == null) {
087: throw new NullPointerException();
088: }
089:
090: if (enabled) {
091: if (puts == Long.MAX_VALUE) {
092: forgetStats();
093: }
094: puts++;
095: if (map.size() >= threshhold) {
096: makeSpace();
097: }
098: map.put(key, value);
099: }
100: }
101:
102: protected void makeSpace() {
103: Iterator iter = collection.iterator();
104:
105: // we are going to remove every 3rd member of the cache
106: int size = map.size();
107: int i = 3;
108: while (i < size) {
109: iter.next();
110: iter.remove();
111: iter.next();
112: iter.next();
113: i = i + 3;
114: }
115: }
116:
117: public synchronized boolean getEnabled() {
118: return enabled;
119: }
120:
121: public synchronized boolean setEnabled(boolean enabled) {
122: boolean result = enabled;
123: this .enabled = enabled;
124: return result;
125: }
126:
127: public synchronized void clear() {
128: map.clear();
129: }
130:
131: public synchronized long getHits() {
132: return hits;
133: }
134:
135: public synchronized long getGets() {
136: return gets;
137: }
138:
139: public synchronized long getPuts() {
140: return puts;
141: }
142:
143: protected void forgetStats() {
144: gets = gets / 2;
145: puts = puts / 2;
146: hits = hits / 2;
147: }
148:
149: }
150: /*
151: * (c) Copyright 2003, 2004, 2005, 2006, 2007, 2008 Hewlett-Packard Development Company, LP
152: *
153: * All rights reserved.
154: *
155: *
156: * Redistribution and use in source and binary forms, with or without
157: * modification, are permitted provided that the following conditions
158: * are met:
159: * 1. Redistributions of source code must retain the above copyright
160: * notice, this list of conditions and the following disclaimer.
161: * 2. Redistributions in binary form must reproduce the above copyright
162: * notice, this list of conditions and the following disclaimer in the
163: * documentation and/or other materials provided with the distribution.
164: * 3. The name of the author may not be used to endorse or promote products
165: * derived from this software without specific prior written permission.
166:
167: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
168: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
169: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
170: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
171: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
172: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
173: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
174: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
175: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
176: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
177: *
178: * $Id: RandCache.java,v 1.11 2008/01/02 12:10:16 andy_seaborne Exp $
179: */
|