/******************************************************************************* | |
* Copyright (c) 1998, 2013 Oracle and/or its affiliates. All rights reserved. | |
* This program and the accompanying materials are made available under the | |
* terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0 | |
* which accompanies this distribution. | |
* The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html | |
* and the Eclipse Distribution License is available at | |
* http://www.eclipse.org/org/documents/edl-v10.php. | |
* | |
* Contributors: | |
* Oracle - initial API and implementation from Oracle TopLink | |
******************************************************************************/ | |
package org.eclipse.persistence.internal.helper; | |
import java.io.Serializable; | |
import java.util.*; | |
import java.util.concurrent.*; | |
/** | |
* Provide a concurrent fixed size caching mechanism. | |
* This is used for caching EJBQL parsed queries, Update calls, | |
* and other places a fixed size cache is needed. | |
* The default fixed size is 100. | |
*/ | |
public class ConcurrentFixedCache implements Serializable { | |
protected int maxSize; | |
protected Map cache; | |
/** | |
* Create a new concurrent cache, with a fixed size of 100. | |
*/ | |
public ConcurrentFixedCache() { | |
this(100); | |
} | |
/** | |
* Create a new concurrent cache, with the max size. | |
*/ | |
public ConcurrentFixedCache(int maxSize) { | |
// PERF: Use a concurrent map to allow concurrent gets. | |
this.cache = new ConcurrentHashMap(maxSize); | |
this.maxSize = maxSize; | |
} | |
/** | |
* Return the fixed size of the parse cache. | |
*/ | |
public int getMaxSize() { | |
return maxSize; | |
} | |
/** | |
* Set the fixed size of the parse cache. | |
* When the size is exceeded, subsequent EJBQL will not be cached. | |
* The default size is 100; | |
*/ | |
public void setMaxSize(int maxSize) { | |
this.maxSize = maxSize; | |
} | |
/** | |
* Return the pre-parsed query that represents the EJBQL string. | |
* If the EJBQL has not been cached, null is returned. | |
*/ | |
public Object get(Object key) { | |
return this.cache.get(key); | |
} | |
public void clear(){ | |
this.cache.clear(); | |
} | |
/** | |
* Add the value to the cache. | |
* Remove the | |
*/ | |
public void put(Object key, Object value) { | |
if (this.maxSize == 0) { | |
return; | |
} | |
this.cache.put(key, value); | |
// Currently just removes the first one encountered, not LRU, | |
// this is not ideal, but the most concurrent and quickest way to ensure fixed size. | |
if (this.cache.size() > this.maxSize) { | |
Iterator iterator = this.cache.keySet().iterator(); | |
try { | |
while ((this.cache.size() > this.maxSize) && iterator.hasNext()) { | |
Object next = iterator.next(); | |
// Do not remove what was just put in. | |
if (next != key) { | |
this.cache.remove(next); | |
} | |
} | |
} catch (Exception alreadyGone) { | |
// Ignore. | |
} | |
} | |
} | |
/** | |
* Remove from cache. | |
*/ | |
public void remove(Object key) { | |
this.cache.remove(key); | |
} | |
/** | |
* Return the cache. | |
*/ | |
public Map getCache() { | |
return cache; | |
} | |
} |