[jboss-cvs] JBossAS SVN: r112345 - in projects/jboss-jca/branches/Branch_1_0/adapters/src/main/java/org/jboss/jca/adapters/jdbc: util and 1 other directory.
jboss-cvs-commits at lists.jboss.org
jboss-cvs-commits at lists.jboss.org
Thu Oct 13 10:44:16 EDT 2011
Author: jesper.pedersen
Date: 2011-10-13 10:44:16 -0400 (Thu, 13 Oct 2011)
New Revision: 112345
Added:
projects/jboss-jca/branches/Branch_1_0/adapters/src/main/java/org/jboss/jca/adapters/jdbc/SecurityActions.java
Modified:
projects/jboss-jca/branches/Branch_1_0/adapters/src/main/java/org/jboss/jca/adapters/jdbc/PreparedStatementCache.java
projects/jboss-jca/branches/Branch_1_0/adapters/src/main/java/org/jboss/jca/adapters/jdbc/util/BoundedConcurrentHashMap.java
Log:
[JBJCA-676] PreparedStatement cache failure
Modified: projects/jboss-jca/branches/Branch_1_0/adapters/src/main/java/org/jboss/jca/adapters/jdbc/PreparedStatementCache.java
===================================================================
--- projects/jboss-jca/branches/Branch_1_0/adapters/src/main/java/org/jboss/jca/adapters/jdbc/PreparedStatementCache.java 2011-10-13 14:32:32 UTC (rev 112344)
+++ projects/jboss-jca/branches/Branch_1_0/adapters/src/main/java/org/jboss/jca/adapters/jdbc/PreparedStatementCache.java 2011-10-13 14:44:16 UTC (rev 112345)
@@ -41,13 +41,40 @@
@SuppressWarnings("unchecked")
public class PreparedStatementCache
{
+ private static BoundedConcurrentHashMap.Eviction evictionPolicy;
+
private final Logger log = Logger.getLogger(getClass());
private BoundedConcurrentHashMap<Key, CachedPreparedStatement> cache;
private JdbcStatisticsPlugin statistics;
+ static
+ {
+ String cache = SecurityActions.getSystemProperty("ironjacamar.jdbc.cache");
+ if (cache != null)
+ {
+ cache = cache.trim();
+
+ if ("LRU".equals(cache))
+ {
+ evictionPolicy = BoundedConcurrentHashMap.Eviction.LRU;
+ }
+ else if ("LRU_OLD".equals(cache))
+ {
+ evictionPolicy = BoundedConcurrentHashMap.Eviction.LRU_OLD;
+ }
+ else if ("LIRS".equals(cache))
+ {
+ evictionPolicy = BoundedConcurrentHashMap.Eviction.LIRS;
+ }
+ }
+
+ if (evictionPolicy == null)
+ evictionPolicy = BoundedConcurrentHashMap.Eviction.LRU_OLD;
+ }
+
/**
- * Ket class
+ * Key class
*/
public static class Key
{
@@ -183,7 +210,7 @@
this.cache =
new BoundedConcurrentHashMap<Key, CachedPreparedStatement>(max, 16,
- BoundedConcurrentHashMap.Eviction.LIRS,
+ evictionPolicy,
evictionListener);
this.statistics = stats;
}
@@ -263,6 +290,13 @@
}
}
}
+
+ /**
+ * {@inheritDoc}
+ */
+ public void onEntryChosenForEviction(Object internalCacheEntry)
+ {
+ }
}
/**
Added: projects/jboss-jca/branches/Branch_1_0/adapters/src/main/java/org/jboss/jca/adapters/jdbc/SecurityActions.java
===================================================================
--- projects/jboss-jca/branches/Branch_1_0/adapters/src/main/java/org/jboss/jca/adapters/jdbc/SecurityActions.java (rev 0)
+++ projects/jboss-jca/branches/Branch_1_0/adapters/src/main/java/org/jboss/jca/adapters/jdbc/SecurityActions.java 2011-10-13 14:44:16 UTC (rev 112345)
@@ -0,0 +1,50 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2010, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.jca.adapters.jdbc;
+
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+/**
+ * Privileged Blocks
+ *
+ * @author <a href="mailto:jesper.pedersen at jboss.org">Jesper Pedersen</a>
+ */
+class SecurityActions
+{
+ /**
+ * Get a system property
+ * @param name The property name
+ * @return The property value
+ */
+ static String getSystemProperty(final String name)
+ {
+ return AccessController.doPrivileged(new PrivilegedAction<String>()
+ {
+ public String run()
+ {
+ return System.getProperty(name);
+ }
+ });
+ }
+}
Modified: projects/jboss-jca/branches/Branch_1_0/adapters/src/main/java/org/jboss/jca/adapters/jdbc/util/BoundedConcurrentHashMap.java
===================================================================
--- projects/jboss-jca/branches/Branch_1_0/adapters/src/main/java/org/jboss/jca/adapters/jdbc/util/BoundedConcurrentHashMap.java 2011-10-13 14:32:32 UTC (rev 112344)
+++ projects/jboss-jca/branches/Branch_1_0/adapters/src/main/java/org/jboss/jca/adapters/jdbc/util/BoundedConcurrentHashMap.java 2011-10-13 14:44:16 UTC (rev 112345)
@@ -103,6 +103,8 @@
* Modified for https://jira.jboss.org/jira/browse/ISPN-299
* Includes ideas described in http://portal.acm.org/citation.cfm?id=1547428
*
+ * Latest: https://github.com/infinispan/infinispan/commit/054e321d4ab1d2f33d2d920242bdac3d73745eec
+ *
* @since 1.5
* @author Doug Lea
* @param <K> the type of keys maintained by this map
@@ -359,6 +361,15 @@
return new NullEvictionPolicy<K, V>();
}
},
+ /** LRU_OLD */
+ LRU_OLD
+ {
+ @Override
+ public <K, V> EvictionPolicy<K, V> make(Segment<K, V> s, int capacity, float lf)
+ {
+ return new LRUOld<K, V>(s, capacity, lf, capacity * 10, lf);
+ }
+ },
/** LRU */
LRU
{
@@ -398,12 +409,18 @@
* @param evicted The entry
*/
void onEntryEviction(Map<K, V> evicted);
+
+ /**
+ * OnEntryChosenForEviction
+ * @param internalCacheEntry The cache entry
+ */
+ void onEntryChosenForEviction(V internalCacheEntry);
}
/**
* Null eviction listener
*/
- static class NullEvictionListener<K, V> implements EvictionListener<K, V>
+ static final class NullEvictionListener<K, V> implements EvictionListener<K, V>
{
/**
* {@inheritDoc}
@@ -413,6 +430,15 @@
{
// Do nothing.
}
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void onEntryChosenForEviction(V internalCacheEntry)
+ {
+ // Do nothing.
+ }
}
/**
@@ -562,7 +588,7 @@
/**
* LRU
*/
- static final class LRU<K, V> implements EvictionPolicy<K, V>
+ static final class LRUOld<K, V> implements EvictionPolicy<K, V>
{
private final ConcurrentLinkedQueue<HashEntry<K, V>> accessQueue;
private final Segment<K, V> segment;
@@ -579,10 +605,10 @@
* @param maxBatchSize The max batch size
* @param batchThresholdFactor The batch threshold factor
*/
- public LRU(Segment<K, V> s, int capacity, float lf, int maxBatchSize, float batchThresholdFactor)
+ public LRUOld(Segment<K, V> s, int capacity, float lf, int maxBatchSize, float batchThresholdFactor)
{
this.segment = s;
- this.trimDownSize = (int) (capacity * lf);
+ this.trimDownSize = capacity;
this.maxBatchQueueSize = maxBatchSize > MAX_BATCH_SIZE ? MAX_BATCH_SIZE : maxBatchSize;
this.batchThresholdFactor = batchThresholdFactor;
this.accessQueue = new ConcurrentLinkedQueue<HashEntry<K, V>>();
@@ -612,6 +638,7 @@
while (isOverflow())
{
HashEntry<K, V> first = lruQueue.getLast();
+ segment.evictionListener.onEntryChosenForEviction(first.value);
segment.remove(first.key, first.hash, null);
evicted.add(first);
}
@@ -693,8 +720,158 @@
@Override
public Eviction strategy()
{
+ return Eviction.LRU_OLD;
+ }
+ }
+
+ /**
+ * LRU
+ */
+ static final class LRU<K, V> extends LinkedHashMap<HashEntry<K, V>, V> implements EvictionPolicy<K, V>
+ {
+ /** The serialVersionUID */
+ private static final long serialVersionUID = -7645068174197717838L;
+ private final ConcurrentLinkedQueue<HashEntry<K, V>> accessQueue;
+ private final Segment<K, V> segment;
+ private final int maxBatchQueueSize;
+ private final int trimDownSize;
+ private final float batchThresholdFactor;
+ private final Set<HashEntry<K, V>> evicted;
+
+ /**
+ * LRU
+ * @param s The segment
+ * @param capacity The capacity
+ * @param lf The load factor
+ * @param maxBatchSize The max batch size
+ * @param batchThresholdFactor The batch threshold factor
+ */
+ public LRU(Segment<K, V> s, int capacity, float lf, int maxBatchSize, float batchThresholdFactor)
+ {
+ super(capacity, lf, true);
+ this.segment = s;
+ this.trimDownSize = capacity;
+ this.maxBatchQueueSize = maxBatchSize > MAX_BATCH_SIZE ? MAX_BATCH_SIZE : maxBatchSize;
+ this.batchThresholdFactor = batchThresholdFactor;
+ this.accessQueue = new ConcurrentLinkedQueue<HashEntry<K, V>>();
+ this.evicted = new HashSet<HashEntry<K, V>>();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Set<HashEntry<K, V>> execute()
+ {
+ Set<HashEntry<K, V>> evictedCopy = new HashSet<HashEntry<K, V>>();
+ for (HashEntry<K, V> e : accessQueue)
+ {
+ put(e, e.value);
+ }
+ evictedCopy.addAll(evicted);
+ accessQueue.clear();
+ evicted.clear();
+ return evictedCopy;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Set<HashEntry<K, V>> onEntryMiss(HashEntry<K, V> e)
+ {
+ put(e, e.value);
+ if (!evicted.isEmpty())
+ {
+ Set<HashEntry<K, V>> evictedCopy = new HashSet<HashEntry<K, V>>();
+ evictedCopy.addAll(evicted);
+ evicted.clear();
+ return evictedCopy;
+ }
+ else
+ {
+ return Collections.emptySet();
+ }
+ }
+
+ /*
+ * Invoked without holding a lock on Segment
+ */
+ @Override
+ public boolean onEntryHit(HashEntry<K, V> e)
+ {
+ accessQueue.add(e);
+ return accessQueue.size() >= maxBatchQueueSize * batchThresholdFactor;
+ }
+
+ /*
+ * Invoked without holding a lock on Segment
+ */
+ @Override
+ public boolean thresholdExpired()
+ {
+ return accessQueue.size() >= maxBatchQueueSize;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void onEntryRemove(HashEntry<K, V> e)
+ {
+ remove(e);
+
+ // we could have multiple instances of e in accessQueue; remove them all
+ while (accessQueue.remove(e))
+ {
+ continue;
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void clear()
+ {
+ super.clear();
+ accessQueue.clear();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Eviction strategy()
+ {
return Eviction.LRU;
}
+
+ /**
+ * Is above threshold
+ * @return True if above; false otherwise
+ */
+ protected boolean isAboveThreshold()
+ {
+ return size() > trimDownSize;
+ }
+
+ /**
+ * Remove eldest entry
+ * @param eldest The eldest entry
+ * @return True if removed; false otherwise
+ */
+ protected boolean removeEldestEntry(Map.Entry<HashEntry<K, V>, V> eldest)
+ {
+ boolean aboveThreshold = isAboveThreshold();
+ if (aboveThreshold)
+ {
+ HashEntry<K, V> evictedEntry = eldest.getKey();
+ segment.evictionListener.onEntryChosenForEviction(evictedEntry.value);
+ segment.remove(evictedEntry.key, evictedEntry.hash, null);
+ evicted.add(evictedEntry);
+ }
+ return aboveThreshold;
+ }
}
/**
@@ -788,6 +965,7 @@
if (inStack)
{
queue.remove(e);
+ currentLIRSize++;
e.transitionToLIRResident();
switchBottomostLIRtoHIRAndPrune(evicted);
}
@@ -872,6 +1050,7 @@
{
for (HashEntry<K, V> e : evicted)
{
+ segment.evictionListener.onEntryChosenForEviction(e.value);
segment.remove(e.key, e.hash, null);
}
}
@@ -888,6 +1067,7 @@
{
seenFirstLIR = true;
i.remove();
+ currentLIRSize--;
next.transitionLIRResidentToHIRResident();
queue.addLast(next);
}
@@ -1049,6 +1229,11 @@
*/
final float loadFactor;
+ /**
+ * Evict cap
+ */
+ final int evictCap;
+
/** The eviction policy */
final transient EvictionPolicy<K, V> eviction;
@@ -1058,14 +1243,16 @@
/**
* Constructor
* @param cap The capacity
+ * @param ec The eviction cap
* @param lf The load factor
* @param es The eviction
* @param listener The eviction listener
*/
- Segment(int cap, float lf, Eviction es, EvictionListener<K, V> listener)
+ Segment(int cap, int ec, float lf, Eviction es, EvictionListener<K, V> listener)
{
loadFactor = lf;
- eviction = es.make(this, cap, lf);
+ evictCap = ec;
+ eviction = es.make(this, evictCap, lf);
evictionListener = listener;
setTable(HashEntry.<K, V> newArray(cap));
}
@@ -1357,7 +1544,7 @@
count = c; // write-volatile
if (eviction.strategy() != Eviction.NONE)
{
- if (c > tab.length)
+ if (c > evictCap)
{
// remove entries;lower count
evicted = eviction.execute();
@@ -1566,7 +1753,10 @@
{
try
{
- evicted = eviction.execute();
+ if (eviction.thresholdExpired())
+ {
+ evicted = eviction.execute();
+ }
}
finally
{
@@ -1678,14 +1868,14 @@
++c;
}
int cap = 1;
- while (cap < c)
+ while (cap < c / DEFAULT_LOAD_FACTOR)
{
cap <<= 1;
}
for (int i = 0; i < this.segments.length; ++i)
{
- this.segments[i] = new Segment<K, V>(cap, DEFAULT_LOAD_FACTOR, evictionStrategy, evictionListener);
+ this.segments[i] = new Segment<K, V>(cap, c, DEFAULT_LOAD_FACTOR, evictionStrategy, evictionListener);
}
}
@@ -1857,13 +2047,19 @@
{
segments[i].lock();
}
- for (int i = 0; i < segments.length; ++i)
+ try
{
- sum += segments[i].count;
+ for (int i = 0; i < segments.length; ++i)
+ {
+ sum += segments[i].count;
+ }
}
- for (int i = 0; i < segments.length; ++i)
+ finally
{
- segments[i].unlock();
+ for (int i = 0; i < segments.length; ++i)
+ {
+ segments[i].unlock();
+ }
}
}
if (sum > Integer.MAX_VALUE)
More information about the jboss-cvs-commits
mailing list