You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openjpa.apache.org by aw...@apache.org on 2006/09/20 20:40:29 UTC
svn commit: r448298 - in
/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel:
AbstractJDBCSeq.java ClassTableJDBCSeq.java NativeJDBCSeq.java
TableJDBCSeq.java
Author: awhite
Date: Wed Sep 20 11:40:28 2006
New Revision: 448298
URL: http://svn.apache.org/viewvc?view=rev&rev=448298
Log:
Perform JDBC sequence ops outside of synchronization blocks in case of JDBC
hangs. Also should improve concurrency.
Modified:
incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/AbstractJDBCSeq.java
incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/ClassTableJDBCSeq.java
incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/NativeJDBCSeq.java
incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/TableJDBCSeq.java
Modified: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/AbstractJDBCSeq.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/AbstractJDBCSeq.java?view=diff&rev=448298&r1=448297&r2=448298
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/AbstractJDBCSeq.java (original)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/AbstractJDBCSeq.java Wed Sep 20 11:40:28 2006
@@ -41,10 +41,6 @@
protected int type = TYPE_DEFAULT;
protected Object current = null;
- // used to track current conn so that we can close it
- private Connection _conn = null;
- private boolean _commit = false;
-
/**
* Records the sequence type.
*/
@@ -52,7 +48,7 @@
this.type = type;
}
- public synchronized Object next(StoreContext ctx, ClassMetaData meta) {
+ public Object next(StoreContext ctx, ClassMetaData meta) {
JDBCStore store = getStore(ctx);
try {
current = nextInternal(store, (ClassMapping) meta);
@@ -63,12 +59,10 @@
throw SQLExceptions.getStore(se, store.getDBDictionary());
} catch (Exception e) {
throw new StoreException(e);
- } finally {
- closeConnection();
}
}
- public synchronized Object current(StoreContext ctx, ClassMetaData meta) {
+ public Object current(StoreContext ctx, ClassMetaData meta) {
JDBCStore store = getStore(ctx);
try {
return currentInternal(store, (ClassMapping) meta);
@@ -78,13 +72,10 @@
throw SQLExceptions.getStore(se, store.getDBDictionary());
} catch (Exception e) {
throw new StoreException(e);
- } finally {
- closeConnection();
}
}
- public synchronized void allocate(int additional, StoreContext ctx,
- ClassMetaData meta) {
+ public void allocate(int additional, StoreContext ctx, ClassMetaData meta) {
JDBCStore store = getStore(ctx);
try {
allocateInternal(additional, store, (ClassMapping) meta);
@@ -94,8 +85,6 @@
throw SQLExceptions.getStore(se, store.getDBDictionary());
} catch (Exception e) {
throw new StoreException(e);
- } finally {
- closeConnection();
}
}
@@ -121,7 +110,7 @@
/**
* Return the current sequence object. By default returns the last
* sequence value used, or null if no sequence values have been requested
- * yet.
+ * yet. Default implementation is not threadsafe.
*/
protected Object currentInternal(JDBCStore store, ClassMapping mapping)
throws Exception {
@@ -149,41 +138,31 @@
*/
protected Connection getConnection(JDBCStore store)
throws SQLException {
- // close previous connection if user is asking for another connection
- closeConnection();
-
if (type == TYPE_TRANSACTIONAL || type == TYPE_CONTIGUOUS)
- _conn = store.getConnection();
- else {
- JDBCConfiguration conf = store.getConfiguration();
- DataSource ds = conf.getDataSource2(store.getContext());
- _conn = ds.getConnection();
- if (_conn.getAutoCommit())
- _conn.setAutoCommit(false);
- _commit = true;
- }
- return _conn;
+ return store.getConnection();
+
+ JDBCConfiguration conf = store.getConfiguration();
+ DataSource ds = conf.getDataSource2(store.getContext());
+ Connection conn = ds.getConnection();
+ if (conn.getAutoCommit())
+ conn.setAutoCommit(false);
+ return conn;
}
/**
* Close the current connection.
*/
- protected void closeConnection() {
- if (_conn == null)
+ protected void closeConnection(Connection conn) {
+ if (conn == null)
return;
try {
- if (_commit)
- _conn.commit();
+ if (type == TYPE_TRANSACTIONAL || type == TYPE_CONTIGUOUS)
+ conn.commit();
} catch (SQLException se) {
throw SQLExceptions.getStore(se);
} finally {
- try {
- _conn.close();
- } catch (SQLException se) {
- }
- _conn = null;
- _commit = false;
+ try { conn.close(); } catch (SQLException se) {}
}
}
}
Modified: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/ClassTableJDBCSeq.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/ClassTableJDBCSeq.java?view=diff&rev=448298&r1=448297&r2=448298
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/ClassTableJDBCSeq.java (original)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/ClassTableJDBCSeq.java Wed Sep 20 11:40:28 2006
@@ -44,8 +44,8 @@
public class ClassTableJDBCSeq
extends TableJDBCSeq {
- private static final Localizer _loc = Localizer
- .forPackage(ClassTableJDBCSeq.class);
+ private static final Localizer _loc = Localizer.forPackage
+ (ClassTableJDBCSeq.class);
private final Map _stats = new HashMap();
private boolean _ignore = false;
@@ -95,7 +95,7 @@
_aliases = aliases;
}
- protected Status getStatus(ClassMapping mapping) {
+ protected synchronized Status getStatus(ClassMapping mapping) {
if (mapping == null)
return null;
String key = getKey(mapping, false);
Modified: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/NativeJDBCSeq.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/NativeJDBCSeq.java?view=diff&rev=448298&r1=448297&r2=448298
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/NativeJDBCSeq.java (original)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/NativeJDBCSeq.java Wed Sep 20 11:40:28 2006
@@ -199,8 +199,12 @@
protected Object nextInternal(JDBCStore store, ClassMapping mapping)
throws SQLException {
- long next = getSequence(getConnection(store));
- return Numbers.valueOf(next);
+ Connection conn = getConnection(store);
+ try {
+ return Numbers.valueOf(getSequence(conn));
+ } finally {
+ closeConnection(conn);
+ }
}
/**
Modified: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/TableJDBCSeq.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/TableJDBCSeq.java?view=diff&rev=448298&r1=448297&r2=448298
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/TableJDBCSeq.java (original)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/TableJDBCSeq.java Wed Sep 20 11:40:28 2006
@@ -213,20 +213,29 @@
throw new InvalidStateException(_loc.get("bad-seq-type",
getClass(), mapping));
- // make sure seq is at least 1, since autoassigned ids of 0 can
- // conflict with uninitialized values
- stat.seq = Math.max(stat.seq, 1);
- if (stat.seq >= stat.max)
+ while (true) {
+ synchronized (stat) {
+ // make sure seq is at least 1, since autoassigned ids of 0 can
+ // conflict with uninitialized values
+ stat.seq = Math.max(stat.seq, 1);
+ if (stat.seq < stat.max)
+ return Numbers.valueOf(stat.seq++);
+ }
allocateSequence(store, mapping, stat, _alloc, true);
- return Numbers.valueOf(stat.seq++);
+ }
}
protected Object currentInternal(JDBCStore store, ClassMapping mapping)
throws Exception {
if (current == null) {
- long cur = getSequence(mapping, getConnection(store));
- if (cur != -1)
- current = Numbers.valueOf(cur);
+ Connection conn = getConnection(store);
+ try {
+ long cur = getSequence(mapping, getConnection(store));
+ if (cur != -1)
+ current = Numbers.valueOf(cur);
+ } finally {
+ closeConnection(conn);
+ }
}
return super.currentInternal(store, mapping);
}
@@ -235,9 +244,18 @@
ClassMapping mapping)
throws SQLException {
Status stat = getStatus(mapping);
- if (stat != null && stat.max - stat.seq < count)
- allocateSequence(store, mapping, stat,
- count - (int) (stat.max - stat.seq), false);
+ if (stat == null)
+ return;
+
+ while (true) {
+ int available;
+ synchronized (stat) {
+ available = (int) (stat.max - stat.seq);
+ if (available >= count)
+ return;
+ }
+ allocateSequence(store, mapping, stat, count - available, false);
+ }
}
/**
@@ -295,40 +313,45 @@
* Updates the max available sequence value.
*/
private void allocateSequence(JDBCStore store, ClassMapping mapping,
- Status stat, int alloc, boolean updateStatSeq) {
+ Status stat, int alloc, boolean updateStatSeq)
+ throws SQLException {
+ Connection conn = getConnection(store);
+ try {
+ if (setSequence(mapping, stat, alloc, updateStatSeq, conn))
+ return;
+ } catch (SQLException se) {
+ throw SQLExceptions.getStore(_loc.get("bad-seq-up", _table),
+ se, _conf.getDBDictionaryInstance());
+ } finally {
+ closeConnection(conn);
+ }
+
try {
- // if the update fails, probably because row doesn't exist yet
- if (!setSequence(mapping, stat, alloc, updateStatSeq,
- getConnection(store))) {
- closeConnection();
-
- // possible that we might get errors when inserting if
- // another thread/process is inserting same pk at same time
- SQLException err = null;
- Connection conn = _conf.getDataSource2(store.getContext()).
- getConnection();
- try {
- insertSequence(mapping, conn);
- } catch (SQLException se) {
- err = se;
- } finally {
- try {
- conn.close();
- } catch (SQLException se) {
- }
- }
-
- // now we should be able to update...
- if (!setSequence(mapping, stat, alloc, updateStatSeq,
- getConnection(store)))
- throw(err != null) ? err : new SQLException(_loc.get
+ // possible that we might get errors when inserting if
+ // another thread/process is inserting same pk at same time
+ SQLException err = null;
+ conn = _conf.getDataSource2(store.getContext()).getConnection();
+ try {
+ insertSequence(mapping, conn);
+ } catch (SQLException se) {
+ err = se;
+ } finally {
+ try { conn.close(); } catch (SQLException se) {}
+ }
+
+ // now we should be able to update...
+ conn = getConnection(store);
+ try {
+ if (!setSequence(mapping, stat, alloc, updateStatSeq, conn))
+ throw (err != null) ? err : new SQLException(_loc.get
("no-seq-row", mapping, _table).getMessage());
+ } finally {
+ closeConnection(conn);
}
- }
- catch (SQLException se2) {
+ } catch (SQLException se2) {
throw SQLExceptions.getStore(_loc.get("bad-seq-up", _table),
se2, _conf.getDBDictionaryInstance());
- }
+ }
}
/**
@@ -362,10 +385,7 @@
stmnt.executeUpdate();
} finally {
if (stmnt != null)
- try {
- stmnt.close();
- } catch (SQLException se) {
- }
+ try { stmnt.close(); } catch (SQLException se) {}
if (!wasAuto)
conn.setAutoCommit(false);
}
@@ -401,14 +421,8 @@
return dict.getLong(rs, 1);
} finally {
if (rs != null)
- try {
- rs.close();
- } catch (SQLException se) {
- }
- try {
- stmnt.close();
- } catch (SQLException se) {
- }
+ try { rs.close(); } catch (SQLException se) {}
+ try { stmnt.close(); } catch (SQLException se) {}
}
}
@@ -433,8 +447,7 @@
SQLBuffer where = new SQLBuffer(dict).append(_pkColumn).append(" = ").
appendValue(pk, _pkColumn);
- // not all databases support locking, so loop until we have a
- // successful atomic select/update sequence
+ // loop until we have a successful atomic select/update sequence
long cur = 0;
PreparedStatement stmnt;
ResultSet rs;
@@ -459,23 +472,20 @@
stmnt = upd.prepareStatement(conn);
updates = stmnt.executeUpdate();
} finally {
- if (rs != null)
- try {
- rs.close();
- } catch (SQLException se) {
- }
+ if (rs != null)
+ try { rs.close(); } catch (SQLException se) {}
if (stmnt != null)
- try {
- stmnt.close();
- } catch (SQLException se) {
- }
+ try { stmnt.close(); } catch (SQLException se) {}
}
}
// setup new sequence range
- if (updateStatSeq)
- stat.seq = cur;
- stat.max = cur + inc;
+ synchronized (stat) {
+ if (updateStatSeq && stat.seq < cur)
+ stat.seq = cur;
+ if (stat.max < cur + inc)
+ stat.max = cur + inc;
+ }
return true;
}