You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openjpa.apache.org by cu...@apache.org on 2010/07/12 23:39:47 UTC
svn commit: r963498 -
/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/PreparedQueryCacheImpl.java
Author: curtisr7
Date: Mon Jul 12 21:39:47 2010
New Revision: 963498
URL: http://svn.apache.org/viewvc?rev=963498&view=rev
Log:
OPENJPA-1723: Improve the scalability of PreparedQueryCacheImpl.
Modified:
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/PreparedQueryCacheImpl.java
Modified: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/PreparedQueryCacheImpl.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/PreparedQueryCacheImpl.java?rev=963498&r1=963497&r2=963498&view=diff
==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/PreparedQueryCacheImpl.java (original)
+++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/PreparedQueryCacheImpl.java Mon Jul 12 21:39:47 2010
@@ -21,11 +21,11 @@ package org.apache.openjpa.jdbc.kernel;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
-import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
-import java.util.concurrent.locks.ReentrantLock;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
import org.apache.commons.lang.StringUtils;
import org.apache.openjpa.conf.OpenJPAConfiguration;
@@ -59,7 +59,9 @@ public class PreparedQueryCacheImpl impl
private final List<Exclusion> _exclusionPatterns;
private QueryStatistics<String> _stats;
private boolean _statsEnabled;
- private ReentrantLock _lock = new ReentrantLock();
+
+ private Lock _writeLock;
+ private Lock _readLock;
private Log _log;
private static Localizer _loc = Localizer.forPackage(PreparedQueryCacheImpl.class);
@@ -67,6 +69,10 @@ public class PreparedQueryCacheImpl impl
_delegate = new CacheMap();
_uncachables = new CacheMap();
_exclusionPatterns = new ArrayList<Exclusion>();
+
+ ReentrantReadWriteLock _rwl = new ReentrantReadWriteLock();
+ _writeLock = _rwl.writeLock();
+ _readLock = _rwl.readLock();
}
public Boolean register(String id, Query query, FetchConfiguration hints) {
@@ -88,14 +94,14 @@ public class PreparedQueryCacheImpl impl
}
public Map<String,String> getMapView() {
- lock();
+ lock(false);
try {
Map<String, String> view = new TreeMap<String, String>();
for (Map.Entry<String, PreparedQuery> entry : _delegate.entrySet())
view.put(entry.getKey(), entry.getValue().getTargetQuery());
return view;
} finally {
- unlock();
+ unlock(false);
}
}
@@ -106,7 +112,7 @@ public class PreparedQueryCacheImpl impl
* the matched exclusion pattern.
*/
public boolean cache(PreparedQuery q) {
- lock();
+ lock(false);
try {
String id = q.getIdentifier();
if (Boolean.FALSE.equals(isCachable(id))) {
@@ -124,7 +130,7 @@ public class PreparedQueryCacheImpl impl
_log.trace(_loc.get("prepared-query-cached", id));
return true;
} finally {
- unlock();
+ unlock(false);
}
}
@@ -142,27 +148,27 @@ public class PreparedQueryCacheImpl impl
}
public boolean invalidate(String id) {
- lock();
+ lock(false);
try {
if (_log != null && _log.isTraceEnabled())
_log.trace(_loc.get("prepared-query-invalidate", id));
return _delegate.remove(id) != null;
} finally {
- unlock();
+ unlock(false);
}
}
public PreparedQuery get(String id) {
- lock();
+ lock(true);
try {
return _delegate.get(id);
} finally {
- unlock();
+ unlock(true);
}
}
public Boolean isCachable(String id) {
- lock();
+ lock(true);
try {
if (_uncachables.containsKey(id))
return Boolean.FALSE;
@@ -170,12 +176,12 @@ public class PreparedQueryCacheImpl impl
return Boolean.TRUE;
return null;
} finally {
- unlock();
+ unlock(true);
}
}
public PreparedQuery markUncachable(String id, Exclusion exclusion) {
- lock();
+ lock(false);
try {
if (_uncachables.put(id, exclusion) == null) {
if (_log != null && _log.isTraceEnabled())
@@ -183,7 +189,7 @@ public class PreparedQueryCacheImpl impl
}
return _delegate.remove(id);
} finally {
- unlock();
+ unlock(false);
}
}
@@ -192,7 +198,7 @@ public class PreparedQueryCacheImpl impl
}
public void setExcludes(String excludes) {
- lock();
+ lock(false);
try {
if (StringUtils.isEmpty(excludes))
return;
@@ -200,7 +206,7 @@ public class PreparedQueryCacheImpl impl
for (String pattern : patterns)
addExclusionPattern(pattern);
} finally {
- unlock();
+ unlock(false);
}
}
@@ -213,7 +219,7 @@ public class PreparedQueryCacheImpl impl
* matches the given pattern will be marked invalidated as a side-effect.
*/
public void addExclusionPattern(String pattern) {
- lock();
+ lock(false);
try {
String reason = _loc.get("prepared-query-excluded-by-user", pattern).getMessage();
Exclusion exclusion = new WeakExclusion(pattern, reason);
@@ -224,7 +230,7 @@ public class PreparedQueryCacheImpl impl
markUncachable(invalidKey, invalid);
}
} finally {
- unlock();
+ unlock(false);
}
}
@@ -234,7 +240,7 @@ public class PreparedQueryCacheImpl impl
* uncachables as a side-effect.
*/
public void removeExclusionPattern(String pattern) {
- lock();
+ lock(false);
try {
Exclusion exclusion = new WeakExclusion(pattern, null);
_exclusionPatterns.remove(exclusion);
@@ -245,7 +251,7 @@ public class PreparedQueryCacheImpl impl
_log.trace(_loc.get("prepared-query-remove-pattern", pattern, rebornKey));
}
} finally {
- unlock();
+ unlock(false);
}
}
@@ -290,14 +296,31 @@ public class PreparedQueryCacheImpl impl
return result;
}
- void lock() {
- if (_lock != null)
- _lock.lock();
+ /**
+ * Note: Care needs to be taken so that a read lock is <b>never</b> held while requesting a write lock. This will
+ * result in a deadlock.
+ *
+ * @param readOnly
+ * - If true, a read lock will be acquired. Else a write lock will be acquired.
+ */
+ protected void lock(boolean readOnly) {
+ if (readOnly == true) {
+ _readLock.lock();
+ } else {
+ _writeLock.lock();
+ }
}
- void unlock() {
- if (_lock != null && _lock.isLocked())
- _lock.unlock();
+ /**
+ * @param readOnly
+ * - If true, the read lock will be released. Else a write lock will be released.
+ */
+ protected void unlock(boolean readOnly) {
+ if (readOnly == true) {
+ _readLock.unlock();
+ } else {
+ _writeLock.unlock();
+ }
}
boolean matches(String pattern, String target) {