001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one
003: * or more contributor license agreements. See the NOTICE file
004: * distributed with this work for additional information
005: * regarding copyright ownership. The ASF licenses this file
006: * to you under the Apache License, Version 2.0 (the
007: * "License"); you may not use this file except in compliance
008: * with the License. You may obtain a copy of the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing,
013: * software distributed under the License is distributed on an
014: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015: * KIND, either express or implied. See the License for the
016: * specific language governing permissions and limitations
017: * under the License.
018: */
019: package org.apache.openjpa.datacache;
020:
021: import java.util.Collection;
022:
023: import org.apache.openjpa.event.RemoteCommitListener;
024: import org.apache.openjpa.util.CacheMap;
025:
026: /**
027: * A {@link QueryCache} implementation that is optimized for concurrent
028: * access. When the cache fill up, values to remove from the cache are chosen
029: * randomly. Due to race conditions, it is possible that a get call might not
030: * retur a cached instance if that instance is being transferred between
031: * internal datastructures.
032: *
033: * @since 0.4.1
034: */
035: public class ConcurrentQueryCache extends AbstractQueryCache implements
036: RemoteCommitListener {
037:
038: private CacheMap _cache = newCacheMap();
039:
040: /**
041: * Returns the underlying {@link CacheMap} that this cache is using.
042: * This is not an unmodifiable view on the map, so care should be taken
043: * with this reference. Implementations should probably not modify the
044: * contents of the cache, but should only use this reference
045: * to obtain cache metrics. Additionally, this map may contain
046: * expired data. Removal of timed-out data is done in a lazy
047: * fashion, so the actual size of the map may be greater than the
048: * number of non-expired query results in cache.
049: */
050: public CacheMap getCacheMap() {
051: return _cache;
052: }
053:
054: /**
055: * Returns the maximum number of unpinned objects to keep hard
056: * references to.
057: */
058: public int getCacheSize() {
059: return _cache.getCacheSize();
060: }
061:
062: /**
063: * Sets the maximum number of unpinned objects to keep hard
064: * references to. If the map contains more unpinned objects than
065: * <code>size</code>, then this method will result in the cache
066: * flushing old values.
067: */
068: public void setCacheSize(int size) {
069: _cache.setCacheSize(size);
070: }
071:
072: /**
073: * Returns the maximum number of unpinned objects to keep soft
074: * references to. Defaults to <code>-1</code>.
075: */
076: public int getSoftReferenceSize() {
077: return _cache.getSoftReferenceSize();
078: }
079:
080: /**
081: * Sets the maximum number of unpinned objects to keep soft
082: * references to. If the map contains more soft references than
083: * <code>size</code>, then this method will result in the cache
084: * flushing values.
085: */
086: public void setSoftReferenceSize(int size) {
087: _cache.setSoftReferenceSize(size);
088: }
089:
090: public void initialize(DataCacheManager mgr) {
091: super .initialize(mgr);
092: conf.getRemoteCommitEventManager().addInternalListener(this );
093: }
094:
095: public void writeLock() {
096: // delegate actually does nothing, but in case that changes...
097: _cache.writeLock();
098: }
099:
100: public void writeUnlock() {
101: // delegate actually does nothing, but in case that changes...
102: _cache.writeUnlock();
103: }
104:
105: /**
106: * Return the map to use as an internal cache.
107: */
108: protected CacheMap newCacheMap() {
109: return new CacheMap();
110: }
111:
112: protected QueryResult getInternal(QueryKey qk) {
113: return (QueryResult) _cache.get(qk);
114: }
115:
116: protected QueryResult putInternal(QueryKey qk, QueryResult result) {
117: return (QueryResult) _cache.put(qk, result);
118: }
119:
120: protected QueryResult removeInternal(QueryKey qk) {
121: return (QueryResult) _cache.remove(qk);
122: }
123:
124: protected void clearInternal() {
125: _cache.clear();
126: }
127:
128: protected boolean pinInternal(QueryKey qk) {
129: return _cache.pin(qk);
130: }
131:
132: protected boolean unpinInternal(QueryKey qk) {
133: return _cache.unpin(qk);
134: }
135:
136: protected Collection keySet() {
137: return _cache.keySet();
138: }
139: }
|