You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by mi...@apache.org on 2015/08/20 16:39:31 UTC
svn commit: r1696798 - in /lucene/dev/trunk/lucene: CHANGES.txt
core/src/java/org/apache/lucene/store/RAMInputStream.java
test-framework/src/java/org/apache/lucene/store/BaseDirectoryTestCase.java
Author: mikemccand
Date: Thu Aug 20 14:39:30 2015
New Revision: 1696798
URL: http://svn.apache.org/r1696798
Log:
LUCENE-6745: RAMInputStream.clone was not thread safe (Mike McCandless)
Modified:
lucene/dev/trunk/lucene/CHANGES.txt
lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/store/RAMInputStream.java
lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/store/BaseDirectoryTestCase.java
Modified: lucene/dev/trunk/lucene/CHANGES.txt
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/CHANGES.txt?rev=1696798&r1=1696797&r2=1696798&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/CHANGES.txt (original)
+++ lucene/dev/trunk/lucene/CHANGES.txt Thu Aug 20 14:39:30 2015
@@ -79,6 +79,8 @@ Bug Fixes
test data. In addition, the performance of those filters was improved
significantly. (Uwe Schindler, Robert Muir)
+* LUCENE-6745: RAMInputStream.clone was not thread safe (Mike McCandless)
+
Other
* LUCENE-6174: Improve "ant eclipse" to select right JRE for building.
Modified: lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/store/RAMInputStream.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/store/RAMInputStream.java?rev=1696798&r1=1696797&r2=1696798&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/store/RAMInputStream.java (original)
+++ lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/store/RAMInputStream.java Thu Aug 20 14:39:30 2015
@@ -116,7 +116,7 @@ public class RAMInputStream extends Inde
@Override
public void seek(long pos) throws IOException {
- if (currentBuffer==null || pos < bufferStart || pos >= bufferStart + BUFFER_SIZE) {
+ if (currentBuffer == null || pos < bufferStart || pos >= bufferStart + BUFFER_SIZE) {
currentBufferIndex = (int) (pos / BUFFER_SIZE);
switchCurrentBuffer(false);
}
@@ -157,4 +157,19 @@ public class RAMInputStream extends Inde
}
};
}
+
+ @Override
+ public RAMInputStream clone() {
+ RAMInputStream clone = (RAMInputStream) super.clone();
+ // If another thread was using our instance, this new clone could have a mismatched currentBuffer and currentBufferIndex, so we do
+ // a "fresh seek" here:
+ clone.currentBuffer = null;
+ try {
+ clone.seek(getFilePointer());
+ } catch (IOException ioe) {
+ // Should not happen!
+ throw new AssertionError(ioe);
+ }
+ return clone;
+ }
}
Modified: lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/store/BaseDirectoryTestCase.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/store/BaseDirectoryTestCase.java?rev=1696798&r1=1696797&r2=1696798&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/store/BaseDirectoryTestCase.java (original)
+++ lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/store/BaseDirectoryTestCase.java Thu Aug 20 14:39:30 2015
@@ -1167,5 +1167,59 @@ public abstract class BaseDirectoryTestC
in.close(); // close again
dir.close();
}
-}
+ public void testCloneThreadSafety() throws Exception {
+ Directory dir = getDirectory(createTempDir());
+ IndexOutput out = dir.createOutput("randombytes", IOContext.DEFAULT);
+
+ // Write file with at least 20 K random bytes:
+ final int numBytes = atLeast(20*1024);
+ final byte[] bytes = new byte[numBytes];
+ random().nextBytes(bytes);
+ out.writeBytes(bytes, 0, bytes.length);
+ out.close();
+
+ // Then read the bytes back at random seek points from multiple threads:
+ final IndexInput in = dir.openInput("randombytes", IOContext.DEFAULT);
+
+ int numThreads = 4;
+ Thread[] threads = new Thread[numThreads];
+ for(int i=0;i<numThreads;i++) {
+ int finalI = i;
+ threads[i] = new Thread() {
+ @Override
+ public void run() {
+ int numIters = atLeast(1000);
+ byte[] scratch = new byte[numBytes];
+ for(int iter=0;iter<numIters;iter++) {
+ // First thread uses the original IndexInput, all other threads use clone:
+ IndexInput myIn;
+ if (finalI == 0) {
+ myIn = in;
+ } else {
+ myIn = in.clone();
+ }
+ int spot = random().nextInt(numBytes/2);
+ try {
+ myIn.seek(spot);
+ int length = numBytes-spot;
+ myIn.readBytes(scratch, 0, length);
+ for(int i=0;i<length;i++) {
+ assertEquals(bytes[spot+i], scratch[i]);
+ }
+ } catch (IOException ioe) {
+ throw new RuntimeException(ioe);
+ }
+ }
+ }
+ };
+ threads[i].start();
+ }
+
+ for(Thread thread : threads) {
+ thread.join();
+ }
+ in.close();
+ dir.close();
+ }
+}