You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by ju...@apache.org on 2012/08/03 11:48:55 UTC
svn commit: r1368852 - in /jackrabbit/branches/2.4: ./
jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/db/
jackrabbit-core/src/main/java/org/apache/jackrabbit/core/util/db/
jackrabbit-core/src/test/java/org/apache/jackrabbit/core/data/
Author: jukka
Date: Fri Aug 3 09:48:54 2012
New Revision: 1368852
URL: http://svn.apache.org/viewvc?rev=1368852&view=rev
Log:
2.4: Merged revisions 1349185 and 1358543 (JCR-3318 and JCR-3377)
Modified:
jackrabbit/branches/2.4/ (props changed)
jackrabbit/branches/2.4/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/db/DbDataStore.java
jackrabbit/branches/2.4/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/db/TempFileInputStream.java
jackrabbit/branches/2.4/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/util/db/ConnectionHelper.java
jackrabbit/branches/2.4/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/util/db/DbUtility.java
jackrabbit/branches/2.4/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/util/db/StreamWrapper.java
jackrabbit/branches/2.4/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/data/TempFileInputStreamTest.java
Propchange: jackrabbit/branches/2.4/
------------------------------------------------------------------------------
Merged /jackrabbit/trunk:r1349185,1358543
Modified: jackrabbit/branches/2.4/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/db/DbDataStore.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.4/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/db/DbDataStore.java?rev=1368852&r1=1368851&r2=1368852&view=diff
==============================================================================
--- jackrabbit/branches/2.4/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/db/DbDataStore.java (original)
+++ jackrabbit/branches/2.4/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/db/DbDataStore.java Fri Aug 3 09:48:54 2012
@@ -346,9 +346,8 @@ public class DbDataStore implements Data
wrapper = new StreamWrapper(in, Integer.MAX_VALUE);
} else if (STORE_TEMP_FILE.equals(storeStream)) {
File temp = moveToTempFile(in);
- fileInput = new BufferedInputStream(new TempFileInputStream(temp));
long length = temp.length();
- wrapper = new StreamWrapper(fileInput, length);
+ wrapper = new StreamWrapper(new TempFileInputStream(temp, true), length);
} else {
throw new DataStoreException("Unsupported stream store algorithm: " + storeStream);
}
@@ -579,7 +578,7 @@ public class DbDataStore implements Data
} else if (copyWhenReading) {
// If we copy while reading, create a temp file and close the stream
File temp = moveToTempFile(stream);
- stream = new BufferedInputStream(new TempFileInputStream(temp));
+ stream = new BufferedInputStream(new TempFileInputStream(temp, false));
DbUtility.close(rs);
} else {
stream = new BufferedInputStream(stream);
Modified: jackrabbit/branches/2.4/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/db/TempFileInputStream.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.4/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/db/TempFileInputStream.java?rev=1368852&r1=1368851&r2=1368852&view=diff
==============================================================================
--- jackrabbit/branches/2.4/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/db/TempFileInputStream.java (original)
+++ jackrabbit/branches/2.4/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/db/TempFileInputStream.java Fri Aug 3 09:48:54 2012
@@ -39,6 +39,7 @@ public class TempFileInputStream extends
private final File file;
private boolean closed;
+ private boolean delayedResourceCleanup = true;
/**
* Copy the data to a file and close the input stream afterwards.
@@ -57,17 +58,28 @@ public class TempFileInputStream extends
/**
* Construct a new temporary file input stream.
- * The file is deleted if the input stream is closed or fully read.
+ * The file is deleted if the input stream is closed or fully read and
+ * delayedResourceCleanup was set to true. Otherwise you must call {@link #deleteFile()}.
* Deleting is only attempted once.
*
* @param file the temporary file
+ * @param delayedResourceCleanup
*/
- public TempFileInputStream(File file) throws FileNotFoundException {
+ public TempFileInputStream(File file, boolean delayedResourceCleanup) throws FileNotFoundException {
super(new BufferedInputStream(new FileInputStream(file)));
this.file = file;
+ this.delayedResourceCleanup = delayedResourceCleanup;
}
- private int closeIfEOF(int read) throws IOException {
+ public File getFile() {
+ return file;
+ }
+
+ public void deleteFile() {
+ file.delete();
+ }
+
+ private int closeIfEOF(int read) throws IOException {
if (read < 0) {
close();
}
@@ -77,7 +89,9 @@ public class TempFileInputStream extends
public void close() throws IOException {
if (!closed) {
in.close();
- file.delete();
+ if (!delayedResourceCleanup) {
+ deleteFile();
+ }
closed = true;
}
}
Modified: jackrabbit/branches/2.4/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/util/db/ConnectionHelper.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.4/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/util/db/ConnectionHelper.java?rev=1368852&r1=1368851&r2=1368852&view=diff
==============================================================================
--- jackrabbit/branches/2.4/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/util/db/ConnectionHelper.java (original)
+++ jackrabbit/branches/2.4/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/util/db/ConnectionHelper.java Fri Aug 3 09:48:54 2012
@@ -278,7 +278,7 @@ public class ConnectionHelper {
* @throws SQLException on error
*/
public final void exec(final String sql, final Object... params) throws SQLException {
- new RetryManager<Void>() {
+ new RetryManager<Void>(params) {
@Override
protected Void call() throws SQLException {
@@ -316,7 +316,7 @@ public class ConnectionHelper {
* @throws SQLException on error
*/
public final int update(final String sql, final Object... params) throws SQLException {
- return new RetryManager<Integer>() {
+ return new RetryManager<Integer>(params) {
@Override
protected Integer call() throws SQLException {
@@ -363,11 +363,11 @@ public class ConnectionHelper {
*/
public final ResultSet exec(final String sql, final Object[] params, final boolean returnGeneratedKeys,
final int maxRows) throws SQLException {
- return new RetryManager<ResultSet>() {
+ return new RetryManager<ResultSet>(params) {
@Override
protected ResultSet call() throws SQLException {
- return reallyExec(sql, params, returnGeneratedKeys, maxRows);
+ return reallyExec(sql, params, returnGeneratedKeys, maxRows);
}
}.doTry();
@@ -463,7 +463,6 @@ public class ConnectionHelper {
protected PreparedStatement execute(PreparedStatement stmt, Object[] params) throws SQLException {
for (int i = 0; params != null && i < params.length; i++) {
Object p = params[i];
- // FIXME: what about already consumed input streams when in a retry?
if (p instanceof StreamWrapper) {
StreamWrapper wrapper = (StreamWrapper) p;
stmt.setBinaryStream(i + 1, wrapper.getStream(), (int) wrapper.getSize());
@@ -471,17 +470,39 @@ public class ConnectionHelper {
stmt.setObject(i + 1, p);
}
}
- stmt.execute();
+ try {
+ stmt.execute();
+ } catch (SQLException e) {
+ //Reset Stream for retry ...
+ for (int i = 0; params != null && i < params.length; i++) {
+ Object p = params[i];
+ if (p instanceof StreamWrapper) {
+ StreamWrapper wrapper = (StreamWrapper) p;
+ if(!wrapper.resetStream()) {
+ wrapper.cleanupResources();
+ throw new RuntimeException("Unable to reset the Stream.");
+ }
+ }
+ }
+ throw e;
+ }
return stmt;
}
/**
* This class encapsulates the logic to retry a method invocation if it threw an SQLException.
+ * The RetryManager must cleanup the Params it will get.
*
* @param <T> the return type of the method which is retried if it failed
*/
public abstract class RetryManager<T> {
+ private Object[] params;
+
+ public RetryManager(Object[] params) {
+ this.params = params;
+ }
+
public final T doTry() throws SQLException {
if (inBatchMode()) {
return call();
@@ -491,7 +512,9 @@ public class ConnectionHelper {
SQLException lastException = null;
while (!sleepInterrupted && (blockOnConnectionLoss || failures <= RETRIES)) {
try {
- return call();
+ T object = call();
+ cleanupParamResources();
+ return object;
} catch (SQLException e) {
lastException = e;
}
@@ -508,10 +531,26 @@ public class ConnectionHelper {
}
}
}
+ cleanupParamResources();
throw lastException;
}
}
protected abstract T call() throws SQLException;
+
+ /**
+ * Cleans up the Parameter resources that are not automatically closed or deleted.
+ *
+ * @param params
+ */
+ protected void cleanupParamResources() {
+ for (int i = 0; params != null && i < params.length; i++) {
+ Object p = params[i];
+ if (p instanceof StreamWrapper) {
+ StreamWrapper wrapper = (StreamWrapper) p;
+ wrapper.cleanupResources();
+ }
+ }
+ }
}
}
Modified: jackrabbit/branches/2.4/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/util/db/DbUtility.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.4/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/util/db/DbUtility.java?rev=1368852&r1=1368851&r2=1368852&view=diff
==============================================================================
--- jackrabbit/branches/2.4/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/util/db/DbUtility.java (original)
+++ jackrabbit/branches/2.4/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/util/db/DbUtility.java Fri Aug 3 09:48:54 2012
@@ -71,7 +71,7 @@ public final class DbUtility {
logException("failed to close Statement", e);
} finally {
try {
- if (con != null) {
+ if (con != null && !con.isClosed()) {
con.close();
}
} catch (SQLException e) {
Modified: jackrabbit/branches/2.4/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/util/db/StreamWrapper.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.4/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/util/db/StreamWrapper.java?rev=1368852&r1=1368851&r2=1368852&view=diff
==============================================================================
--- jackrabbit/branches/2.4/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/util/db/StreamWrapper.java (original)
+++ jackrabbit/branches/2.4/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/util/db/StreamWrapper.java Fri Aug 3 09:48:54 2012
@@ -16,11 +16,20 @@
*/
package org.apache.jackrabbit.core.util.db;
+import java.io.BufferedInputStream;
+import java.io.IOException;
import java.io.InputStream;
+import java.sql.SQLException;
+
+import org.apache.jackrabbit.core.data.db.TempFileInputStream;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
public class StreamWrapper {
- private final InputStream stream;
+ static Logger log = LoggerFactory.getLogger(StreamWrapper.class);
+
+ private InputStream stream;
private final long size;
/**
@@ -28,7 +37,8 @@ public class StreamWrapper {
* safely be passed as a parameter to the {@link ConnectionHelper#exec(String, Object...)},
* {@link ConnectionHelper#exec(String, Object[], boolean, int)} and
* {@link ConnectionHelper#update(String, Object[])} methods.
- *
+ * If the wrapped Stream is a {@link TempFileInputStream} it will be wrapped again by a {@link BufferedInputStream}.
+ *
* @param in the InputStream to wrap
* @param size the size of the input stream
*/
@@ -38,10 +48,49 @@ public class StreamWrapper {
}
public InputStream getStream() {
+ if (stream instanceof TempFileInputStream) {
+ return new BufferedInputStream(stream);
+ }
return stream;
}
public long getSize() {
return size;
}
+
+ /**
+ * Cleans up the internal Resources
+ */
+ public void cleanupResources() {
+ if (stream instanceof TempFileInputStream) {
+ try {
+ stream.close();
+ ((TempFileInputStream) stream).deleteFile();
+ } catch (IOException e) {
+ log.warn("Unable to cleanup the TempFileInputStream");
+ }
+ }
+ }
+
+ /**
+ * Resets the internal InputStream that it could be re-read.<br>
+ * Is used from {@link RetryManager} if a {@link SQLException} has occurred.<br>
+ * At the moment only a {@link TempFileInputStream} can be reseted.
+ *
+ * @return returns true if it was able to reset the Stream
+ */
+ public boolean resetStream() {
+ if (stream instanceof TempFileInputStream) {
+ try {
+ TempFileInputStream tempFileInputStream = (TempFileInputStream) stream;
+ // Close it if it is not already closed ...
+ tempFileInputStream.close();
+ stream = new TempFileInputStream(tempFileInputStream.getFile(), true);
+ return true;
+ } catch (Exception e) {
+ log.warn("Failed to create a new TempFileInputStream", e);
+ }
+ }
+ return false;
+ }
}
Modified: jackrabbit/branches/2.4/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/data/TempFileInputStreamTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.4/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/data/TempFileInputStreamTest.java?rev=1368852&r1=1368851&r2=1368852&view=diff
==============================================================================
--- jackrabbit/branches/2.4/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/data/TempFileInputStreamTest.java (original)
+++ jackrabbit/branches/2.4/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/data/TempFileInputStreamTest.java Fri Aug 3 09:48:54 2012
@@ -33,7 +33,7 @@ public class TempFileInputStreamTest ext
public void testReadPastEOF() throws IOException {
File temp = File.createTempFile("test", null);
TempFileInputStream.writeToFileAndClose(new ByteArrayInputStream(new byte[1]), temp);
- TempFileInputStream in = new TempFileInputStream(temp);
+ TempFileInputStream in = new TempFileInputStream(temp, false);
assertEquals(0, in.read());
assertEquals(-1, in.read());
assertEquals(-1, in.read());
@@ -44,7 +44,7 @@ public class TempFileInputStreamTest ext
public void testMarkReset() throws IOException {
File temp = File.createTempFile("test", null);
TempFileInputStream.writeToFileAndClose(new ByteArrayInputStream(new byte[10]), temp);
- InputStream in = new BufferedInputStream(new TempFileInputStream(temp));
+ InputStream in = new BufferedInputStream(new TempFileInputStream(temp, false));
in.mark(100);
for (int i = 0; i < 10; i++) {
assertEquals(0, in.read());