pylucene 3.5.0-3
[pylucene.git] / lucene-java-3.5.0 / lucene / src / test / org / apache / lucene / index / TestIndexReaderDelete.java
diff --git a/lucene-java-3.5.0/lucene/src/test/org/apache/lucene/index/TestIndexReaderDelete.java b/lucene-java-3.5.0/lucene/src/test/org/apache/lucene/index/TestIndexReaderDelete.java
new file mode 100644 (file)
index 0000000..8e58629
--- /dev/null
@@ -0,0 +1,376 @@
+package org.apache.lucene.index;
+
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.IOException;
+
+import org.apache.lucene.analysis.MockAnalyzer;
+import org.apache.lucene.document.Document;
+import org.apache.lucene.document.Field;
+import org.apache.lucene.index.IndexWriterConfig.OpenMode;
+import org.apache.lucene.store.Directory;
+import org.apache.lucene.store.MockDirectoryWrapper;
+import org.apache.lucene.util.LuceneTestCase;
+
+import static org.apache.lucene.index.TestIndexReader.addDoc;
+import static org.apache.lucene.index.TestIndexReader.addDocumentWithFields;
+import static org.apache.lucene.index.TestIndexReader.assertTermDocsCount;
+import static org.apache.lucene.index.TestIndexReader.createDocument;
+
+public class TestIndexReaderDelete extends LuceneTestCase {
+  private void deleteReaderReaderConflict(boolean doFullMerge) throws IOException {
+    Directory dir = newDirectory();
+
+    Term searchTerm1 = new Term("content", "aaa");
+    Term searchTerm2 = new Term("content", "bbb");
+    Term searchTerm3 = new Term("content", "ccc");
+
+    //  add 100 documents with term : aaa
+    //  add 100 documents with term : bbb
+    //  add 100 documents with term : ccc
+    IndexWriter writer  = new IndexWriter(dir, newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random)).setOpenMode(OpenMode.CREATE));
+    for (int i = 0; i < 100; i++) {
+        addDoc(writer, searchTerm1.text());
+        addDoc(writer, searchTerm2.text());
+        addDoc(writer, searchTerm3.text());
+    }
+    if (doFullMerge) {
+      writer.forceMerge(1);
+    }
+    writer.close();
+
+    // OPEN TWO READERS
+    // Both readers get segment info as exists at this time
+    IndexReader reader1 = IndexReader.open(dir, false);
+    assertEquals("first opened", 100, reader1.docFreq(searchTerm1));
+    assertEquals("first opened", 100, reader1.docFreq(searchTerm2));
+    assertEquals("first opened", 100, reader1.docFreq(searchTerm3));
+    assertTermDocsCount("first opened", reader1, searchTerm1, 100);
+    assertTermDocsCount("first opened", reader1, searchTerm2, 100);
+    assertTermDocsCount("first opened", reader1, searchTerm3, 100);
+
+    IndexReader reader2 = IndexReader.open(dir, false);
+    assertEquals("first opened", 100, reader2.docFreq(searchTerm1));
+    assertEquals("first opened", 100, reader2.docFreq(searchTerm2));
+    assertEquals("first opened", 100, reader2.docFreq(searchTerm3));
+    assertTermDocsCount("first opened", reader2, searchTerm1, 100);
+    assertTermDocsCount("first opened", reader2, searchTerm2, 100);
+    assertTermDocsCount("first opened", reader2, searchTerm3, 100);
+
+    // DELETE DOCS FROM READER 2 and CLOSE IT
+    // delete documents containing term: aaa
+    // when the reader is closed, the segment info is updated and
+    // the first reader is now stale
+    reader2.deleteDocuments(searchTerm1);
+    assertEquals("after delete 1", 100, reader2.docFreq(searchTerm1));
+    assertEquals("after delete 1", 100, reader2.docFreq(searchTerm2));
+    assertEquals("after delete 1", 100, reader2.docFreq(searchTerm3));
+    assertTermDocsCount("after delete 1", reader2, searchTerm1, 0);
+    assertTermDocsCount("after delete 1", reader2, searchTerm2, 100);
+    assertTermDocsCount("after delete 1", reader2, searchTerm3, 100);
+    reader2.close();
+
+    // Make sure reader 1 is unchanged since it was open earlier
+    assertEquals("after delete 1", 100, reader1.docFreq(searchTerm1));
+    assertEquals("after delete 1", 100, reader1.docFreq(searchTerm2));
+    assertEquals("after delete 1", 100, reader1.docFreq(searchTerm3));
+    assertTermDocsCount("after delete 1", reader1, searchTerm1, 100);
+    assertTermDocsCount("after delete 1", reader1, searchTerm2, 100);
+    assertTermDocsCount("after delete 1", reader1, searchTerm3, 100);
+
+
+    // ATTEMPT TO DELETE FROM STALE READER
+    // delete documents containing term: bbb
+    try {
+        reader1.deleteDocuments(searchTerm2);
+        fail("Delete allowed from a stale index reader");
+    } catch (IOException e) {
+        /* success */
+    }
+
+    // RECREATE READER AND TRY AGAIN
+    reader1.close();
+    reader1 = IndexReader.open(dir, false);
+    assertEquals("reopened", 100, reader1.docFreq(searchTerm1));
+    assertEquals("reopened", 100, reader1.docFreq(searchTerm2));
+    assertEquals("reopened", 100, reader1.docFreq(searchTerm3));
+    assertTermDocsCount("reopened", reader1, searchTerm1, 0);
+    assertTermDocsCount("reopened", reader1, searchTerm2, 100);
+    assertTermDocsCount("reopened", reader1, searchTerm3, 100);
+
+    reader1.deleteDocuments(searchTerm2);
+    assertEquals("deleted 2", 100, reader1.docFreq(searchTerm1));
+    assertEquals("deleted 2", 100, reader1.docFreq(searchTerm2));
+    assertEquals("deleted 2", 100, reader1.docFreq(searchTerm3));
+    assertTermDocsCount("deleted 2", reader1, searchTerm1, 0);
+    assertTermDocsCount("deleted 2", reader1, searchTerm2, 0);
+    assertTermDocsCount("deleted 2", reader1, searchTerm3, 100);
+    reader1.close();
+
+    // Open another reader to confirm that everything is deleted
+    reader2 = IndexReader.open(dir, false);
+    assertTermDocsCount("reopened 2", reader2, searchTerm1, 0);
+    assertTermDocsCount("reopened 2", reader2, searchTerm2, 0);
+    assertTermDocsCount("reopened 2", reader2, searchTerm3, 100);
+    reader2.close();
+
+    dir.close();
+  }
+
+  private void deleteReaderWriterConflict(boolean doFullMerge) throws IOException {
+    //Directory dir = new RAMDirectory();
+    Directory dir = newDirectory();
+
+    Term searchTerm = new Term("content", "aaa");
+    Term searchTerm2 = new Term("content", "bbb");
+
+    //  add 100 documents with term : aaa
+    IndexWriter writer  = new IndexWriter(dir, newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random)).setOpenMode(OpenMode.CREATE));
+    for (int i = 0; i < 100; i++) {
+        addDoc(writer, searchTerm.text());
+    }
+    writer.close();
+
+    // OPEN READER AT THIS POINT - this should fix the view of the
+    // index at the point of having 100 "aaa" documents and 0 "bbb"
+    IndexReader reader = IndexReader.open(dir, false);
+    assertEquals("first docFreq", 100, reader.docFreq(searchTerm));
+    assertEquals("first docFreq", 0, reader.docFreq(searchTerm2));
+    assertTermDocsCount("first reader", reader, searchTerm, 100);
+    assertTermDocsCount("first reader", reader, searchTerm2, 0);
+
+    // add 100 documents with term : bbb
+    writer  = new IndexWriter(dir, newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random)).setOpenMode(OpenMode.APPEND));
+    for (int i = 0; i < 100; i++) {
+        addDoc(writer, searchTerm2.text());
+    }
+
+    // REQUEST full merge
+    // This causes a new segment to become current for all subsequent
+    // searchers. Because of this, deletions made via a previously open
+    // reader, which would be applied to that reader's segment, are lost
+    // for subsequent searchers/readers
+    if (doFullMerge) {
+      writer.forceMerge(1);
+    }
+    writer.close();
+
+    // The reader should not see the new data
+    assertEquals("first docFreq", 100, reader.docFreq(searchTerm));
+    assertEquals("first docFreq", 0, reader.docFreq(searchTerm2));
+    assertTermDocsCount("first reader", reader, searchTerm, 100);
+    assertTermDocsCount("first reader", reader, searchTerm2, 0);
+
+
+    // DELETE DOCUMENTS CONTAINING TERM: aaa
+    // NOTE: the reader was created when only "aaa" documents were in
+    int deleted = 0;
+    try {
+        deleted = reader.deleteDocuments(searchTerm);
+        fail("Delete allowed on an index reader with stale segment information");
+    } catch (StaleReaderException e) {
+        /* success */
+    }
+
+    // Re-open index reader and try again. This time it should see
+    // the new data.
+    reader.close();
+    reader = IndexReader.open(dir, false);
+    assertEquals("first docFreq", 100, reader.docFreq(searchTerm));
+    assertEquals("first docFreq", 100, reader.docFreq(searchTerm2));
+    assertTermDocsCount("first reader", reader, searchTerm, 100);
+    assertTermDocsCount("first reader", reader, searchTerm2, 100);
+
+    deleted = reader.deleteDocuments(searchTerm);
+    assertEquals("deleted count", 100, deleted);
+    assertEquals("deleted docFreq", 100, reader.docFreq(searchTerm));
+    assertEquals("deleted docFreq", 100, reader.docFreq(searchTerm2));
+    assertTermDocsCount("deleted termDocs", reader, searchTerm, 0);
+    assertTermDocsCount("deleted termDocs", reader, searchTerm2, 100);
+    reader.close();
+
+    // CREATE A NEW READER and re-test
+    reader = IndexReader.open(dir, false);
+    assertEquals("deleted docFreq", 100, reader.docFreq(searchTerm2));
+    assertTermDocsCount("deleted termDocs", reader, searchTerm, 0);
+    assertTermDocsCount("deleted termDocs", reader, searchTerm2, 100);
+    reader.close();
+    dir.close();
+  }
+
+  public void testBasicDelete() throws IOException {
+    Directory dir = newDirectory();
+
+    IndexWriter writer = null;
+    IndexReader reader = null;
+    Term searchTerm = new Term("content", "aaa");
+
+    //  add 100 documents with term : aaa
+    writer  = new IndexWriter(dir, newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random)));
+    writer.setInfoStream(VERBOSE ? System.out : null);
+    for (int i = 0; i < 100; i++) {
+        addDoc(writer, searchTerm.text());
+    }
+    writer.close();
+
+    // OPEN READER AT THIS POINT - this should fix the view of the
+    // index at the point of having 100 "aaa" documents and 0 "bbb"
+    reader = IndexReader.open(dir, false);
+    assertEquals("first docFreq", 100, reader.docFreq(searchTerm));
+    assertTermDocsCount("first reader", reader, searchTerm, 100);
+    reader.close();
+
+    // DELETE DOCUMENTS CONTAINING TERM: aaa
+    int deleted = 0;
+    reader = IndexReader.open(dir, false);
+    deleted = reader.deleteDocuments(searchTerm);
+    assertEquals("deleted count", 100, deleted);
+    assertEquals("deleted docFreq", 100, reader.docFreq(searchTerm));
+    assertTermDocsCount("deleted termDocs", reader, searchTerm, 0);
+
+    // open a 2nd reader to make sure first reader can
+    // commit its changes (.del) while second reader
+    // is open:
+    IndexReader reader2 = IndexReader.open(dir, false);
+    reader.close();
+
+    // CREATE A NEW READER and re-test
+    reader = IndexReader.open(dir, false);
+    assertEquals("deleted docFreq", 0, reader.docFreq(searchTerm));
+    assertTermDocsCount("deleted termDocs", reader, searchTerm, 0);
+    reader.close();
+    reader2.close();
+    dir.close();
+  }
+
+  public void testDeleteReaderReaderConflictNoFullMerge() throws IOException {
+    deleteReaderReaderConflict(false);
+  }
+  
+  public void testDeleteReaderReaderConflictFullMerge() throws IOException {
+    deleteReaderReaderConflict(true);
+  }
+  
+  public void testDeleteReaderWriterConflictNoFullMerge() throws IOException {
+    deleteReaderWriterConflict(false);
+  }
+  
+  public void testDeleteReaderWriterConflictFullMerge() throws IOException {
+    deleteReaderWriterConflict(true);
+  }
+  
+  public void testMultiReaderDeletes() throws Exception {
+    Directory dir = newDirectory();
+    RandomIndexWriter w= new RandomIndexWriter(random, dir, newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random)).setMergePolicy(newLogMergePolicy()));
+    Document doc = new Document();
+    doc.add(newField("f", "doctor", Field.Store.NO, Field.Index.NOT_ANALYZED));
+    w.addDocument(doc);
+    doc = new Document();
+    w.commit();
+    doc.add(newField("f", "who", Field.Store.NO, Field.Index.NOT_ANALYZED));
+    w.addDocument(doc);
+    IndexReader r = new SlowMultiReaderWrapper(w.getReader());
+    w.close();
+
+    assertFalse(r.hasDeletions());
+    r.close();
+
+    r = new SlowMultiReaderWrapper(IndexReader.open(dir, false));
+
+    assertFalse(r.hasDeletions());
+    assertEquals(1, r.deleteDocuments(new Term("f", "doctor")));
+    assertTrue(r.hasDeletions());
+    assertTrue(r.isDeleted(0));
+    assertEquals(1, r.deleteDocuments(new Term("f", "who")));
+    assertTrue(r.isDeleted(1));
+    r.close();
+    dir.close();
+  }
+  
+  public void testUndeleteAll() throws IOException {
+    Directory dir = newDirectory();
+    IndexWriter writer  = new IndexWriter(dir, newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random)));
+    addDocumentWithFields(writer);
+    addDocumentWithFields(writer);
+    writer.close();
+    IndexReader reader = IndexReader.open(dir, false);
+    reader.deleteDocument(0);
+    reader.deleteDocument(1);
+    reader.undeleteAll();
+    reader.close();
+    reader = IndexReader.open(dir, false);
+    assertEquals(2, reader.numDocs());  // nothing has really been deleted thanks to undeleteAll()
+    reader.close();
+    dir.close();
+  }
+
+  public void testUndeleteAllAfterClose() throws IOException {
+    Directory dir = newDirectory();
+    IndexWriter writer  = new IndexWriter(dir, newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random)));
+    addDocumentWithFields(writer);
+    addDocumentWithFields(writer);
+    writer.close();
+    IndexReader reader = IndexReader.open(dir, false);
+    reader.deleteDocument(0);
+    reader.close();
+    reader = IndexReader.open(dir, false);
+    reader.undeleteAll();
+    assertEquals(2, reader.numDocs());  // nothing has really been deleted thanks to undeleteAll()
+    reader.close();
+    dir.close();
+  }
+
+  public void testUndeleteAllAfterCloseThenReopen() throws IOException {
+    Directory dir = newDirectory();
+    IndexWriter writer  = new IndexWriter(dir, newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random)));
+    addDocumentWithFields(writer);
+    addDocumentWithFields(writer);
+    writer.close();
+    IndexReader reader = IndexReader.open(dir, false);
+    reader.deleteDocument(0);
+    reader.close();
+    reader = IndexReader.open(dir, false);
+    reader.undeleteAll();
+    reader.close();
+    reader = IndexReader.open(dir, false);
+    assertEquals(2, reader.numDocs());  // nothing has really been deleted thanks to undeleteAll()
+    reader.close();
+    dir.close();
+  }
+  
+  // LUCENE-1647
+  public void testIndexReaderUnDeleteAll() throws Exception {
+    MockDirectoryWrapper dir = newDirectory();
+    dir.setPreventDoubleWrite(false);
+    IndexWriter writer = new IndexWriter(dir, newIndexWriterConfig(
+        TEST_VERSION_CURRENT, new MockAnalyzer(random)));
+    writer.addDocument(createDocument("a"));
+    writer.addDocument(createDocument("b"));
+    writer.addDocument(createDocument("c"));
+    writer.close();
+    IndexReader reader = IndexReader.open(dir, false);
+    reader.deleteDocuments(new Term("id", "a"));
+    reader.flush();
+    reader.deleteDocuments(new Term("id", "b"));
+    reader.undeleteAll();
+    reader.deleteDocuments(new Term("id", "b"));
+    reader.close();
+    IndexReader.open(dir,true).close();
+    dir.close();
+  }
+}