[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