You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by th...@apache.org on 2008/04/18 14:27:52 UTC
svn commit: r649493 - in /jackrabbit/trunk/jackrabbit-core/src:
main/java/org/apache/jackrabbit/core/data/
main/java/org/apache/jackrabbit/core/data/db/
test/java/org/apache/jackrabbit/core/data/
Author: thomasm
Date: Fri Apr 18 05:27:48 2008
New Revision: 649493
URL: http://svn.apache.org/viewvc?rev=649493&view=rev
Log:
JCR-1388 Allow concurrent reads from the database data store
Added:
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/db/DatabaseHelper.java (with props)
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/db/DbInputStream.java (with props)
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/db/DbResources.java (with props)
jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/data/TestTwoGetStreams.java (with props)
Modified:
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/DataRecord.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/FileDataRecord.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/db/DbDataRecord.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/db/DbDataStore.java
jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/data/TestAll.java
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/DataRecord.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/DataRecord.java?rev=649493&r1=649492&r2=649493&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/DataRecord.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/DataRecord.java Fri Apr 18 05:27:48 2008
@@ -46,4 +46,10 @@
*/
InputStream getStream() throws DataStoreException;
+ /**
+ * Returns the last modified of the record.
+ *
+ * @return last modified time of the binary stream
+ */
+ long getLastModified();
}
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/FileDataRecord.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/FileDataRecord.java?rev=649493&r1=649492&r2=649493&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/FileDataRecord.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/FileDataRecord.java Fri Apr 18 05:27:48 2008
@@ -37,7 +37,7 @@
* @param identifier data identifier
* @param file file that contains the binary stream
*/
- protected FileDataRecord(DataIdentifier identifier, File file) {
+ public FileDataRecord(DataIdentifier identifier, File file) {
super(identifier);
assert file.isFile();
this.file = file;
@@ -61,4 +61,10 @@
}
}
+ /**
+ * {@inheritDoc}
+ */
+ public long getLastModified() {
+ return file.lastModified();
+ }
}
Added: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/db/DatabaseHelper.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/db/DatabaseHelper.java?rev=649493&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/db/DatabaseHelper.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/db/DatabaseHelper.java Fri Apr 18 05:27:48 2008
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.core.data.db;
+
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Helper methods for database operations.
+ */
+public class DatabaseHelper {
+
+ private static Logger log = LoggerFactory.getLogger(DatabaseHelper.class);
+
+ /**
+ * Silently closes a connection.
+ */
+ public static void closeSilently(Connection con) {
+ try {
+ if (con != null) {
+ con.close();
+ }
+ } catch (SQLException e) {
+ log.info("Couldn't close connection: ", e);
+ }
+ }
+
+ /**
+ * Silently closes a result set.
+ */
+ public static void closeSilently(ResultSet rs) {
+ try {
+ if (rs != null) {
+ rs.close();
+ }
+ } catch (SQLException e) {
+ log.info("Couldn't close result set: ", e);
+ }
+ }
+
+ /**
+ * Silently closes a statement.
+ */
+ public static void closeSilently(Statement stmt) {
+ try {
+ if (stmt != null) {
+ stmt.close();
+ }
+ } catch (SQLException e) {
+ log.info("Couldn't close statement: ", e);
+ }
+ }
+}
Propchange: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/db/DatabaseHelper.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/db/DatabaseHelper.java
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision Rev URL
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/db/DbDataRecord.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/db/DbDataRecord.java?rev=649493&r1=649492&r2=649493&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/db/DbDataRecord.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/db/DbDataRecord.java Fri Apr 18 05:27:48 2008
@@ -33,7 +33,7 @@
/**
* Creates a data record based on the given identifier and length.
- *
+ *
* @param identifier data identifier
* @param length the length
* @param file file that contains the binary stream
@@ -58,7 +58,13 @@
*/
public InputStream getStream() throws DataStoreException {
lastModified = store.touch(getIdentifier(), lastModified);
- return store.getInputStream(getIdentifier());
+ return new DbInputStream(store, getIdentifier());
}
+ /**
+ * {@inheritDoc}
+ */
+ public long getLastModified() {
+ return lastModified;
+ }
}
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/db/DbDataStore.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/db/DbDataStore.java?rev=649493&r1=649492&r2=649493&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/db/DbDataStore.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/db/DbDataStore.java Fri Apr 18 05:27:48 2008
@@ -29,6 +29,7 @@
import org.slf4j.LoggerFactory;
import java.io.BufferedInputStream;
+import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
@@ -487,6 +488,51 @@
}
/**
+ * getDatabaseResources() does NOT close the DB resources on success. It's up to the client of
+ * the stream backed by these resources to close it and therefore close the DB resources.
+ *
+ * @param identifier data identifier
+ * @return database resources that will back the stream corresponding
+ * to the passed data identifier
+ * @throws DataStoreException if the data store could not be accessed,
+ * or if the given identifier is invalid
+ */
+ public DbResources getDatabaseResources(DataIdentifier identifier) throws DataStoreException {
+ ConnectionRecoveryManager conn = null;
+ ResultSet rs = null;
+ try {
+ conn = getConnection();
+ // SELECT ID, DATA FROM DATASTORE WHERE ID = ?
+ PreparedStatement prep = conn.executeStmt(selectDataSQL, new Object[]{identifier.toString()});
+ rs = prep.getResultSet();
+ if (!rs.next()) {
+ throw new DataStoreException("Record not found: " + identifier);
+ }
+ InputStream result = null;
+ InputStream stream = rs.getBinaryStream(2);
+ if (stream == null) {
+ // If the stream is null, go ahead and close resources
+ result = new ByteArrayInputStream(new byte[0]);
+ DatabaseHelper.closeSilently(rs);
+ putBack(conn);
+ } else {
+ result = new BufferedInputStream(stream);
+ if (copyWhenReading) {
+ File temp = moveToTempFile(result);
+ result = new TempFileInputStream(temp);
+ }
+ }
+
+ DbResources dbResources = new DbResources(conn, rs, prep, result, this);
+ return dbResources;
+ } catch (Exception e) {
+ DatabaseHelper.closeSilently(rs);
+ putBack(conn);
+ throw convert("Retrieving database resources ", e);
+ }
+ }
+
+ /**
* {@inheritDoc}
*/
public synchronized void init(String homeDir) throws DataStoreException {
@@ -643,32 +689,6 @@
}
}
return lastModified;
- }
-
- /**
- * {@inheritDoc}
- */
- public InputStream getInputStream(DataIdentifier identifier) throws DataStoreException {
- ConnectionRecoveryManager conn = getConnection();
- try {
- String id = identifier.toString();
- // SELECT ID, DATA FROM DATASTORE WHERE ID = ?
- PreparedStatement prep = conn.executeStmt(selectDataSQL, new Object[]{id});
- ResultSet rs = prep.getResultSet();
- if (!rs.next()) {
- throw new DataStoreException("Record not found: " + identifier);
- }
- InputStream in = new BufferedInputStream(rs.getBinaryStream(2));
- if (copyWhenReading) {
- File temp = moveToTempFile(in);
- in = new TempFileInputStream(temp);
- }
- return in;
- } catch (Exception e) {
- throw convert("Can not read identifier " + identifier, e);
- } finally {
- putBack(conn);
- }
}
/**
Added: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/db/DbInputStream.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/db/DbInputStream.java?rev=649493&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/db/DbInputStream.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/db/DbInputStream.java Fri Apr 18 05:27:48 2008
@@ -0,0 +1,197 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.core.data.db;
+
+import java.io.FilterInputStream;
+import java.io.IOException;
+import org.apache.jackrabbit.core.data.DataIdentifier;
+import org.apache.jackrabbit.core.data.DataStoreException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * This class represents an input stream backed by a database. It allows the stream to be used by
+ * keeping the DB resources open until the stream is closed. When the stream is finished or
+ * close()d, then the resources are freed.
+ */
+public class DbInputStream extends FilterInputStream {
+
+ private static Logger log = LoggerFactory.getLogger(DbInputStream.class);
+
+ protected DbResources resources;
+ protected boolean streamFinished;
+ protected boolean streamClosed;
+ protected DbDataStore store;
+ protected DataIdentifier identifier;
+
+ /**
+ * @param in the stream obtained by a call to ResultSet.getBinaryStream().
+ * @param con the connection to the DB. It must not be closed.
+ * @param rs the result set from wich the stream is obtained. It must not be closed.
+ * @param stmt the statemen that produced the result set. It must not be closed.
+ */
+ protected DbInputStream(DbDataStore store, DataIdentifier identifier) {
+ super(null);
+ streamFinished = false;
+ streamClosed = true;
+ this.store = store;
+ this.identifier = identifier;
+ }
+
+ private void getStream() throws IOException {
+ try {
+ resources = store.getDatabaseResources(identifier);
+ in = resources.getInputStream();
+ streamClosed = false;
+ } catch (DataStoreException e) {
+ IOException e2 = new IOException(e.getMessage());
+ e2.initCause(e);
+ throw e2;
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ * When the stream is consumed, the database resources held by the instance are closed.
+ */
+ public int read() throws IOException {
+ if (streamFinished) {
+ return -1;
+ }
+ if (in == null) {
+ getStream();
+ }
+ int c = in.read();
+ if (c == -1) {
+ streamFinished = true;
+ close();
+ }
+ return c;
+ }
+
+ /**
+ * {@inheritDoc}
+ * When the stream is consumed, the database resources held by the instance are closed.
+ */
+ public int read(byte[] b) throws IOException {
+ if (streamFinished) {
+ return -1;
+ }
+ int c = read(b, 0, b.length);
+ if (c == -1) {
+ streamFinished = true;
+ close();
+ }
+ return c;
+ }
+
+ /**
+ * {@inheritDoc}
+ * When the stream is consumed, the database resources held by the instance are closed.
+ */
+ public int read(byte[] b, int off, int len) throws IOException {
+ if (streamFinished) {
+ return -1;
+ }
+ if (in == null) {
+ getStream();
+ }
+ int c = in.read(b, off, len);
+ if (c == -1) {
+ streamFinished = true;
+ close();
+ }
+ return c;
+ }
+
+ /**
+ * {@inheritDoc}
+ * When the stream is consumed, the database resources held by the instance are closed.
+ */
+ public void close() throws IOException {
+ if (!streamClosed) {
+ streamClosed = true;
+ // It may be null (see constructor)
+ if (in != null) {
+ super.close();
+ }
+ // resources may be null (if getStream() was not called)
+ if (resources != null) {
+ resources.close();
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public long skip(long n) throws IOException {
+ if (in == null) {
+ getStream();
+ }
+ return in.skip(n);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int available() throws IOException {
+ if (in == null) {
+ getStream();
+ }
+ return in.available();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void mark(int readlimit) {
+ if (in == null) {
+ try {
+ getStream();
+ } catch (IOException e) {
+ log.info("Error getting underlying stream: ", e);
+ }
+ }
+ in.mark(readlimit);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void reset() throws IOException {
+ if (in == null) {
+ getStream();
+ }
+ in.reset();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean markSupported() {
+ if (in == null) {
+ try {
+ getStream();
+ } catch (IOException e) {
+ log.info("Error getting underlying stream: ", e);
+ return false;
+ }
+ }
+ return in.markSupported();
+ }
+}
Propchange: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/db/DbInputStream.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/db/DbInputStream.java
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision Rev URL
Added: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/db/DbResources.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/db/DbResources.java?rev=649493&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/db/DbResources.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/db/DbResources.java Fri Apr 18 05:27:48 2008
@@ -0,0 +1,77 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.core.data.db;
+
+import java.io.InputStream;
+import java.sql.ResultSet;
+import java.sql.Statement;
+
+import org.apache.jackrabbit.core.persistence.bundle.util.ConnectionRecoveryManager;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Represents the resources used to back a database-based input stream.
+ */
+public class DbResources {
+
+ private static Logger log = LoggerFactory.getLogger(DbResources.class);
+
+ protected final ConnectionRecoveryManager conn;
+ protected final ResultSet rs;
+ protected final Statement stmt;
+ protected final InputStream in;
+ protected final DbDataStore store;
+ protected boolean closed;
+
+ public DbResources(ConnectionRecoveryManager conn, ResultSet rs, Statement stmt, InputStream in, DbDataStore store) {
+ this.conn = conn;
+ this.rs = rs;
+ this.stmt = stmt;
+ this.in = in;
+ this.store = store;
+ this.closed = false;
+ }
+
+ public ConnectionRecoveryManager getConnection() {
+ return conn;
+ }
+
+ public InputStream getInputStream() {
+ return in;
+ }
+
+ public ResultSet getResultSet() {
+ return rs;
+ }
+
+ public Statement getStatement() {
+ return stmt;
+ }
+
+ public void close() {
+ if (!closed) {
+ closed = true;
+ DatabaseHelper.closeSilently(rs);
+ try {
+ store.putBack(conn);
+ } catch (Exception e) {
+ log.info("Closing DbResources: ", e);
+ }
+ }
+ }
+}
Propchange: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/db/DbResources.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/db/DbResources.java
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision Rev URL
Modified: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/data/TestAll.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/data/TestAll.java?rev=649493&r1=649492&r2=649493&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/data/TestAll.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/data/TestAll.java Fri Apr 18 05:27:48 2008
@@ -39,6 +39,7 @@
suite.addTestSuite(GCEventListenerTest.class);
suite.addTestSuite(PersistenceManagerIteratorTest.class);
suite.addTestSuite(CopyValueTest.class);
+ suite.addTestSuite(TestTwoGetStreams.class);
return suite;
}
Added: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/data/TestTwoGetStreams.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/data/TestTwoGetStreams.java?rev=649493&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/data/TestTwoGetStreams.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/data/TestTwoGetStreams.java Fri Apr 18 05:27:48 2008
@@ -0,0 +1,131 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.core.data;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import javax.jcr.Node;
+import javax.jcr.Session;
+
+import org.apache.jackrabbit.test.AbstractJCRTest;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Test concurrent reads to the data store.
+ */
+public class TestTwoGetStreams extends AbstractJCRTest {
+
+ private static Logger log = LoggerFactory.getLogger(TestTwoGetStreams.class);
+
+ private static final int STREAM_LENGTH = 1 * 1024 * 1024;
+
+ /**
+ * Test reading from two concurrently opened streams.
+ */
+ public void testTwoGetStreams() throws Exception {
+ Session session = helper.getSuperuserSession();
+ Node root = session.getRootNode();
+ root.setProperty("p1", new RandomInputStream(1, STREAM_LENGTH));
+ root.setProperty("p2", new RandomInputStream(2, STREAM_LENGTH));
+ session.save();
+
+ InputStream i1 = root.getProperty("p1").getStream();
+ InputStream i2 = root.getProperty("p2").getStream();
+ assertEquals("p1", i1, new RandomInputStream(1, STREAM_LENGTH));
+ assertEquals("p2", i2, new RandomInputStream(2, STREAM_LENGTH));
+ try {
+ i1.close();
+ } catch (IOException e) {
+ log.info("Could not close first input stream: ", e);
+ }
+ try {
+ i2.close();
+ } catch (IOException e) {
+ log.info("Could not close second input stream: ", e);
+ }
+ }
+
+ /**
+ * Tests reading concurrently from two different streams.
+ */
+ public void testTwoStreamsConcurrently() throws Exception {
+ Session session = helper.getSuperuserSession();
+ Node root = session.getRootNode();
+ root.setProperty("p1", new RandomInputStream(1, STREAM_LENGTH));
+ root.setProperty("p2", new RandomInputStream(1, STREAM_LENGTH));
+ session.save();
+
+ InputStream i1 = root.getProperty("p1").getStream();
+ InputStream i2 = root.getProperty("p2").getStream();
+ assertEquals("Streams are different", i1, i2);
+ try {
+ i1.close();
+ } catch (IOException e) {
+ log.info("Could not close first input stream: ", e);
+ }
+ try {
+ i2.close();
+ } catch (IOException e) {
+ log.info("Could not close second input stream: ", e);
+ }
+ }
+
+ /**
+ * Tests reading concurrently from two different streams coming from the
+ * same property.
+ */
+ public void testTwoStreamsFromSamePropertyConcurrently() throws Exception {
+ Session session = helper.getSuperuserSession();
+ Node root = session.getRootNode();
+ root.setProperty("p1", new RandomInputStream(1, STREAM_LENGTH));
+ session.save();
+
+ InputStream i1 = root.getProperty("p1").getStream();
+ InputStream i2 = root.getProperty("p1").getStream();
+ assertEquals("Streams are different", i1, i2);
+ try {
+ i1.close();
+ } catch (IOException e) {
+ log.info("Could not close first input stream: ", e);
+ }
+ try {
+ i2.close();
+ } catch (IOException e) {
+ log.info("Could not close second input stream: ", e);
+ }
+ }
+
+ /**
+ * Asserts that two input streams are equal.
+ */
+ protected void assertEquals(String message, InputStream i1, InputStream i2) {
+ try {
+ int b1 = 0, b2 = 0;
+ int i = 0;
+ while (b1 != -1 || b2 != -1) {
+ b1 = i1.read();
+ b2 = i2.read();
+ assertEquals(message + "; byte #" + i + " mismatch!", b2, b1);
+ ++i;
+ }
+ } catch (Exception e) {
+ fail("Could not read inputstream! " + e);
+ }
+ }
+}
Propchange: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/data/TestTwoGetStreams.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/data/TestTwoGetStreams.java
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision Rev URL