Hello Christoph,

Thanks for the fixes and additional unit tests.
I applied your patches and added your test cases to TestIndexReader
unit test class.  I will commit TestIndexReader now, but note that the
reader-reader test still fails sometimes/often (see below).

I will therefore wait with the commit of IndexReader.


    [junit] Testsuite: org.apache.lucene.index.TestDelete
    [junit] Tests run: 2, Failures: 1, Errors: 0, Time elapsed: 0.658
sec
 
    [junit] Testcase:
testDeleteReaderReaderConflict(org.apache.lucene.index.TestDelete):    
  FAILED
    [junit] expected:<0> but was:<100>
    [junit] junit.framework.AssertionFailedError: expected:<0> but
was:<100>
    [junit]     at
org.apache.lucene.index.TestDelete.testDeleteReaderReaderConflict(TestDelete.java:149)
    [junit]     at sun.reflect.NativeMethodAccessorImpl.invoke0(Native
Method)
    [junit]     at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    [junit]     at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
                                                                       
                                                     
                                                                       
                                                     
    [junit] TEST org.apache.lucene.index.TestDelete FAILED


Otis


--- Christoph Goller <[EMAIL PROTECTED]> wrote:
> This is a patch for Bug 12588.
> 
> Problem:
> 
> If a reader is opened (reader1) on an index without acquiring a
> write.lock and
> later the index is changed by either another reader (reader2) or a
> writer, the
> first reader can still acquire a write.lock and change the index.
> Thus
> the changes by reader1 or the writer are lost. My patch adds an
> additional check
> to Indexreader.delete(int) which checks whether the index has changed
> since the reader
> was opened. Since this check is done with a valid write.lock no other
> reader/writer
> could interfere with the check. If the index has been changed the
> reader is not
> granted write permission. The only way to delete a document in such a
> case is to
> get a new reader and call delete there. The patch for IndexReader and
> a unit test are
> attached.
> 
> Christoph
> 
> -- 
> *****************************************************************
> * Dr. Christoph Goller       Tel.:   +49 89 203 45734           *
> * Detego Software GmbH       Mobile: +49 179 1128469            *
> * Keuslinstr. 13             Fax.:   +49 721 151516176          *
> * 80798 München, Germany     Email:  [EMAIL PROTECTED]  *
> *****************************************************************
> > Index: IndexReader.java
> ===================================================================
> RCS file:
>
/home/cvspublic/jakarta-lucene/src/java/org/apache/lucene/index/IndexReader.java,v
> retrieving revision 1.17
> diff -u -r1.17 IndexReader.java
> --- IndexReader.java  12 Aug 2003 15:05:03 -0000      1.17
> +++ IndexReader.java  12 Sep 2003 11:28:14 -0000
> @@ -80,10 +80,14 @@
>  public abstract class IndexReader {
>    protected IndexReader(Directory directory) {
>      this.directory = directory;
> +    segmentInfosAge = Long.MAX_VALUE;
>    }
>  
>    Directory directory;
>    private Lock writeLock;
> +  
> +  //used to determine whether index has chaged since reader was
> opened
> +  private long segmentInfosAge;
>  
>    /** Returns an IndexReader reading the index in an FSDirectory in
> the named
>    path. */
> @@ -102,15 +106,20 @@
>      synchronized (directory) {                         // in- & inter-process sync
>        return (IndexReader)new
> Lock.With(directory.makeLock("commit.lock"),
> IndexWriter.COMMIT_LOCK_TIMEOUT) {
>         public Object doBody() throws IOException {
> +            IndexReader result = null;
> +            
>           SegmentInfos infos = new SegmentInfos();
>           infos.read(directory);
>           if (infos.size() == 1)                // index is optimized
> -           return new SegmentReader(infos.info(0), true);
> +           result = new SegmentReader(infos.info(0), true);
>  
>           SegmentReader[] readers = new SegmentReader[infos.size()];
>           for (int i = 0; i < infos.size(); i++)
>             readers[i] = new SegmentReader(infos.info(i),
> i==infos.size()-1);
> -         return new SegmentsReader(directory, readers);
> +         result =  new SegmentsReader(directory, readers);
> +        
> +            result.segmentInfosAge =
> directory.fileModified("segments");
> +            return result;
>         }
>       }.run();
>      }
> @@ -258,6 +267,14 @@
>        if (!writeLock.obtain(IndexWriter.WRITE_LOCK_TIMEOUT)) //
> obtain write lock
>          throw new IOException("Index locked for write: " +
> writeLock);
>        this.writeLock = writeLock;
> +      
> +      // we have to check whether index has changed since this
> reader was opened.
> +      // if so, this reader is no longer valid for deletion
> +      if(lastModified(directory) > segmentInfosAge){
> +          this.writeLock.release();
> +          this.writeLock = null;
> +          throw new IOException("IndexReader out of date and no
> longer valid for deletion");
> +      }
>      }
>      doDelete(docNum);
>    }
> > /*
>  * Created on 11.09.2003
>  *
>  * To change the template for this generated file go to
>  * Window>Preferences>Java>Code Generation>Code and Comments
>  */
> package org.apache.lucene.index;
> 
> import java.io.IOException;
> 
> import org.apache.lucene.analysis.WhitespaceAnalyzer;
> import org.apache.lucene.document.Document;
> import org.apache.lucene.document.Field;
> import org.apache.lucene.search.Hits;
> import org.apache.lucene.search.IndexSearcher;
> import org.apache.lucene.search.Searcher;
> import org.apache.lucene.search.TermQuery;
> import org.apache.lucene.store.Directory;
> import org.apache.lucene.store.RAMDirectory;
> 
> import junit.framework.TestCase;
> 
> /**
>  * 
>  * @author goller
>  */
> public class TestDelete extends TestCase {
>     
>     public void testDeleteReaderWriterConflict(){
>         
>         Directory dir = new RAMDirectory();
>         IndexWriter writer = null;
>         IndexReader reader = null;
>         Searcher searcher = null;
>         Term searchTerm = new Term("content", "aaa");
>         Hits hits = null;
>         
>         try {
>             
>             //  add 100 documents with term : aaa
>            writer  = new IndexWriter(dir, new WhitespaceAnalyzer(),
> true);
>            for (int i = 0; i < 100; i++) {
>              addDoc(writer, "aaa");
>            }
>            writer.close();
>            
>            reader = IndexReader.open(dir);
>            
>            //  add 100 documents with term : bbb
>           writer  = new IndexWriter(dir, new WhitespaceAnalyzer(),
> false);
>           for (int i = 0; i < 100; i++) {
>             addDoc(writer, "bbb");
>           }
>           writer.optimize();
>           writer.close();
>           
>         }
>         catch (IOException e) {
>           e.printStackTrace();
>         }
>            
>         try{
>             // delete documents containing term: aaa
>             reader.delete(searchTerm);
>             reader.close();
>         }
>         catch (IOException e) {
>             try {
>                 // if reader throws IOException try once more to
> delete documents with a new reader
>                 reader.close();
>                 reader = IndexReader.open(dir);
>                 reader.delete(searchTerm);
>                 reader.close();
>             }
>             catch (IOException e1) {
>                 e1.printStackTrace();
>             }
>         }
> 
>         try {
>             searcher = new IndexSearcher(dir);
>             hits = searcher.search(new TermQuery(searchTerm));
>             assertEquals(0, hits.length());
>             searcher.close();
>         }
>         catch (IOException e1) {
>             e1.printStackTrace();
>         }
>           
>         
>         
>     }
>     
>     public void testDeleteReaderReaderConflict(){
>         
>         Directory dir = new RAMDirectory();
>         IndexWriter writer = null;
>         IndexReader reader1 = null;
>         IndexReader reader2 = null;
>         Searcher searcher = null;
>         Hits hits = null;
>         Term searchTerm1 = new Term("content", "aaa");
>         Term searchTerm2 = new Term("content", "bbb");
>         
>         try {
>             
>             //  add 100 documents with term : aaa
>             //  add 100 documents with term : bbb
>             //  add 100 documents with term : ccc
>            writer  = new IndexWriter(dir, new WhitespaceAnalyzer(),
> true);
>            for (int i = 0; i < 100; i++) {
>              addDoc(writer, "aaa");
>              addDoc(writer, "bbb");
>              addDoc(writer, "ccc");
>            }
>           writer.optimize();
>           writer.close();
>           
>         }
>         catch (IOException e) {
>           e.printStackTrace();
>         }
>         
>            
>         try{
>             
>             reader1 = IndexReader.open(dir);
>             reader2 = IndexReader.open(dir);
>             
>             // delete documents containing term: aaa
>             reader2.delete(searchTerm1);
>             reader2.close();
>             
>             // delete documents containing term: bbb
>             reader1.delete(searchTerm2);
>             reader1.close();
>         }
>         catch (IOException e) {
>             try {
>                 // if reader throws IOException try once more to
> delete documents with a new reader
>                 reader1.close();
>                 reader1 = IndexReader.open(dir);
>                 reader1.delete(searchTerm2);
>                 reader1.close();
>             }
>             catch (IOException e1) {
>                 e1.printStackTrace();
>             }
>         }
> 
>         try {
>             searcher = new IndexSearcher(dir);
>             hits = searcher.search(new TermQuery(searchTerm1));
>             assertEquals(0, hits.length());
>             hits = searcher.search(new TermQuery(searchTerm2));
>             assertEquals(0, hits.length());
>             searcher.close();
>         }
>         catch (IOException e1) {
>             e1.printStackTrace();
>         }
>         
>     }
>     
>     
>     private void addDoc(IndexWriter writer, String value)
>     {
>       Document doc = new Document();
>       doc.add(Field.UnStored("content", value));
> 
>       try {
>         writer.addDocument(doc);
>       }
>       catch (IOException e) {
>         e.printStackTrace();
>       }
>     }
> }
> 
> >
---------------------------------------------------------------------
> To unsubscribe, e-mail: [EMAIL PROTECTED]
> For additional commands, e-mail: [EMAIL PROTECTED]


__________________________________
Do you Yahoo!?
Yahoo! SiteBuilder - Free, easy-to-use web site design software
http://sitebuilder.yahoo.com

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to