Index: jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/OraclePersistenceManager.java =================================================================== --- jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/OraclePersistenceManager.java (revision 629174) +++ jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/OraclePersistenceManager.java (working copy) @@ -20,8 +20,10 @@ import java.sql.SQLException; import org.apache.jackrabbit.core.persistence.PMContext; +import org.apache.jackrabbit.core.persistence.bundle.util.DbNameIndex; import org.apache.jackrabbit.core.persistence.bundle.util.NGKDbNameIndex; -import org.apache.jackrabbit.core.persistence.bundle.util.DbNameIndex; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * Extends the {@link BundleDbPersistenceManager} by Oracle specific code. @@ -47,6 +49,11 @@ static final String CVS_ID = "$URL$ $Rev$ $Date$"; /** + * the default logger + */ + private static Logger log = LoggerFactory.getLogger(OraclePersistenceManager.class); + + /** * Creates a new oracle persistence manager */ public OraclePersistenceManager() { @@ -75,17 +82,20 @@ setSchemaObjectPrefix(context.getHomeDir().getName() + "_"); } super.init(context); -/* + // check driver version - DatabaseMetaData metaData = con.getMetaData(); - if (metaData.getDriverMajorVersion() < 10) { - // oracle drivers prior to version 10 only support - // writing BLOBs up to 32k in size... - log.warn("unsupported driver version detected: " - + metaData.getDriverName() - + " v" + metaData.getDriverVersion()); + try { + DatabaseMetaData metaData = connectionManager.getConnection().getMetaData(); + if (metaData.getDriverMajorVersion() < 10) { + // Oracle drivers prior to version 10 only support + // writing BLOBs up to 32k in size... + log.warn("Unsupported driver version detected: " + + metaData.getDriverName() + + " v" + metaData.getDriverVersion()); + } + } catch (SQLException e) { + log.warn("Can not retrieve driver version", e); } -*/ } /** @@ -94,7 +104,7 @@ * @throws SQLException if an SQL error occurs. */ protected DbNameIndex createDbNameIndex() throws SQLException { - return new NGKDbNameIndex(con, schemaObjectPrefix); + return new NGKDbNameIndex(connectionManager, schemaObjectPrefix); } /** @@ -114,7 +124,7 @@ * @inheritDoc */ protected void prepareSchemaObjectPrefix() throws Exception { - DatabaseMetaData metaData = con.getMetaData(); + DatabaseMetaData metaData = connectionManager.getConnection().getMetaData(); String legalChars = metaData.getExtraNameCharacters(); legalChars += "ABCDEFGHIJKLMNOPQRSTUVWXZY0123456789_"; Index: jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/DerbyPersistenceManager.java =================================================================== --- jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/DerbyPersistenceManager.java (revision 629174) +++ jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/DerbyPersistenceManager.java (working copy) @@ -19,9 +19,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.apache.jackrabbit.core.persistence.PMContext; -import org.apache.jackrabbit.core.persistence.db.DatabasePersistenceManager; -import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.sql.Statement; @@ -58,7 +56,7 @@ /** name of the embedded driver */ public static final String DERBY_EMBEDDED_DRIVER = "org.apache.derby.jdbc.EmbeddedDriver"; - + /** the default logger */ private static Logger log = LoggerFactory.getLogger(DerbyPersistenceManager.class); @@ -271,7 +269,7 @@ protected void checkSchema() throws SQLException, RepositoryException { // set properties if (DERBY_EMBEDDED_DRIVER.equals(getDriver())) { - Statement stmt = con.createStatement(); + Statement stmt = connectionManager.getConnection().createStatement(); try { stmt.execute("CALL SYSCS_UTIL.SYSCS_SET_DATABASE_PROPERTY " + "('derby.storage.initialPages', '" + derbyStorageInitialPages + "')"); @@ -317,7 +315,7 @@ } // prepare connection url for issuing shutdown command - String url = con.getMetaData().getURL(); + String url = connectionManager.getConnection().getMetaData().getURL(); int pos = url.lastIndexOf(';'); if (pos != -1) { // strip any attributes from connection url @@ -329,7 +327,7 @@ // otherwise Derby would mysteriously complain about some pending uncommitted // changes which can't possibly be true. // @todo further investigate - con.setAutoCommit(true); + connectionManager.getConnection().setAutoCommit(true); // now it's safe to shutdown the embedded Derby database try { @@ -342,4 +340,4 @@ super.close(); } -} \ No newline at end of file +} Index: jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/H2PersistenceManager.java =================================================================== --- jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/H2PersistenceManager.java (revision 629174) +++ jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/H2PersistenceManager.java (working copy) @@ -17,7 +17,6 @@ package org.apache.jackrabbit.core.persistence.bundle; import org.apache.jackrabbit.core.persistence.PMContext; -import org.apache.jackrabbit.core.persistence.PersistenceManager; import java.sql.Statement; import java.sql.SQLException; @@ -103,7 +102,7 @@ * {@inheritDoc} */ protected void checkSchema() throws SQLException, RepositoryException { - Statement stmt = con.createStatement(); + Statement stmt = connectionManager.getConnection().createStatement(); try { stmt.execute("SET LOCK_TIMEOUT " + lockTimeout); } finally { @@ -121,7 +120,7 @@ } if (getUrl().startsWith("jdbc:h2:file:")) { // have to explicitly shutdown in-proc h2 - Statement stmt = con.createStatement(); + Statement stmt = connectionManager.getConnection().createStatement(); stmt.execute("shutdown"); stmt.close(); } @@ -129,4 +128,4 @@ super.close(); } -} \ No newline at end of file +} Index: jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/BundleDbPersistenceManager.java =================================================================== --- jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/BundleDbPersistenceManager.java (revision 629174) +++ jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/BundleDbPersistenceManager.java (working copy) @@ -26,6 +26,7 @@ import org.apache.jackrabbit.core.state.NodeReferences; import org.apache.jackrabbit.core.persistence.PMContext; import org.apache.jackrabbit.core.persistence.AbstractPersistenceManager; +import org.apache.jackrabbit.core.persistence.bundle.util.ConnectionRecoveryManager; import org.apache.jackrabbit.core.persistence.bundle.util.DbNameIndex; import org.apache.jackrabbit.core.persistence.bundle.util.NodePropBundle; import org.apache.jackrabbit.core.persistence.bundle.util.BundleBinding; @@ -54,15 +55,14 @@ import java.sql.Blob; import java.sql.Connection; import java.sql.DatabaseMetaData; -import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; -import java.sql.Driver; -import java.util.Iterator; -import java.util.Collection; import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; import javax.jcr.RepositoryException; @@ -83,6 +83,7 @@ *
true if the blobs are stored in the DB.
* @return true if the blobs are stored in the DB.
@@ -405,7 +418,7 @@
throw new RepositoryException(msg);
}
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
- Statement stmt = con.createStatement();
+ Statement stmt = connectionManager.getConnection().createStatement();
try {
String sql = reader.readLine();
while (sql != null) {
@@ -440,10 +453,11 @@
* @return true if the tables exist;
* false otherwise.
*
- * @throws SQLException if an SQL erro occurs.
+ * @throws SQLException if a database error occurs.
+ * @throws RepositoryException if a repository exception occurs.
*/
- protected boolean checkTablesExist() throws SQLException {
- DatabaseMetaData metaData = con.getMetaData();
+ protected boolean checkTablesExist() throws SQLException, RepositoryException {
+ DatabaseMetaData metaData = connectionManager.getConnection().getMetaData();
String tableName = schemaObjectPrefix + "BUNDLE";
if (metaData.storesLowerCaseIdentifiers()) {
tableName = tableName.toLowerCase();
@@ -477,37 +491,37 @@
*
* Basically wrapps a JDBC transaction around super.store().
*/
- public synchronized void store(ChangeLog changeLog)
- throws ItemStateException {
-
- try {
- con.setAutoCommit(false);
- super.store(changeLog);
- } catch (SQLException e) {
- String msg = "setting autocommit failed.";
- log.error(msg, e);
- throw new ItemStateException(msg, e);
- } catch (ItemStateException e) {
- // storing the changes failed, rollback changes
+ public synchronized void store(ChangeLog changeLog) throws ItemStateException {
+ int trials = 2;
+ Throwable lastException = null;
+ do {
+ trials--;
+ Connection con = null;
try {
- con.rollback();
- } catch (SQLException e1) {
- String msg = "rollback of change log failed";
- log.error(msg, e1);
+ con = connectionManager.getConnection();
+ connectionManager.setAutoReconnect(false);
+ con.setAutoCommit(false);
+ super.store(changeLog);
+ con.commit();
+ con.setAutoCommit(true);
+ return;
+ } catch (Throwable th) {
+ lastException = th;
+ try {
+ if (con != null) {
+ con.rollback();
+ }
+ } catch (SQLException e) {
+ logException("rollback failed", e);
+ }
+ if (th instanceof SQLException || th.getCause() instanceof SQLException) {
+ connectionManager.close();
+ }
+ } finally {
+ connectionManager.setAutoReconnect(true);
}
- // re-throw original exception
- throw e;
- }
-
- // storing the changes succeeded, now commit the changes
- try {
- con.commit();
- con.setAutoCommit(true);
- } catch (SQLException e) {
- String msg = "committing change log failed";
- log.error(msg, e);
- throw new ItemStateException(msg, e);
- }
+ } while(blockOnConnectionLoss || trials > 0);
+ throw new ItemStateException(lastException.getMessage());
}
/**
@@ -521,14 +535,8 @@
this.name = context.getHomeDir().getName();
- // setup jdbc connection
- // Note: Explicit creation of new instance of the driver is required
- // in order to re-register the driver in the DriverManager after a
- // repository shutdown.
- Driver drv = (Driver) Class.forName(driver).newInstance();
- log.info("JDBC driver created: {}", drv);
- con = DriverManager.getConnection(url, user, password);
- con.setAutoCommit(true);
+ connectionManager = new ConnectionRecoveryManager(blockOnConnectionLoss,
+ getDriver(), getUrl(), getUser(), getPassword());
// make sure schemaObjectPrefix consists of legal name characters only
prepareSchemaObjectPrefix();
@@ -539,28 +547,8 @@
// create correct blob store
blobStore = createBlobStore();
- // prepare statements
- if (getStorageModel() == SM_BINARY_KEYS) {
- bundleInsert = con.prepareStatement("insert into " + schemaObjectPrefix + "BUNDLE (BUNDLE_DATA, NODE_ID) values (?, ?)");
- bundleUpdate = con.prepareStatement("update " + schemaObjectPrefix + "BUNDLE set BUNDLE_DATA = ? where NODE_ID = ?");
- bundleSelect = con.prepareStatement("select BUNDLE_DATA from " + schemaObjectPrefix + "BUNDLE where NODE_ID = ?");
- bundleDelete = con.prepareStatement("delete from " + schemaObjectPrefix + "BUNDLE where NODE_ID = ?");
+ buildSQLStatements();
- nodeReferenceInsert = con.prepareStatement("insert into " + schemaObjectPrefix + "REFS (REFS_DATA, NODE_ID) values (?, ?)");
- nodeReferenceUpdate = con.prepareStatement("update " + schemaObjectPrefix + "REFS set REFS_DATA = ? where NODE_ID = ?");
- nodeReferenceSelect = con.prepareStatement("select REFS_DATA from " + schemaObjectPrefix + "REFS where NODE_ID = ?");
- nodeReferenceDelete = con.prepareStatement("delete from " + schemaObjectPrefix + "REFS where NODE_ID = ?");
- } else {
- bundleInsert = con.prepareStatement("insert into " + schemaObjectPrefix + "BUNDLE (BUNDLE_DATA, NODE_ID_HI, NODE_ID_LO) values (?, ?, ?)");
- bundleUpdate = con.prepareStatement("update " + schemaObjectPrefix + "BUNDLE set BUNDLE_DATA = ? where NODE_ID_HI = ? and NODE_ID_LO = ?");
- bundleSelect = con.prepareStatement("select BUNDLE_DATA from " + schemaObjectPrefix + "BUNDLE where NODE_ID_HI = ? and NODE_ID_LO = ?");
- bundleDelete = con.prepareStatement("delete from " + schemaObjectPrefix + "BUNDLE where NODE_ID_HI = ? and NODE_ID_LO = ?");
-
- nodeReferenceInsert = con.prepareStatement("insert into " + schemaObjectPrefix + "REFS (REFS_DATA, NODE_ID_HI, NODE_ID_LO) values (?, ?, ?)");
- nodeReferenceUpdate = con.prepareStatement("update " + schemaObjectPrefix + "REFS set REFS_DATA = ? where NODE_ID_HI = ? and NODE_ID_LO = ?");
- nodeReferenceSelect = con.prepareStatement("select REFS_DATA from " + schemaObjectPrefix + "REFS where NODE_ID_HI = ? and NODE_ID_LO = ?");
- nodeReferenceDelete = con.prepareStatement("delete from " + schemaObjectPrefix + "REFS where NODE_ID_HI = ? and NODE_ID_LO = ?");
- }
// load namespaces
binding = new BundleBinding(errorHandling, blobStore, getNsIndex(), getNameIndex());
binding.setMinBlobSize(minBlobSize);
@@ -613,7 +601,7 @@
* @throws SQLException if an SQL error occurs.
*/
protected DbNameIndex createDbNameIndex() throws SQLException {
- return new DbNameIndex(con, schemaObjectPrefix);
+ return new DbNameIndex(connectionManager, schemaObjectPrefix);
}
/**
@@ -667,20 +655,16 @@
log.info("{}: checking workspace consistency...", name);
Collection modifications = new ArrayList();
- PreparedStatement stmt = null;
ResultSet rs = null;
DataInputStream din = null;
try {
+ String sql;
if (getStorageModel() == SM_BINARY_KEYS) {
- stmt = con.prepareStatement(
- "select NODE_ID, BUNDLE_DATA from "
- + schemaObjectPrefix + "BUNDLE");
+ sql = "select NODE_ID, BUNDLE_DATA from " + schemaObjectPrefix + "BUNDLE";
} else {
- stmt = con.prepareStatement(
- "select NODE_ID_HI, NODE_ID_LO, BUNDLE_DATA from "
- + schemaObjectPrefix + "BUNDLE");
+ sql = "select NODE_ID_HI, NODE_ID_LO, BUNDLE_DATA from " + schemaObjectPrefix + "BUNDLE";
}
- stmt.execute();
+ Statement stmt = connectionManager.executeStmt(sql, new Object[0]);
rs = stmt.getResultSet();
while (rs.next()) {
NodeId id;
@@ -751,7 +735,6 @@
} finally {
closeStream(din);
closeResultSet(rs);
- closeStatement(stmt);
}
if (consistencyFix && !modifications.isEmpty()) {
@@ -781,7 +764,7 @@
* @throws Exception if an error occurs
*/
protected void prepareSchemaObjectPrefix() throws Exception {
- DatabaseMetaData metaData = con.getMetaData();
+ DatabaseMetaData metaData = connectionManager.getConnection().getMetaData();
String legalChars = metaData.getExtraNameCharacters();
legalChars += "ABCDEFGHIJKLMNOPQRSTUVWXZY0123456789_";
@@ -811,24 +794,10 @@
}
try {
- // close shared prepared statements
- closeStatement(bundleInsert);
- closeStatement(bundleUpdate);
- closeStatement(bundleSelect);
- closeStatement(bundleDelete);
-
- closeStatement(nodeReferenceInsert);
- closeStatement(nodeReferenceUpdate);
- closeStatement(nodeReferenceSelect);
- closeStatement(nodeReferenceDelete);
-
if (nameIndex instanceof DbNameIndex) {
((DbNameIndex) nameIndex).close();
}
-
- // close jdbc connection
- con.close();
-
+ connectionManager.close();
// close blob store
blobStore.close();
blobStore = null;
@@ -859,16 +828,63 @@
}
/**
+ * Constructs a parameter list for a PreparedStatement
+ * for the given UUID.
+ *
+ * @param uuid the uuid
+ * @return a list of Objects
+ */
+ protected Object[] getKey(UUID uuid) {
+ if (getStorageModel() == SM_BINARY_KEYS) {
+ return new Object[]{uuid.getRawBytes()};
+ } else {
+ return new Object[]{new Long(uuid.getMostSignificantBits()),
+ new Long(uuid.getLeastSignificantBits())};
+ }
+ }
+
+ /**
+ * Creates a parameter array for an SQL statement that needs
+ * (i) a UUID, and (2) another parameter.
+ *
+ * @param uuid the UUID
+ * @param p the other parameter
+ * @param before whether the other parameter should be before the uuid parameter
+ * @return an Object array that represents the parameters
+ */
+ protected Object[] createParams(UUID uuid, Object p, boolean before) {
+
+ // Create the key
+ List key = new ArrayList();
+ if (getStorageModel() == SM_BINARY_KEYS) {
+ key.add(uuid.getRawBytes());
+ } else {
+ key.add(new Long(uuid.getMostSignificantBits()));
+ key.add(new Long(uuid.getLeastSignificantBits()));
+ }
+
+ // Create the parameters
+ List params = new ArrayList();
+ if (before) {
+ params.add(p);
+ params.addAll(key);
+ } else {
+ params.addAll(key);
+ params.add(p);
+ }
+
+ return params.toArray();
+ }
+
+ /**
* {@inheritDoc}
*/
protected synchronized NodePropBundle loadBundle(NodeId id)
throws ItemStateException {
- PreparedStatement stmt = bundleSelect;
ResultSet rs = null;
InputStream in = null;
try {
- setKey(stmt, id.getUUID(), 1);
- stmt.execute();
+ Statement stmt = connectionManager.executeStmt(bundleSelectSQL, getKey(id.getUUID()));
rs = stmt.getResultSet();
if (!rs.next()) {
return null;
@@ -893,7 +909,6 @@
} finally {
closeStream(in);
closeResultSet(rs);
- resetStatement(stmt);
}
}
@@ -901,13 +916,10 @@
* {@inheritDoc}
*/
protected synchronized boolean existsBundle(NodeId id) throws ItemStateException {
- PreparedStatement stmt = bundleSelect;
ResultSet rs = null;
try {
- setKey(stmt, id.getUUID(), 1);
- stmt.execute();
+ Statement stmt = connectionManager.executeStmt(bundleSelectSQL, getKey(id.getUUID()));
rs = stmt.getResultSet();
-
// a bundle exists, if the result has at least one entry
return rs.next();
} catch (Exception e) {
@@ -916,7 +928,6 @@
throw new ItemStateException(msg, e);
} finally {
closeResultSet(rs);
- resetStatement(stmt);
}
}
@@ -924,27 +935,19 @@
* {@inheritDoc}
*/
protected synchronized void storeBundle(NodePropBundle bundle) throws ItemStateException {
- PreparedStatement stmt = null;
try {
ByteArrayOutputStream out = new ByteArrayOutputStream(INITIAL_BUFFER_SIZE);
DataOutputStream dout = new DataOutputStream(out);
binding.writeBundle(dout, bundle);
dout.close();
- if (bundle.isNew()) {
- stmt = bundleInsert;
- } else {
- stmt = bundleUpdate;
- }
- stmt.setBytes(1, out.toByteArray());
- setKey(stmt, bundle.getId().getUUID(), 2);
- stmt.execute();
+ String sql = bundle.isNew() ? bundleInsertSQL : bundleUpdateSQL;
+ Object[] params = createParams(bundle.getId().getUUID(), out.toByteArray(), true);
+ connectionManager.executeStmt(sql, params);
} catch (Exception e) {
String msg = "failed to write bundle: " + bundle.getId();
log.error(msg, e);
throw new ItemStateException(msg, e);
- } finally {
- resetStatement(stmt);
}
}
@@ -952,10 +955,8 @@
* {@inheritDoc}
*/
protected synchronized void destroyBundle(NodePropBundle bundle) throws ItemStateException {
- PreparedStatement stmt = bundleDelete;
try {
- setKey(stmt, bundle.getId().getUUID(), 1);
- stmt.execute();
+ connectionManager.executeStmt(bundleDeleteSQL, getKey(bundle.getId().getUUID()));
// also delete all
bundle.removeAllProperties();
} catch (Exception e) {
@@ -965,8 +966,6 @@
String msg = "failed to delete bundle: " + bundle.getId();
log.error(msg, e);
throw new ItemStateException(msg, e);
- } finally {
- resetStatement(stmt);
}
}
@@ -979,12 +978,11 @@
throw new IllegalStateException("not initialized");
}
- PreparedStatement stmt = nodeReferenceSelect;
ResultSet rs = null;
InputStream in = null;
try {
- setKey(stmt, targetId.getTargetId().getUUID(), 1);
- stmt.execute();
+ Statement stmt = connectionManager.executeStmt(
+ nodeReferenceSelectSQL, getKey(targetId.getTargetId().getUUID()));
rs = stmt.getResultSet();
if (!rs.next()) {
throw new NoSuchItemStateException(targetId.toString());
@@ -1005,7 +1003,6 @@
} finally {
closeStream(in);
closeResultSet(rs);
- resetStatement(stmt);
}
}
@@ -1023,34 +1020,25 @@
throw new IllegalStateException("not initialized");
}
- PreparedStatement stmt = null;
- try {
- // check if insert or update
- if (exists(refs.getId())) {
- stmt = nodeReferenceUpdate;
- } else {
- stmt = nodeReferenceInsert;
- }
+ // check if insert or update
+ boolean update = exists(refs.getId());
+ String sql = (update) ? nodeReferenceUpdateSQL : nodeReferenceInsertSQL;
- ByteArrayOutputStream out = new ByteArrayOutputStream(INITIAL_BUFFER_SIZE);
+ try {
+ ByteArrayOutputStream out =
+ new ByteArrayOutputStream(INITIAL_BUFFER_SIZE);
// serialize references
Serializer.serialize(refs, out);
- // we are synchronized on this instance, therefore we do not
- // not have to additionally synchronize on the preparedStatement
+ Object[] params = createParams(refs.getTargetId().getUUID(), out.toByteArray(), true);
+ connectionManager.executeStmt(sql, params);
- stmt.setBytes(1, out.toByteArray());
- setKey(stmt, refs.getTargetId().getUUID(), 2);
- stmt.execute();
-
// there's no need to close a ByteArrayOutputStream
//out.close();
} catch (Exception e) {
- String msg = "failed to write property state: " + refs.getTargetId();
+ String msg = "failed to write node references: " + refs.getId();
log.error(msg, e);
throw new ItemStateException(msg, e);
- } finally {
- resetStatement(stmt);
}
}
@@ -1062,10 +1050,9 @@
throw new IllegalStateException("not initialized");
}
- PreparedStatement stmt = nodeReferenceDelete;
try {
- setKey(stmt, refs.getTargetId().getUUID(), 1);
- stmt.execute();
+ connectionManager.executeStmt(nodeReferenceDeleteSQL,
+ getKey(refs.getTargetId().getUUID()));
} catch (Exception e) {
if (e instanceof NoSuchItemStateException) {
throw (NoSuchItemStateException) e;
@@ -1073,8 +1060,6 @@
String msg = "failed to delete references: " + refs.getTargetId();
log.error(msg, e);
throw new ItemStateException(msg, e);
- } finally {
- resetStatement(stmt);
}
}
@@ -1086,22 +1071,21 @@
throw new IllegalStateException("not initialized");
}
- PreparedStatement stmt = nodeReferenceSelect;
ResultSet rs = null;
try {
- setKey(stmt, targetId.getTargetId().getUUID(), 1);
- stmt.execute();
+ Statement stmt = connectionManager.executeStmt(nodeReferenceSelectSQL,
+ getKey(targetId.getTargetId().getUUID()));
rs = stmt.getResultSet();
- // a reference exists, if the result has at least one entry
+ // a reference exists if the result has at least one entry
return rs.next();
} catch (Exception e) {
- String msg = "failed to check existence of node references: " + targetId;
+ String msg = "failed to check existence of node references: "
+ + targetId;
log.error(msg, e);
throw new ItemStateException(msg, e);
} finally {
closeResultSet(rs);
- resetStatement(stmt);
}
}
@@ -1188,6 +1172,34 @@
}
/**
+ * Initializes the SQL strings.
+ */
+ protected void buildSQLStatements() {
+ // prepare statements
+ if (getStorageModel() == SM_BINARY_KEYS) {
+ bundleInsertSQL = "insert into " + schemaObjectPrefix + "BUNDLE (BUNDLE_DATA, NODE_ID) values (?, ?)";
+ bundleUpdateSQL = "update " + schemaObjectPrefix + "BUNDLE set BUNDLE_DATA = ? where NODE_ID = ?";
+ bundleSelectSQL = "select BUNDLE_DATA from " + schemaObjectPrefix + "BUNDLE where NODE_ID = ?";
+ bundleDeleteSQL = "delete from " + schemaObjectPrefix + "BUNDLE where NODE_ID = ?";
+
+ nodeReferenceInsertSQL = "insert into " + schemaObjectPrefix + "REFS (REFS_DATA, NODE_ID) values (?, ?)";
+ nodeReferenceUpdateSQL = "update " + schemaObjectPrefix + "REFS set REFS_DATA = ? where NODE_ID = ?";
+ nodeReferenceSelectSQL = "select REFS_DATA from " + schemaObjectPrefix + "REFS where NODE_ID = ?";
+ nodeReferenceDeleteSQL = "delete from " + schemaObjectPrefix + "REFS where NODE_ID = ?";
+ } else {
+ bundleInsertSQL = "insert into " + schemaObjectPrefix + "BUNDLE (BUNDLE_DATA, NODE_ID_HI, NODE_ID_LO) values (?, ?, ?)";
+ bundleUpdateSQL = "update " + schemaObjectPrefix + "BUNDLE set BUNDLE_DATA = ? where NODE_ID_HI = ? and NODE_ID_LO = ?";
+ bundleSelectSQL = "select BUNDLE_DATA from " + schemaObjectPrefix + "BUNDLE where NODE_ID_HI = ? and NODE_ID_LO = ?";
+ bundleDeleteSQL = "delete from " + schemaObjectPrefix + "BUNDLE where NODE_ID_HI = ? and NODE_ID_LO = ?";
+
+ nodeReferenceInsertSQL = "insert into " + schemaObjectPrefix + "REFS (REFS_DATA, NODE_ID_HI, NODE_ID_LO) values (?, ?, ?)";
+ nodeReferenceUpdateSQL = "update " + schemaObjectPrefix + "REFS set REFS_DATA = ? where NODE_ID_HI = ? and NODE_ID_LO = ?";
+ nodeReferenceSelectSQL = "select REFS_DATA from " + schemaObjectPrefix + "REFS where NODE_ID_HI = ? and NODE_ID_LO = ?";
+ nodeReferenceDeleteSQL = "delete from " + schemaObjectPrefix + "REFS where NODE_ID_HI = ? and NODE_ID_LO = ?";
+ }
+ }
+
+ /**
* Helper interface for closeable stores
*/
protected static interface CloseableBLOBStore extends BLOBStore {
@@ -1226,28 +1238,18 @@
*/
protected class DbBlobStore implements CloseableBLOBStore {
- protected PreparedStatement blobInsert;
- protected PreparedStatement blobUpdate;
- protected PreparedStatement blobSelect;
- protected PreparedStatement blobSelectExist;
- protected PreparedStatement blobDelete;
+ protected String blobInsertSQL;
+ protected String blobUpdateSQL;
+ protected String blobSelectSQL;
+ protected String blobSelectExistSQL;
+ protected String blobDeleteSQL;
public DbBlobStore() throws SQLException {
- blobInsert =
- con.prepareStatement("insert into "
- + schemaObjectPrefix + "BINVAL (BINVAL_DATA, BINVAL_ID) values (?, ?)");
- blobUpdate =
- con.prepareStatement("update "
- + schemaObjectPrefix + "BINVAL set BINVAL_DATA = ? where BINVAL_ID = ?");
- blobSelect =
- con.prepareStatement("select BINVAL_DATA from "
- + schemaObjectPrefix + "BINVAL where BINVAL_ID = ?");
- blobSelectExist =
- con.prepareStatement("select 1 from "
- + schemaObjectPrefix + "BINVAL where BINVAL_ID = ?");
- blobDelete =
- con.prepareStatement("delete from "
- + schemaObjectPrefix + "BINVAL where BINVAL_ID = ?");
+ blobInsertSQL = "insert into " + schemaObjectPrefix + "BINVAL (BINVAL_DATA, BINVAL_ID) values (?, ?)";
+ blobUpdateSQL = "update " + schemaObjectPrefix + "BINVAL set BINVAL_DATA = ? where BINVAL_ID = ?";
+ blobSelectSQL = "select BINVAL_DATA from " + schemaObjectPrefix + "BINVAL where BINVAL_ID = ?";
+ blobSelectExistSQL = "select 1 from " + schemaObjectPrefix + "BINVAL where BINVAL_ID = ?";
+ blobDeleteSQL = "delete from " + schemaObjectPrefix + "BINVAL where BINVAL_ID = ?";
}
/**
@@ -1269,39 +1271,31 @@
* {@inheritDoc}
*/
public InputStream get(String blobId) throws Exception {
- PreparedStatement stmt = blobSelect;
- synchronized (stmt) {
- try {
- stmt.setString(1, blobId);
- stmt.execute();
- final ResultSet rs = stmt.getResultSet();
- if (!rs.next()) {
- closeResultSet(rs);
- throw new Exception("no such BLOB: " + blobId);
- }
- InputStream in = rs.getBinaryStream(1);
- if (in == null) {
- // some databases treat zero-length values as NULL;
- // return empty InputStream in such a case
- closeResultSet(rs);
- return new ByteArrayInputStream(new byte[0]);
- }
+ Statement stmt = connectionManager.executeStmt(blobSelectSQL, new Object[]{blobId});
+ final ResultSet rs = stmt.getResultSet();
+ if (!rs.next()) {
+ closeResultSet(rs);
+ throw new Exception("no such BLOB: " + blobId);
+ }
+ InputStream in = rs.getBinaryStream(1);
+ if (in == null) {
+ // some databases treat zero-length values as NULL;
+ // return empty InputStream in such a case
+ closeResultSet(rs);
+ return new ByteArrayInputStream(new byte[0]);
+ }
- /**
- * return an InputStream wrapper in order to
- * close the ResultSet when the stream is closed
- */
- return new FilterInputStream(in) {
- public void close() throws IOException {
- in.close();
- // now it's safe to close ResultSet
- closeResultSet(rs);
- }
- };
- } finally {
- resetStatement(stmt);
+ /**
+ * return an InputStream wrapper in order to
+ * close the ResultSet when the stream is closed
+ */
+ return new FilterInputStream(in) {
+ public void close() throws IOException {
+ in.close();
+ // now it's safe to close ResultSet
+ closeResultSet(rs);
}
- }
+ };
}
/**
@@ -1309,45 +1303,28 @@
*/
public synchronized void put(String blobId, InputStream in, long size)
throws Exception {
- PreparedStatement stmt = blobSelectExist;
- try {
- stmt.setString(1, blobId);
- stmt.execute();
- ResultSet rs = stmt.getResultSet();
- // a BLOB exists if the result has at least one entry
- boolean exists = rs.next();
- resetStatement(stmt);
- closeResultSet(rs);
+ Statement stmt = connectionManager.executeStmt(blobSelectExistSQL, new Object[]{blobId});
+ ResultSet rs = stmt.getResultSet();
+ // a BLOB exists if the result has at least one entry
+ boolean exists = rs.next();
+ closeResultSet(rs);
- stmt = (exists) ? blobUpdate : blobInsert;
- stmt.setBinaryStream(1, in, (int) size);
- stmt.setString(2, blobId);
- stmt.executeUpdate();
- } finally {
- resetStatement(stmt);
- }
+ String sql = (exists) ? blobUpdateSQL : blobInsertSQL;
+ Object[] params = new Object[]{new ConnectionRecoveryManager.StreamWrapper(in, size), blobId};
+ connectionManager.executeStmt(sql, params);
}
/**
* {@inheritDoc}
*/
public synchronized boolean remove(String blobId) throws Exception {
- PreparedStatement stmt = blobDelete;
- try {
- stmt.setString(1, blobId);
- return stmt.executeUpdate() == 1;
- } finally {
- resetStatement(stmt);
- }
+ Statement stmt = connectionManager.executeStmt(blobDeleteSQL, new Object[]{blobId});
+ return stmt.getUpdateCount() == 1;
}
public void close() {
- closeStatement(blobInsert);
- closeStatement(blobUpdate);
- closeStatement(blobSelect);
- closeStatement(blobSelectExist);
- closeStatement(blobDelete);
+ // closing the database resources of this blobstore is left to the
+ // owning BundleDbPersistenceManager
}
}
-
}
Index: jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/AbstractBundlePersistenceManager.java
===================================================================
--- jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/AbstractBundlePersistenceManager.java (revision 629174)
+++ jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/AbstractBundlePersistenceManager.java (working copy)
@@ -16,40 +16,40 @@
*/
package org.apache.jackrabbit.core.persistence.bundle;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+import javax.jcr.PropertyType;
+
+import org.apache.jackrabbit.core.NamespaceRegistryImpl;
+import org.apache.jackrabbit.core.NodeId;
+import org.apache.jackrabbit.core.PropertyId;
+import org.apache.jackrabbit.core.fs.FileSystem;
import org.apache.jackrabbit.core.fs.FileSystemResource;
-import org.apache.jackrabbit.core.fs.FileSystem;
+import org.apache.jackrabbit.core.nodetype.PropDefId;
+import org.apache.jackrabbit.core.persistence.PMContext;
+import org.apache.jackrabbit.core.persistence.PersistenceManager;
+import org.apache.jackrabbit.core.persistence.bundle.util.BundleCache;
+import org.apache.jackrabbit.core.persistence.bundle.util.HashMapIndex;
+import org.apache.jackrabbit.core.persistence.bundle.util.LRUNodeIdCache;
+import org.apache.jackrabbit.core.persistence.bundle.util.NamespaceIndex;
+import org.apache.jackrabbit.core.persistence.bundle.util.NodePropBundle;
+import org.apache.jackrabbit.core.persistence.bundle.util.StringIndex;
+import org.apache.jackrabbit.core.state.ChangeLog;
import org.apache.jackrabbit.core.state.ItemState;
-import org.apache.jackrabbit.core.state.ChangeLog;
import org.apache.jackrabbit.core.state.ItemStateException;
+import org.apache.jackrabbit.core.state.NoSuchItemStateException;
import org.apache.jackrabbit.core.state.NodeReferences;
-import org.apache.jackrabbit.core.state.NoSuchItemStateException;
import org.apache.jackrabbit.core.state.NodeReferencesId;
+import org.apache.jackrabbit.core.state.NodeState;
import org.apache.jackrabbit.core.state.PropertyState;
-import org.apache.jackrabbit.core.state.NodeState;
-import org.apache.jackrabbit.core.NodeId;
-import org.apache.jackrabbit.core.PropertyId;
-import org.apache.jackrabbit.core.NamespaceRegistryImpl;
-import org.apache.jackrabbit.core.nodetype.PropDefId;
import org.apache.jackrabbit.core.value.InternalValue;
-import org.apache.jackrabbit.core.persistence.PMContext;
-import org.apache.jackrabbit.core.persistence.PersistenceManager;
-import org.apache.jackrabbit.core.persistence.bundle.util.StringIndex;
-import org.apache.jackrabbit.core.persistence.bundle.util.NamespaceIndex;
-import org.apache.jackrabbit.core.persistence.bundle.util.NodePropBundle;
-import org.apache.jackrabbit.core.persistence.bundle.util.BundleCache;
-import org.apache.jackrabbit.core.persistence.bundle.util.LRUNodeIdCache;
-import org.apache.jackrabbit.core.persistence.bundle.util.HashMapIndex;
import org.apache.jackrabbit.name.QName;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Set;
-
-import javax.jcr.PropertyType;
-
/**
* The AbstractBundlePersistenceManager acts as base for all
* persistence managers that store the state in a {@link NodePropBundle}.
Index: jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/util/ConnectionRecoveryManager.java
===================================================================
--- jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/util/ConnectionRecoveryManager.java (revision 629174)
+++ jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/util/ConnectionRecoveryManager.java (working copy)
@@ -26,6 +26,8 @@
import java.sql.Statement;
import java.util.HashMap;
+import javax.jcr.RepositoryException;
+
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -124,8 +126,9 @@
* @param url the url to use for the connection
* @param user the user to use for the connection
* @param password the password to use for the connection
+ * @throws RepositoryException if the database driver could not be loaded
*/
- public ConnectionRecoveryManager(boolean block, String driver, String url, String user, String password) {
+ public ConnectionRecoveryManager(boolean block, String driver, String url, String user, String password) throws RepositoryException {
this.block = block;
this.driver = driver;
this.url = url;
@@ -147,8 +150,9 @@
*
* @return the database connection that is managed
* @throws SQLException on error
+ * @throws RepositoryException if the database driver could not be loaded
*/
- public synchronized Connection getConnection() throws SQLException {
+ public synchronized Connection getConnection() throws SQLException, RepositoryException {
if (isClosed) {
if (autoReconnect) {
reestablishConnection();
@@ -172,13 +176,38 @@
}
/**
+ * Executes the given SQL query. Retries once or blocks (when the
+ * block parameter has been set to true on construction)
+ * if this fails and autoReconnect is enabled.
+ *
+ * @param sql the SQL query to execute
+ * @return the executed ResultSet
+ * @throws SQLException on error
+ * @throws RepositoryException if the database driver could not be loaded
+ */
+ public synchronized ResultSet executeQuery(String sql) throws SQLException, RepositoryException {
+ int trials = 2;
+ SQLException lastException = null;
+ do {
+ trials--;
+ try {
+ return executeQueryInternal(sql);
+ } catch (SQLException e) {
+ lastException = e;
+ }
+ } while(autoReconnect && (block || trials > 0));
+ throw lastException;
+ }
+
+ /**
* Executes the given SQL query.
*
* @param sql query to execute
* @return a ResultSet object
* @throws SQLException if an error occurs
+ * @throws RepositoryException if the database driver could not be loaded
*/
- public synchronized ResultSet executeQuery(String sql) throws SQLException {
+ private ResultSet executeQueryInternal(String sql) throws SQLException, RepositoryException {
PreparedStatement stmt = null;
try {
stmt = (PreparedStatement) preparedStatements.get(sql);
@@ -203,20 +232,34 @@
* @param params parameters to set
* @return the Statement object that had been executed
* @throws SQLException if an error occurs
+ * @throws RepositoryException if the database driver could not be loaded
*/
- public synchronized Statement executeStmt(String sql, Object[] params) throws SQLException {
- try {
- PreparedStatement stmt = (PreparedStatement) preparedStatements.get(sql);
- if (stmt == null) {
- stmt = getConnection().prepareStatement(sql);
- preparedStatements.put(sql, stmt);
+ public Statement executeStmt(String sql, Object[] params) throws SQLException, RepositoryException {
+ return executeStmt(sql, params, Statement.NO_GENERATED_KEYS);
+ }
+
+ /**
+ * Executes the given SQL statement with the specified parameters.
+ *
+ * @param sql statement to execute
+ * @param params parameters to set
+ * @param autoGeneratedKeys the constant that tells the driver to make auto generated keys available
+ * @return the Statement object that had been executed
+ * @throws SQLException if an error occurs
+ * @throws RepositoryException if the database driver could not be loaded
+ */
+ public synchronized Statement executeStmt(String sql, Object[] params, int autoGeneratedKeys) throws SQLException, RepositoryException {
+ int trials = 2;
+ SQLException lastException = null;
+ do {
+ trials--;
+ try {
+ return executeStmtInternal(sql, params, autoGeneratedKeys);
+ } catch (SQLException e) {
+ lastException = e;
}
- return executeStmtInternal(params, stmt);
- } catch (SQLException e) {
- logException("could not execute statement", e);
- close();
- throw e;
- }
+ } while(autoReconnect && (block || trials > 0));
+ throw lastException;
}
/**
@@ -227,8 +270,9 @@
* @param autoGeneratedKeys the constant that tells the driver to make auto generated keys available
* @return the Statement object that had been executed
* @throws SQLException if an error occurs
+ * @throws RepositoryException if the database driver could not be loaded
*/
- public synchronized Statement executeStmt(String sql, Object[] params, int autoGeneratedKeys) throws SQLException {
+ private synchronized Statement executeStmtInternal(String sql, Object[] params, int autoGeneratedKeys) throws SQLException, RepositoryException {
try {
PreparedStatement stmt = (PreparedStatement) preparedStatements.get(sql + "_" + autoGeneratedKeys);
if (stmt == null) {
@@ -267,14 +311,24 @@
* Creates the database connection.
*
* @throws SQLException on error
+ * @throws RepositoryException if the database driver could not be loaded
*/
- private void setupConnection() throws SQLException {
+ private void setupConnection() throws SQLException, RepositoryException {
try {
- Class.forName(driver).newInstance();
- } catch (Exception e) {
- throw new SQLException("could not load driver: " + e.getMessage());
+ Class driverClass = Class.forName(driver);
+ // Workaround for Apache Derby:
+ // The JDBC specification recommends the Class.ForName method without the .newInstance() method call,
+ // but adding the newInstance() guarantees that Derby will be booted on any Java Virtual Machine.
+ driverClass.newInstance();
+ } catch (Throwable e) {
+ throw new RepositoryException("Could not load or initialize the database driver class " + driver, e);
}
- connection = DriverManager.getConnection(url, user, password);
+ try {
+ connection = DriverManager.getConnection(url, user, password);
+ } catch (SQLException e) {
+ log.warn("Could not connect; driver: " + driver + " url: " + url + " user: " + user + " error: " + e.toString(), e);
+ throw e;
+ }
connection.setAutoCommit(true);
try {
DatabaseMetaData meta = connection.getMetaData();
@@ -309,8 +363,9 @@
* Re-establishes the database connection.
*
* @throws SQLException if reconnecting failed
+ * @throws RepositoryException
*/
- private void reestablishConnection() throws SQLException {
+ private void reestablishConnection() throws SQLException, RepositoryException {
long trials = TRIALS;
SQLException exception = null;
Index: jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/util/DbNameIndex.java
===================================================================
--- jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/util/DbNameIndex.java (revision 629174)
+++ jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/util/DbNameIndex.java (working copy)
@@ -18,8 +18,6 @@
import java.util.HashMap;
-import java.sql.Connection;
-import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
@@ -42,14 +40,19 @@
*/
static final String CVS_ID = "$URL$ $Rev$ $Date$";
- // name index statements
- protected PreparedStatement nameSelect;
- protected PreparedStatement indexSelect;
- protected PreparedStatement nameInsert;
+ /**
+ * The class that manages statement execution and recovery from connection loss.
+ */
+ protected ConnectionRecoveryManager connectionManager;
+ // name index statements
+ protected String nameSelectSQL;
+ protected String indexSelectSQL;
+ protected String nameInsertSQL;
+
// caches
private final HashMap string2Index = new HashMap();
- private final HashMap index2String= new HashMap();
+ private final HashMap index2String = new HashMap();
/**
* Creates a new index that is stored in a db.
@@ -57,9 +60,10 @@
* @param schemaObjectPrefix the prefix for table names
* @throws SQLException if the statements cannot be prepared.
*/
- public DbNameIndex(Connection con, String schemaObjectPrefix)
+ public DbNameIndex(ConnectionRecoveryManager conMgr, String schemaObjectPrefix)
throws SQLException {
- init(con, schemaObjectPrefix);
+ connectionManager = conMgr;
+ init(schemaObjectPrefix);
}
/**
@@ -69,20 +73,19 @@
* @param schemaObjectPrefix the prefix for table names
* @throws SQLException if the statements cannot be prepared.
*/
- protected void init(Connection con, String schemaObjectPrefix)
+ protected void init(String schemaObjectPrefix)
throws SQLException {
- nameSelect = con.prepareStatement("select NAME from " + schemaObjectPrefix + "NAMES where ID = ?");
- indexSelect = con.prepareStatement("select ID from " + schemaObjectPrefix + "NAMES where NAME = ?");
- nameInsert = con.prepareStatement("insert into " + schemaObjectPrefix + "NAMES (NAME) values (?)", Statement.RETURN_GENERATED_KEYS);
+ nameSelectSQL = "select NAME from " + schemaObjectPrefix + "NAMES where ID = ?";
+ indexSelectSQL = "select ID from " + schemaObjectPrefix + "NAMES where NAME = ?";
+ nameInsertSQL = "insert into " + schemaObjectPrefix + "NAMES (NAME) values (?)";
}
/**
* Closes this index and releases it's resources.
*/
public void close() {
- closeStatement(nameSelect);
- closeStatement(indexSelect);
- closeStatement(nameInsert);
+ // closing the database resources is done by the owning
+ // BundleDbPersistenceManager that created this index
}
/**
@@ -135,11 +138,9 @@
*/
protected int insertString(String string) {
// assert index does not exist
- PreparedStatement stmt = nameInsert;
ResultSet rs = null;
try {
- stmt.setString(1, string);
- stmt.executeUpdate();
+ Statement stmt = connectionManager.executeStmt(nameInsertSQL, new Object[]{string}, Statement.RETURN_GENERATED_KEYS);
rs = stmt.getGeneratedKeys();
if (!rs.next()) {
return -1;
@@ -150,7 +151,6 @@
throw new IllegalStateException("Unable to insert index: " + e);
} finally {
closeResultSet(rs);
- resetStatement(stmt);
}
}
@@ -160,11 +160,9 @@
* @return the index or -1 if not found.
*/
protected int getIndex(String string) {
- PreparedStatement stmt = indexSelect;
ResultSet rs = null;
try {
- stmt.setString(1, string);
- stmt.execute();
+ Statement stmt = connectionManager.executeStmt(indexSelectSQL, new Object[]{string});
rs = stmt.getResultSet();
if (!rs.next()) {
return -1;
@@ -175,7 +173,6 @@
throw new IllegalStateException("Unable to read index: " + e);
} finally {
closeResultSet(rs);
- resetStatement(stmt);
}
}
@@ -185,11 +182,9 @@
* @return the string or null if not found.
*/
protected String getString(int index) {
- PreparedStatement stmt = nameSelect;
ResultSet rs = null;
try {
- stmt.setInt(1, index);
- stmt.execute();
+ Statement stmt = connectionManager.executeStmt(nameSelectSQL, new Object[]{new Integer(index)});
rs = stmt.getResultSet();
if (!rs.next()) {
return null;
@@ -200,42 +195,10 @@
throw new IllegalStateException("Unable to read name: " + e);
} finally {
closeResultSet(rs);
- resetStatement(stmt);
}
}
/**
- * closes the statement
- * @param stmt the statement
- */
- protected void closeStatement(PreparedStatement stmt) {
- if (stmt != null) {
- try {
- stmt.close();
- } catch (SQLException se) {
- // ignore
- }
- }
- }
- /**
- * Resets the given PreparedStatement by clearing the
- * parameters and warnings contained.
- *
- * @param stmt The PreparedStatement to reset. If
- * null this method does nothing.
- */
- protected void resetStatement(PreparedStatement stmt) {
- if (stmt != null) {
- try {
- stmt.clearParameters();
- stmt.clearWarnings();
- } catch (SQLException se) {
- // ignore
- }
- }
- }
-
- /**
* Closes the result set
* @param rs the result set.
*/
@@ -248,4 +211,4 @@
}
}
}
-}
\ No newline at end of file
+}
Index: jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/util/NGKDbNameIndex.java
===================================================================
--- jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/util/NGKDbNameIndex.java (revision 629174)
+++ jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/util/NGKDbNameIndex.java (working copy)
@@ -16,11 +16,8 @@
*/
package org.apache.jackrabbit.core.persistence.bundle.util;
-import java.sql.PreparedStatement;
import java.sql.SQLException;
-import java.sql.Connection;
import java.sql.ResultSet;
-import java.sql.Statement;
/**
* Same as {@link DbNameIndex} but does not make use of the
@@ -36,23 +33,23 @@
/**
* Creates a new index that is stored in a db.
- * @param con the jdbc connection
+ * @param con the ConnectionRecoveryManager
* @param schemaObjectPrefix the prefix for table names
* @throws SQLException if the statements cannot be prepared.
*/
- public NGKDbNameIndex(Connection con, String schemaObjectPrefix)
+ public NGKDbNameIndex(ConnectionRecoveryManager conMgr, String schemaObjectPrefix)
throws SQLException {
- super(con, schemaObjectPrefix);
+ super(conMgr, schemaObjectPrefix);
}
/**
* {@inheritDoc}
*/
- protected void init(Connection con, String schemaObjectPrefix)
+ protected void init(String schemaObjectPrefix)
throws SQLException {
- nameSelect = con.prepareStatement("select NAME from " + schemaObjectPrefix + "NAMES where ID = ?");
- indexSelect = con.prepareStatement("select ID from " + schemaObjectPrefix + "NAMES where NAME = ?");
- nameInsert = con.prepareStatement("insert into " + schemaObjectPrefix + "NAMES (NAME) values (?)");
+ nameSelectSQL = "select NAME from " + schemaObjectPrefix + "NAMES where ID = ?";
+ indexSelectSQL = "select ID from " + schemaObjectPrefix + "NAMES where NAME = ?";
+ nameInsertSQL = "insert into " + schemaObjectPrefix + "NAMES (NAME) values (?)";
}
/**
@@ -66,17 +63,14 @@
*/
protected int insertString(String string) {
// assert index does not exist
- PreparedStatement stmt = nameInsert;
ResultSet rs = null;
try {
- stmt.setString(1, string);
- stmt.executeUpdate();
+ connectionManager.executeStmt(nameInsertSQL, new Object[]{string});
return getIndex(string);
} catch (Exception e) {
throw new IllegalStateException("Unable to insert index: " + e);
} finally {
closeResultSet(rs);
- resetStatement(stmt);
}
}
-}
\ No newline at end of file
+}
Index: jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/Oracle9PersistenceManager.java
===================================================================
--- jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/Oracle9PersistenceManager.java (revision 629174)
+++ jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/Oracle9PersistenceManager.java (working copy)
@@ -33,9 +33,9 @@
import java.lang.reflect.Method;
import java.sql.Blob;
import java.sql.Connection;
-import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
+import java.sql.Statement;
/**
* OracleLegacyPersistenceManager provides support for Oracle jdbc
@@ -68,8 +68,8 @@
private static Logger log = LoggerFactory.getLogger(Oracle9PersistenceManager.class);
private Class blobClass;
- private Integer DURATION_SESSION_CONSTANT;
- private Integer MODE_READWRITE_CONSTANT;
+ private Integer duractionSessionConstant;
+ private Integer modeReadWriteConstant;
public Oracle9PersistenceManager() {
}
@@ -92,10 +92,10 @@
// use the Connection object for using the exact same
// class loader that the Oracle driver was loaded with
- blobClass = con.getClass().getClassLoader().loadClass("oracle.sql.BLOB");
- DURATION_SESSION_CONSTANT =
+ blobClass = connectionManager.getConnection().getClass().getClassLoader().loadClass("oracle.sql.BLOB");
+ duractionSessionConstant =
new Integer(blobClass.getField("DURATION_SESSION").getInt(null));
- MODE_READWRITE_CONSTANT =
+ modeReadWriteConstant =
new Integer(blobClass.getField("MODE_READWRITE").getInt(null));
}
@@ -111,7 +111,6 @@
*/
protected synchronized void storeBundle(NodePropBundle bundle)
throws ItemStateException {
- PreparedStatement stmt = null;
Blob blob = null;
try {
ByteArrayOutputStream out = new ByteArrayOutputStream(INITIAL_BUFFER_SIZE);
@@ -119,21 +118,15 @@
binding.writeBundle(dout, bundle);
dout.close();
- if (bundle.isNew()) {
- stmt = bundleInsert;
- } else {
- stmt = bundleUpdate;
- }
+ String sql = bundle.isNew() ? bundleInsertSQL : bundleUpdateSQL;
blob = createTemporaryBlob(new ByteArrayInputStream(out.toByteArray()));
- stmt.setBlob(1, blob);
- stmt.setBytes(2, bundle.getId().getUUID().getRawBytes());
- stmt.execute();
+ Object[] params = createParams(bundle.getId().getUUID(), blob, true);
+ connectionManager.executeStmt(sql, params);
} catch (Exception e) {
String msg = "failed to write bundle: " + bundle.getId();
log.error(msg, e);
throw new ItemStateException(msg, e);
} finally {
- resetStatement(stmt);
if (blob != null) {
try {
freeTemporaryBlob(blob);
@@ -152,15 +145,11 @@
throw new IllegalStateException("not initialized");
}
- PreparedStatement stmt = null;
Blob blob = null;
try {
// check if insert or update
- if (exists(refs.getId())) {
- stmt = nodeReferenceUpdate;
- } else {
- stmt = nodeReferenceInsert;
- }
+ boolean update = exists(refs.getId());
+ String sql = (update) ? nodeReferenceUpdateSQL : nodeReferenceInsertSQL;
ByteArrayOutputStream out = new ByteArrayOutputStream(INITIAL_BUFFER_SIZE);
// serialize references
@@ -170,9 +159,8 @@
// not have to additionally synchronize on the preparedStatement
blob = createTemporaryBlob(new ByteArrayInputStream(out.toByteArray()));
- stmt.setBlob(1, blob);
- stmt.setBytes(2, refs.getTargetId().getUUID().getRawBytes());
- stmt.execute();
+ Object[] params = createParams(refs.getTargetId().getUUID(), blob, true);
+ connectionManager.executeStmt(sql, params);
// there's no need to close a ByteArrayOutputStream
//out.close();
@@ -181,7 +169,6 @@
log.error(msg, e);
throw new ItemStateException(msg, e);
} finally {
- resetStatement(stmt);
if (blob != null) {
try {
freeTemporaryBlob(blob);
@@ -210,9 +197,9 @@
Method createTemporary = blobClass.getMethod("createTemporary",
new Class[]{Connection.class, Boolean.TYPE, Integer.TYPE});
Object blob = createTemporary.invoke(null,
- new Object[]{con, Boolean.FALSE, DURATION_SESSION_CONSTANT});
+ new Object[]{connectionManager.getConnection(), Boolean.FALSE, duractionSessionConstant});
Method open = blobClass.getMethod("open", new Class[]{Integer.TYPE});
- open.invoke(blob, new Object[]{MODE_READWRITE_CONSTANT});
+ open.invoke(blob, new Object[]{modeReadWriteConstant});
Method getBinaryOutputStream = blobClass.getMethod("getBinaryOutputStream", new Class[0]);
OutputStream out = (OutputStream) getBinaryOutputStream.invoke(blob, null);
try {
@@ -253,29 +240,23 @@
*/
public synchronized void put(String blobId, InputStream in, long size)
throws Exception {
- PreparedStatement stmt = blobSelectExist;
+
Blob blob = null;
try {
- stmt.setString(1, blobId);
- stmt.execute();
+ Statement stmt = connectionManager.executeStmt(blobSelectExistSQL, new Object[]{blobId});
ResultSet rs = stmt.getResultSet();
// a BLOB exists if the result has at least one entry
boolean exists = rs.next();
- resetStatement(stmt);
closeResultSet(rs);
- stmt = (exists) ? blobUpdate : blobInsert;
-
+ String sql = (exists) ? blobUpdateSQL : blobInsertSQL;
blob = createTemporaryBlob(in);
- stmt.setBlob(1, blob);
- stmt.setString(2, blobId);
- stmt.executeUpdate();
+ connectionManager.executeStmt(sql, new Object[]{blob, blobId});
} finally {
- resetStatement(stmt);
if (blob != null) {
try {
freeTemporaryBlob(blob);
- } catch (Exception e1) {
+ } catch (Exception e) {
}
}
}