| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| package org.apache.openjpa.datacache; |
| |
| import java.util.Collection; |
| |
| import org.apache.openjpa.event.RemoteCommitListener; |
| import org.apache.openjpa.util.CacheMap; |
| |
| /** |
| * A {@link QueryCache} implementation that is optimized for concurrent |
| * access. When the cache fill up, values to remove from the cache are chosen |
| * randomly. Due to race conditions, it is possible that a get call might not |
| * retur a cached instance if that instance is being transferred between |
| * internal datastructures. |
| * |
| * @since 0.4.1 |
| */ |
| public class ConcurrentQueryCache |
| extends AbstractQueryCache |
| implements RemoteCommitListener { |
| |
| |
| private static final long serialVersionUID = 1L; |
| private CacheMap _cache; |
| protected boolean _lru = false; |
| private int _cacheSize = Integer.MIN_VALUE; |
| private int _softRefs = Integer.MIN_VALUE; |
| |
| /** |
| * Returns the underlying {@link CacheMap} that this cache is using. |
| * This is not an unmodifiable view on the map, so care should be taken |
| * with this reference. Implementations should probably not modify the |
| * contents of the cache, but should only use this reference |
| * to obtain cache metrics. Additionally, this map may contain |
| * expired data. Removal of timed-out data is done in a lazy |
| * fashion, so the actual size of the map may be greater than the |
| * number of non-expired query results in cache. |
| */ |
| public CacheMap getCacheMap() { |
| return _cache; |
| } |
| |
| /** |
| * Returns the maximum number of unpinned objects to keep hard |
| * references to. |
| */ |
| public int getCacheSize() { |
| return _cache.getCacheSize(); |
| } |
| |
| /** |
| * Sets the maximum number of unpinned objects to keep hard |
| * references to. If the map contains more unpinned objects than |
| * <code>size</code>, then this method will result in the cache |
| * flushing old values. |
| */ |
| public void setCacheSize(int size) { |
| _cacheSize = size; |
| } |
| |
| /** |
| * Returns the maximum number of unpinned objects to keep soft |
| * references to. Defaults to <code>-1</code>. |
| */ |
| public int getSoftReferenceSize() { |
| return _cache.getSoftReferenceSize(); |
| } |
| |
| /** |
| * Sets the maximum number of unpinned objects to keep soft |
| * references to. If the map contains more soft references than |
| * <code>size</code>, then this method will result in the cache |
| * flushing values. |
| */ |
| public void setSoftReferenceSize(int size) { |
| _softRefs = size; |
| } |
| |
| @Override |
| public void initialize(DataCacheManager mgr) { |
| super.initialize(mgr); |
| conf.getRemoteCommitEventManager().addInternalListener(this); |
| _cache = newCacheMap(); |
| if (_cacheSize != Integer.MIN_VALUE) { |
| _cache.setCacheSize(_cacheSize); |
| } |
| if (_softRefs != Integer.MIN_VALUE) { |
| _cache.setSoftReferenceSize(_softRefs); |
| } |
| } |
| |
| @Override |
| public void writeLock() { |
| // delegate actually does nothing, but in case that changes... |
| _cache.writeLock(); |
| } |
| |
| @Override |
| public void writeUnlock() { |
| // delegate actually does nothing, but in case that changes... |
| _cache.writeUnlock(); |
| } |
| |
| /** |
| * Return the map to use as an internal cache. |
| */ |
| protected CacheMap newCacheMap() { |
| CacheMap res = new CacheMap(_lru); |
| |
| return res; |
| } |
| |
| @Override |
| protected QueryResult getInternal(QueryKey qk) { |
| return (QueryResult) _cache.get(qk); |
| } |
| |
| @Override |
| protected QueryResult putInternal(QueryKey qk, QueryResult result) { |
| return (QueryResult) _cache.put(qk, result); |
| } |
| |
| @Override |
| protected QueryResult removeInternal(QueryKey qk) { |
| return (QueryResult) _cache.remove(qk); |
| } |
| |
| @Override |
| protected void clearInternal() { |
| _cache.clear(); |
| } |
| |
| @Override |
| protected boolean pinInternal(QueryKey qk) { |
| return _cache.pin(qk); |
| } |
| |
| @Override |
| protected boolean unpinInternal(QueryKey qk) { |
| return _cache.unpin(qk); |
| } |
| |
| @Override |
| protected Collection keySet() { |
| return _cache.keySet (); |
| } |
| |
| /** |
| * Returns the eviction policy of the query cache |
| */ |
| @Override |
| public EvictPolicy getEvictPolicy() { |
| return super.evictPolicy; |
| } |
| |
| public void setLru(boolean l) { |
| _lru = l; |
| } |
| |
| public boolean getLru() { |
| return _lru; |
| } |
| } |