mirror of https://github.com/apache/lucene.git
LUCENE-6745: RAMInputStream.clone was not thread safe (Mike McCandless)
git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/trunk@1696798 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
fd33cfdc03
commit
be9471debb
|
@ -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.
|
||||
|
|
|
@ -116,7 +116,7 @@ public class RAMInputStream extends IndexInput implements Cloneable {
|
|||
|
||||
@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 IndexInput implements Cloneable {
|
|||
}
|
||||
};
|
||||
}
|
||||
|
||||
@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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1167,5 +1167,59 @@ public abstract class BaseDirectoryTestCase extends LuceneTestCase {
|
|||
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();
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue