You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by us...@apache.org on 2012/08/22 23:29:37 UTC

svn commit: r1376261 - in /lucene/dev/trunk/lucene: CHANGES.txt core/src/java/org/apache/lucene/document/Field.java core/src/test/org/apache/lucene/document/TestField.java

Author: uschindler
Date: Wed Aug 22 21:29:36 2012
New Revision: 1376261

URL: http://svn.apache.org/viewvc?rev=1376261&view=rev
Log:
LUCENE-4315: Add ReusableStringReader to Field.java

Modified:
    lucene/dev/trunk/lucene/CHANGES.txt
    lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/document/Field.java
    lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/document/TestField.java

Modified: lucene/dev/trunk/lucene/CHANGES.txt
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/CHANGES.txt?rev=1376261&r1=1376260&r2=1376261&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/CHANGES.txt (original)
+++ lucene/dev/trunk/lucene/CHANGES.txt Wed Aug 22 21:29:36 2012
@@ -104,8 +104,8 @@ Bug Fixes
 
 Optimizations
 
-* LUCENE-4317: Improve reuse of internal TokenStreams in oal.document.Field.
-  (Uwe Schindler, Chris Male, Robert Muir)
+* LUCENE-4317: Improve reuse of internal TokenStreams and StringReader
+  in oal.document.Field.  (Uwe Schindler, Chris Male, Robert Muir)
 
 Build
 

Modified: lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/document/Field.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/document/Field.java?rev=1376261&r1=1376260&r2=1376261&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/document/Field.java (original)
+++ lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/document/Field.java Wed Aug 22 21:29:36 2012
@@ -19,7 +19,6 @@ package org.apache.lucene.document;
 
 import java.io.IOException;
 import java.io.Reader;
-import java.io.StringReader;
 
 import org.apache.lucene.analysis.Analyzer;
 import org.apache.lucene.analysis.NumericTokenStream;
@@ -73,7 +72,8 @@ public class Field implements IndexableF
   // customize how it's tokenized:
   protected TokenStream tokenStream;
 
-  protected transient TokenStream internalTokenStream;
+  private transient TokenStream internalTokenStream;
+  private transient ReusableStringReader internalReader;
 
   protected float boost = 1.0f;
 
@@ -460,12 +460,56 @@ public class Field implements IndexableF
     } else if (readerValue() != null) {
       return analyzer.tokenStream(name(), readerValue());
     } else if (stringValue() != null) {
-      return analyzer.tokenStream(name(), new StringReader(stringValue()));
+      if (internalReader == null) {
+        internalReader = new ReusableStringReader();
+      }
+      internalReader.setValue(stringValue());
+      return analyzer.tokenStream(name(), internalReader);
     }
 
     throw new IllegalArgumentException("Field must have either TokenStream, String, Reader or Number value");
   }
   
+  static final class ReusableStringReader extends Reader {
+    private int pos = 0, size = 0;
+    private String s = null;
+    
+    void setValue(String s) {
+      this.s = s;
+      this.size = s.length();
+      this.pos = 0;
+    }
+    
+    @Override
+    public int read() {
+      if (pos < size) {
+        return s.charAt(pos++);
+      } else {
+        s = null;
+        return -1;
+      }
+    }
+    
+    @Override
+    public int read(char[] c, int off, int len) {
+      if (pos < size) {
+        len = Math.min(len, size-pos);
+        s.getChars(pos, pos+len, c, off);
+        pos += len;
+        return len;
+      } else {
+        s = null;
+        return -1;
+      }
+    }
+    
+    @Override
+    public void close() {
+      pos = size; // this prevents NPE when reading after close!
+      s = null;
+    }
+  }
+  
   static final class StringTokenStream extends TokenStream {
     private final CharTermAttribute termAttribute = addAttribute(CharTermAttribute.class);
     private final OffsetAttribute offsetAttribute = addAttribute(OffsetAttribute.class);
@@ -506,6 +550,11 @@ public class Field implements IndexableF
     public void reset() {
       used = false;
     }
+
+    @Override
+    public void close() {
+      value = null;
+    }
   }
 
   /** Specifies whether and how a field should be stored. */

Modified: lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/document/TestField.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/document/TestField.java?rev=1376261&r1=1376260&r2=1376261&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/document/TestField.java (original)
+++ lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/document/TestField.java Wed Aug 22 21:29:36 2012
@@ -18,9 +18,11 @@ package org.apache.lucene.document;
  */
 
 import java.io.StringReader;
+import java.nio.CharBuffer;
 
 import org.apache.lucene.analysis.CannedTokenStream;
 import org.apache.lucene.analysis.Token;
+import org.apache.lucene.document.Field.ReusableStringReader;
 import org.apache.lucene.util.BytesRef;
 import org.apache.lucene.util.LuceneTestCase;
 
@@ -610,4 +612,40 @@ public class TestField extends LuceneTes
       // expected
     }
   }
+  
+  public void testReusableStringReader() throws Exception {
+    ReusableStringReader reader = new ReusableStringReader();
+    assertEquals(-1, reader.read());
+    assertEquals(-1, reader.read(new char[1]));
+    assertEquals(-1, reader.read(new char[2], 1, 1));
+    assertEquals(-1, reader.read(CharBuffer.wrap(new char[2])));
+    
+    reader.setValue("foobar");
+    char[] buf = new char[4];
+    assertEquals(4, reader.read(buf));
+    assertEquals("foob", new String(buf));
+    assertEquals(2, reader.read(buf));
+    assertEquals("ar", new String(buf, 0, 2));
+    assertEquals(-1, reader.read(buf));
+    reader.close();
+
+    reader.setValue("foobar");
+    assertEquals(0, reader.read(buf, 1, 0));
+    assertEquals(3, reader.read(buf, 1, 3));
+    assertEquals("foo", new String(buf, 1, 3));
+    assertEquals(2, reader.read(CharBuffer.wrap(buf, 2, 2)));
+    assertEquals("ba", new String(buf, 2, 2));
+    assertEquals('r', (char) reader.read());
+    assertEquals(-1, reader.read(buf));
+    reader.close();
+
+    reader.setValue("foobar");
+    StringBuilder sb = new StringBuilder();
+    int ch;
+    while ((ch = reader.read()) != -1) {
+      sb.append((char) ch);
+    }
+    reader.close();
+    assertEquals("foobar", sb.toString());    
+  }
 }