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:44:28 UTC

svn commit: r1696802 - in /lucene/dev/branches/branch_5x: ./ lucene/ lucene/core/ lucene/core/src/java/org/apache/lucene/store/ lucene/test-framework/ lucene/test-framework/src/java/org/apache/lucene/store/

Author: mikemccand
Date: Thu Aug 20 14:44:28 2015
New Revision: 1696802

URL: http://svn.apache.org/r1696802
Log:
LUCENE-6745: RAMInputStream.clone was not thread safe (Mike McCandless)

Modified:
    lucene/dev/branches/branch_5x/   (props changed)
    lucene/dev/branches/branch_5x/lucene/   (props changed)
    lucene/dev/branches/branch_5x/lucene/CHANGES.txt   (contents, props changed)
    lucene/dev/branches/branch_5x/lucene/core/   (props changed)
    lucene/dev/branches/branch_5x/lucene/core/src/java/org/apache/lucene/store/RAMInputStream.java
    lucene/dev/branches/branch_5x/lucene/test-framework/   (props changed)
    lucene/dev/branches/branch_5x/lucene/test-framework/src/java/org/apache/lucene/store/BaseDirectoryTestCase.java

Modified: lucene/dev/branches/branch_5x/lucene/CHANGES.txt
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_5x/lucene/CHANGES.txt?rev=1696802&r1=1696801&r2=1696802&view=diff
==============================================================================
--- lucene/dev/branches/branch_5x/lucene/CHANGES.txt (original)
+++ lucene/dev/branches/branch_5x/lucene/CHANGES.txt Thu Aug 20 14:44:28 2015
@@ -36,6 +36,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/branches/branch_5x/lucene/core/src/java/org/apache/lucene/store/RAMInputStream.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_5x/lucene/core/src/java/org/apache/lucene/store/RAMInputStream.java?rev=1696802&r1=1696801&r2=1696802&view=diff
==============================================================================
--- lucene/dev/branches/branch_5x/lucene/core/src/java/org/apache/lucene/store/RAMInputStream.java (original)
+++ lucene/dev/branches/branch_5x/lucene/core/src/java/org/apache/lucene/store/RAMInputStream.java Thu Aug 20 14:44:28 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/branches/branch_5x/lucene/test-framework/src/java/org/apache/lucene/store/BaseDirectoryTestCase.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_5x/lucene/test-framework/src/java/org/apache/lucene/store/BaseDirectoryTestCase.java?rev=1696802&r1=1696801&r2=1696802&view=diff
==============================================================================
--- lucene/dev/branches/branch_5x/lucene/test-framework/src/java/org/apache/lucene/store/BaseDirectoryTestCase.java (original)
+++ lucene/dev/branches/branch_5x/lucene/test-framework/src/java/org/apache/lucene/store/BaseDirectoryTestCase.java Thu Aug 20 14:44:28 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++) {
+      final 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();
+  }
+}