[jbosscache-commits] JBoss Cache SVN: r6802 - in core/branches/2.2.X/src/main/java/org/jboss/cache: lock and 1 other directories.

jbosscache-commits at lists.jboss.org jbosscache-commits at lists.jboss.org
Fri Sep 26 07:28:53 EDT 2008


Author: manik.surtani at jboss.com
Date: 2008-09-26 07:28:53 -0400 (Fri, 26 Sep 2008)
New Revision: 6802

Removed:
   core/branches/2.2.X/src/main/java/org/jboss/cache/util/concurrent/locks/
Modified:
   core/branches/2.2.X/src/main/java/org/jboss/cache/loader/AdjListJDBCCacheLoader.java
   core/branches/2.2.X/src/main/java/org/jboss/cache/loader/AdjListJDBCCacheLoaderConfig.java
   core/branches/2.2.X/src/main/java/org/jboss/cache/loader/JDBCCacheLoader.java
   core/branches/2.2.X/src/main/java/org/jboss/cache/loader/JDBCCacheLoaderOld.java
   core/branches/2.2.X/src/main/java/org/jboss/cache/lock/StripedLock.java
Log:
Better impl for JBCACHE-1410:  JDBCCacheLoader may attempt to create a node entry in the DB twice

Modified: core/branches/2.2.X/src/main/java/org/jboss/cache/loader/AdjListJDBCCacheLoader.java
===================================================================
--- core/branches/2.2.X/src/main/java/org/jboss/cache/loader/AdjListJDBCCacheLoader.java	2008-09-26 11:20:35 UTC (rev 6801)
+++ core/branches/2.2.X/src/main/java/org/jboss/cache/loader/AdjListJDBCCacheLoader.java	2008-09-26 11:28:53 UTC (rev 6802)
@@ -243,8 +243,46 @@
          safeClose(st);
          cf.close(con);
       }
+
+      createDummyTableIfNeeded();
    }
 
+   private void createDummyTableIfNeeded() throws Exception
+   {
+      Connection conn = null;
+      PreparedStatement ps = null;
+      try
+      {
+         conn = cf.getConnection();
+         ps = conn.prepareStatement(config.getDummyTableRemovalDDL());
+         ps.execute();
+      }
+      catch (Exception e)
+      {
+         // ignore - it just means we didn't need to drop any database tables.
+      }
+      finally
+      {
+         safeClose(ps);
+         cf.close(conn);
+      }
+
+      try
+      {
+         conn = cf.getConnection();
+         ps = conn.prepareStatement(config.getDummyTableCreationDDL());
+         ps.execute();
+         safeClose(ps);
+         ps = conn.prepareStatement(config.getDummyTablePopulationSql());
+         ps.execute();
+      }
+      finally
+      {
+         safeClose(ps);
+         cf.close(conn);
+      }
+   }
+
    @Override
    public void stop()
    {
@@ -411,10 +449,11 @@
    /**
     * Inserts a node into the database
     *
-    * @param name the fqn
-    * @param node the node
+    * @param name        the fqn
+    * @param node        the node
+    * @param rowMayExist if true, then this method will not be strict in testing for 1 row being inserted, since 0 may be inserted if the row already exists.
     */
-   protected void insertNode(Fqn name, Map node)
+   protected void insertNode(Fqn name, Map node, boolean rowMayExist)
    {
       Connection con = null;
       PreparedStatement ps = null;
@@ -428,8 +467,12 @@
          con = cf.getConnection();
          ps = con.prepareStatement(config.getInsertNodeSql());
 
-         ps.setString(1, name.toString());
+         String fqnString = name.toString();
 
+         // the Fqn needs to be in the 1st and 4th places.
+         ps.setString(1, fqnString);
+         ps.setString(4, fqnString);
+
          if (node != null)
          {
             //            ByteArrayOutputStream baos = new ByteArrayOutputStream();
@@ -465,7 +508,7 @@
          }
 
          int rows = ps.executeUpdate();
-         if (rows != 1)
+         if (!rowMayExist && rows != 1)
          {
             throw new IllegalStateException("Expected one insert row but got " + rows);
          }

Modified: core/branches/2.2.X/src/main/java/org/jboss/cache/loader/AdjListJDBCCacheLoaderConfig.java
===================================================================
--- core/branches/2.2.X/src/main/java/org/jboss/cache/loader/AdjListJDBCCacheLoaderConfig.java	2008-09-26 11:20:35 UTC (rev 6801)
+++ core/branches/2.2.X/src/main/java/org/jboss/cache/loader/AdjListJDBCCacheLoaderConfig.java	2008-09-26 11:28:53 UTC (rev 6802)
@@ -579,14 +579,44 @@
 
    private String constructInsertNodeSql()
    {
-      return "insert into " +
-            table +
-            " (" +
-            fqnColumn +
-            ", " +
-            nodeColumn +
-            ", " +
-            parentColumn +
-            ") values (?, ?, ?)";
+      // This SQL string takes in 4 params - fqn, node (serialized data), parent, and fqn AGAIN.
+      // the benefit of this is is that it will run without failing even if the row already exists, so you don't need
+      // to check if the row exists before running this query.  Returns '1' if the row was inserted, '0' otherwise,
+      // but does NOT fail on primary key conflict.
+
+      // the 'dummy' table, table_D, *must* exist though, and could contain just a single dummy constant row.
+
+      return "INSERT INTO "
+            + table
+            + " ("
+            + fqnColumn
+            + ", "
+            + nodeColumn
+            + ", "
+            + parentColumn
+            + ") SELECT ?, ?, ? FROM "
+            + table
+            + "_D WHERE NOT EXISTS (SELECT "
+            + fqnColumn
+            + " FROM "
+            + table
+            + " WHERE "
+            + fqnColumn
+            + " = ?)";
    }
+
+   public String getDummyTableCreationDDL()
+   {
+      return "create table " + table + "_D (i CHAR)";
+   }
+
+   public String getDummyTableRemovalDDL()
+   {
+      return "drop table " + table + "_D";
+   }
+
+   public String getDummyTablePopulationSql()
+   {
+      return "insert into " + table + "_D values ('x')";
+   }
 }
\ No newline at end of file

Modified: core/branches/2.2.X/src/main/java/org/jboss/cache/loader/JDBCCacheLoader.java
===================================================================
--- core/branches/2.2.X/src/main/java/org/jboss/cache/loader/JDBCCacheLoader.java	2008-09-26 11:20:35 UTC (rev 6801)
+++ core/branches/2.2.X/src/main/java/org/jboss/cache/loader/JDBCCacheLoader.java	2008-09-26 11:28:53 UTC (rev 6802)
@@ -240,21 +240,13 @@
       Fqn currentNode = name;
       do
       {
-         try
+         if (currentNode.equals(name))
          {
-            lock.acquireLock(currentNode, true);
-            if (currentNode.equals(name))
-            {
-               insertNode(currentNode, attributes);
-            }
-            else
-            {
-               if (loadNode(currentNode) == null) insertNode(currentNode, null);
-            }
+            insertNode(currentNode, attributes, false);
          }
-         finally
+         else
          {
-            lock.releaseLock(currentNode);
+            insertNode(currentNode, null, true);
          }
          if (currentNode.isRoot()) break;
          currentNode = currentNode.getParent();

Modified: core/branches/2.2.X/src/main/java/org/jboss/cache/loader/JDBCCacheLoaderOld.java
===================================================================
--- core/branches/2.2.X/src/main/java/org/jboss/cache/loader/JDBCCacheLoaderOld.java	2008-09-26 11:20:35 UTC (rev 6801)
+++ core/branches/2.2.X/src/main/java/org/jboss/cache/loader/JDBCCacheLoaderOld.java	2008-09-26 11:28:53 UTC (rev 6802)
@@ -135,11 +135,11 @@
                final Fqn parent = name.getAncestor(i);
                if (!exists(parent))
                {
-                  insertNode(parent, null);
+                  insertNode(parent, null, false);
                }
             }
          }
-         insertNode(name, node);
+         insertNode(name, node, false);
       }
 
       return oldValue;
@@ -317,11 +317,11 @@
                final Fqn parent = name.getAncestor(i);
                if (!exists(parent))
                {
-                  insertNode(parent, null);
+                  insertNode(parent, null, false);
                }
             }
          }
-         insertNode(name, attrs);
+         insertNode(name, attrs, false);
       }
    }
 }

Modified: core/branches/2.2.X/src/main/java/org/jboss/cache/lock/StripedLock.java
===================================================================
--- core/branches/2.2.X/src/main/java/org/jboss/cache/lock/StripedLock.java	2008-09-26 11:20:35 UTC (rev 6801)
+++ core/branches/2.2.X/src/main/java/org/jboss/cache/lock/StripedLock.java	2008-09-26 11:28:53 UTC (rev 6802)
@@ -23,9 +23,9 @@
 
 import net.jcip.annotations.ThreadSafe;
 import org.jboss.cache.Fqn;
-import org.jboss.cache.util.concurrent.locks.UpgradableLock;
 
 import java.util.List;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
 
 /**
  * A simple implementation of lock striping, using Fqns as the keys to lock on, primarily used to help make
@@ -48,7 +48,7 @@
    private final int lockSegmentMask;
    private final int lockSegmentShift;
 
-   final UpgradableLock[] sharedLocks;
+   final ReentrantReadWriteLock[] sharedLocks;
 
    /**
     * This constructor just calls {@link #StripedLock(int)} with a default concurrency value of 20.
@@ -75,9 +75,9 @@
       lockSegmentShift = 32 - tempLockSegShift;
       lockSegmentMask = numLocks - 1;
 
-      sharedLocks = new UpgradableLock[numLocks];
+      sharedLocks = new ReentrantReadWriteLock[numLocks];
 
-      for (int i = 0; i < numLocks; i++) sharedLocks[i] = new UpgradableLock();
+      for (int i = 0; i < numLocks; i++) sharedLocks[i] = new ReentrantReadWriteLock();
    }
 
    /**
@@ -88,11 +88,11 @@
     */
    public void acquireLock(Fqn fqn, boolean exclusive)
    {
-      UpgradableLock lock = getLock(fqn);
+      ReentrantReadWriteLock lock = getLock(fqn);
 
       if (exclusive)
       {
-         lock.acquireWriteLockWithUpgrade();
+         lock.writeLock().lock();
       }
       else
       {
@@ -107,11 +107,18 @@
     */
    public void releaseLock(Fqn fqn)
    {
-      UpgradableLock lock = getLock(fqn);
-      lock.unlock();
+      ReentrantReadWriteLock lock = getLock(fqn);
+      if (lock.isWriteLockedByCurrentThread())
+      {
+         lock.writeLock().unlock();
+      }
+      else
+      {
+         lock.readLock().unlock();
+      }
    }
 
-   final UpgradableLock getLock(Object o)
+   final ReentrantReadWriteLock getLock(Object o)
    {
       return sharedLocks[hashToIndex(o)];
    }




More information about the jbosscache-commits mailing list