| /* |
| * 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. |
| */ |
| |
| using System; |
| using System.Collections.Generic; |
| using NUnit.Framework; |
| |
| using WhitespaceAnalyzer = Lucene.Net.Analysis.WhitespaceAnalyzer; |
| using Document = Lucene.Net.Documents.Document; |
| using Field = Lucene.Net.Documents.Field; |
| using Directory = Lucene.Net.Store.Directory; |
| using MockRAMDirectory = Lucene.Net.Store.MockRAMDirectory; |
| using RAMDirectory = Lucene.Net.Store.RAMDirectory; |
| using IndexSearcher = Lucene.Net.Search.IndexSearcher; |
| using Query = Lucene.Net.Search.Query; |
| using ScoreDoc = Lucene.Net.Search.ScoreDoc; |
| using TermQuery = Lucene.Net.Search.TermQuery; |
| using LuceneTestCase = Lucene.Net.Util.LuceneTestCase; |
| |
| namespace Lucene.Net.Index |
| { |
| |
| /* |
| Verify we can read the pre-2.1 file format, do searches |
| against it, and add documents to it.*/ |
| |
| [TestFixture] |
| public class TestDeletionPolicy : LuceneTestCase |
| { |
| private void VerifyCommitOrder<T>(IList<T> commits) where T : IndexCommit |
| { |
| IndexCommit firstCommit = commits[0]; |
| long last = SegmentInfos.GenerationFromSegmentsFileName(firstCommit.SegmentsFileName); |
| Assert.AreEqual(last, firstCommit.Generation); |
| long lastVersion = firstCommit.Version; |
| long lastTimestamp = firstCommit.Timestamp; |
| for (int i = 1; i < commits.Count; i++) |
| { |
| IndexCommit commit = commits[i]; |
| long now = SegmentInfos.GenerationFromSegmentsFileName(commit.SegmentsFileName); |
| long nowVersion = commit.Version; |
| long nowTimestamp = commit.Timestamp; |
| Assert.IsTrue(now > last, "SegmentInfos commits are out-of-order"); |
| Assert.IsTrue(nowVersion > lastVersion, "SegmentInfos versions are out-of-order"); |
| Assert.IsTrue(nowTimestamp >= lastTimestamp, "SegmentInfos timestamps are out-of-order: now=" + nowTimestamp + " vs last=" + lastTimestamp); |
| Assert.AreEqual(now, commit.Generation); |
| last = now; |
| lastVersion = nowVersion; |
| lastTimestamp = nowTimestamp; |
| } |
| } |
| |
| internal class KeepAllDeletionPolicy : IndexDeletionPolicy |
| { |
| public KeepAllDeletionPolicy(TestDeletionPolicy enclosingInstance) |
| { |
| InitBlock(enclosingInstance); |
| } |
| private void InitBlock(TestDeletionPolicy enclosingInstance) |
| { |
| this.enclosingInstance = enclosingInstance; |
| } |
| private TestDeletionPolicy enclosingInstance; |
| public TestDeletionPolicy Enclosing_Instance |
| { |
| get |
| { |
| return enclosingInstance; |
| } |
| |
| } |
| internal int numOnInit; |
| internal int numOnCommit; |
| internal Directory dir; |
| public virtual void OnInit<T>(IList<T> commits) where T : IndexCommit |
| { |
| Enclosing_Instance.VerifyCommitOrder(commits); |
| numOnInit++; |
| } |
| public virtual void OnCommit<T>(IList<T> commits) where T : IndexCommit |
| { |
| IndexCommit lastCommit = (IndexCommit) commits[commits.Count - 1]; |
| IndexReader r = IndexReader.Open(dir, true); |
| Assert.AreEqual(r.IsOptimized(), lastCommit.IsOptimized, "lastCommit.isOptimized()=" + lastCommit.IsOptimized + " vs IndexReader.isOptimized=" + r.IsOptimized()); |
| r.Close(); |
| Enclosing_Instance.VerifyCommitOrder(commits); |
| numOnCommit++; |
| } |
| } |
| |
| /// <summary> This is useful for adding to a big index when you know |
| /// readers are not using it. |
| /// </summary> |
| internal class KeepNoneOnInitDeletionPolicy : IndexDeletionPolicy |
| { |
| public KeepNoneOnInitDeletionPolicy(TestDeletionPolicy enclosingInstance) |
| { |
| InitBlock(enclosingInstance); |
| } |
| private void InitBlock(TestDeletionPolicy enclosingInstance) |
| { |
| this.enclosingInstance = enclosingInstance; |
| } |
| private TestDeletionPolicy enclosingInstance; |
| public TestDeletionPolicy Enclosing_Instance |
| { |
| get |
| { |
| return enclosingInstance; |
| } |
| |
| } |
| internal int numOnInit; |
| internal int numOnCommit; |
| public virtual void OnInit<T>(IList<T> commits) where T : IndexCommit |
| { |
| Enclosing_Instance.VerifyCommitOrder(commits); |
| numOnInit++; |
| // On init, delete all commit points: |
| System.Collections.IEnumerator it = commits.GetEnumerator(); |
| while (it.MoveNext()) |
| { |
| IndexCommit commit = (IndexCommit) it.Current; |
| commit.Delete(); |
| Assert.IsTrue(commit.IsDeleted); |
| } |
| } |
| public virtual void OnCommit<T>(IList<T> commits) where T : IndexCommit |
| { |
| Enclosing_Instance.VerifyCommitOrder(commits); |
| int size = commits.Count; |
| // Delete all but last one: |
| for (int i = 0; i < size - 1; i++) |
| { |
| ((IndexCommit) commits[i]).Delete(); |
| } |
| numOnCommit++; |
| } |
| } |
| |
| internal class KeepLastNDeletionPolicy : IndexDeletionPolicy |
| { |
| private void InitBlock(TestDeletionPolicy enclosingInstance) |
| { |
| this.enclosingInstance = enclosingInstance; |
| } |
| private TestDeletionPolicy enclosingInstance; |
| public TestDeletionPolicy Enclosing_Instance |
| { |
| get |
| { |
| return enclosingInstance; |
| } |
| |
| } |
| internal int numOnInit; |
| internal int numOnCommit; |
| internal int numToKeep; |
| internal int numDelete; |
| internal System.Collections.Hashtable seen = new System.Collections.Hashtable(); |
| |
| public KeepLastNDeletionPolicy(TestDeletionPolicy enclosingInstance, int numToKeep) |
| { |
| InitBlock(enclosingInstance); |
| this.numToKeep = numToKeep; |
| } |
| |
| public virtual void OnInit<T>(IList<T> commits) where T : IndexCommit |
| { |
| Enclosing_Instance.VerifyCommitOrder(commits); |
| numOnInit++; |
| // do no deletions on init |
| DoDeletes(commits, false); |
| } |
| |
| public virtual void OnCommit<T>(IList<T> commits) where T : IndexCommit |
| { |
| Enclosing_Instance.VerifyCommitOrder(commits); |
| DoDeletes(commits, true); |
| } |
| |
| private void DoDeletes<T>(IList<T> commits, bool isCommit) where T : IndexCommit |
| { |
| |
| // Assert that we really are only called for each new |
| // commit: |
| if (isCommit) |
| { |
| System.String fileName = commits[commits.Count - 1].SegmentsFileName; |
| if (seen.Contains(fileName)) |
| { |
| throw new System.SystemException("onCommit was called twice on the same commit point: " + fileName); |
| } |
| seen.Add(fileName, fileName); |
| numOnCommit++; |
| } |
| int size = commits.Count; |
| for (int i = 0; i < size - numToKeep; i++) |
| { |
| ((IndexCommit) commits[i]).Delete(); |
| numDelete++; |
| } |
| } |
| } |
| |
| /* |
| * Delete a commit only when it has been obsoleted by N |
| * seconds. |
| */ |
| internal class ExpirationTimeDeletionPolicy : IndexDeletionPolicy |
| { |
| private void InitBlock(TestDeletionPolicy enclosingInstance) |
| { |
| this.enclosingInstance = enclosingInstance; |
| } |
| private TestDeletionPolicy enclosingInstance; |
| public TestDeletionPolicy Enclosing_Instance |
| { |
| get |
| { |
| return enclosingInstance; |
| } |
| |
| } |
| |
| internal Directory dir; |
| internal double expirationTimeSeconds; |
| internal int numDelete; |
| |
| public ExpirationTimeDeletionPolicy(TestDeletionPolicy enclosingInstance, Directory dir, double seconds) |
| { |
| InitBlock(enclosingInstance); |
| this.dir = dir; |
| this.expirationTimeSeconds = seconds; |
| } |
| |
| public virtual void OnInit<T>(IList<T> commits) where T : IndexCommit |
| { |
| Enclosing_Instance.VerifyCommitOrder(commits); |
| OnCommit(commits); |
| } |
| |
| public virtual void OnCommit<T>(IList<T> commits) where T : IndexCommit |
| { |
| Enclosing_Instance.VerifyCommitOrder(commits); |
| |
| IndexCommit lastCommit = commits[commits.Count - 1]; |
| |
| // Any commit older than expireTime should be deleted: |
| double expireTime = dir.FileModified(lastCommit.SegmentsFileName) / 1000.0 - expirationTimeSeconds; |
| |
| System.Collections.IEnumerator it = commits.GetEnumerator(); |
| |
| while (it.MoveNext()) |
| { |
| IndexCommit commit = (IndexCommit) it.Current; |
| double modTime = dir.FileModified(commit.SegmentsFileName) / 1000.0; |
| if (commit != lastCommit && modTime < expireTime) |
| { |
| commit.Delete(); |
| numDelete += 1; |
| } |
| } |
| } |
| } |
| |
| /* |
| * Test "by time expiration" deletion policy: |
| */ |
| [Test] |
| public virtual void TestExpirationTimeDeletionPolicy() |
| { |
| double SECONDS = 2.0; |
| |
| bool useCompoundFile = true; |
| |
| Directory dir = new RAMDirectory(); |
| ExpirationTimeDeletionPolicy policy = new ExpirationTimeDeletionPolicy(this, dir, SECONDS); |
| IndexWriter writer = new IndexWriter(dir, new WhitespaceAnalyzer(), true, policy, IndexWriter.MaxFieldLength.UNLIMITED); |
| writer.UseCompoundFile = useCompoundFile; |
| writer.Close(); |
| |
| long lastDeleteTime = 0; |
| for (int i = 0; i < 7; i++) |
| { |
| // Record last time when writer performed deletes of |
| // past commits |
| lastDeleteTime = (DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond); |
| writer = new IndexWriter(dir, new WhitespaceAnalyzer(), false, policy, IndexWriter.MaxFieldLength.UNLIMITED); |
| writer.UseCompoundFile = useCompoundFile; |
| for (int j = 0; j < 17; j++) |
| { |
| AddDoc(writer); |
| } |
| writer.Close(); |
| |
| // Make sure to sleep long enough so that some commit |
| // points will be deleted: |
| System.Threading.Thread.Sleep(new System.TimeSpan((System.Int64) 10000 * (int) (1000.0 * (SECONDS / 5.0)))); |
| } |
| |
| // First, make sure the policy in fact deleted something: |
| Assert.IsTrue(policy.numDelete > 0, "no commits were deleted"); |
| |
| // Then simplistic check: just verify that the |
| // segments_N's that still exist are in fact within SECONDS |
| // seconds of the last one's mod time, and, that I can |
| // open a reader on each: |
| long gen = SegmentInfos.GetCurrentSegmentGeneration(dir); |
| |
| System.String fileName = IndexFileNames.FileNameFromGeneration(IndexFileNames.SEGMENTS, "", gen); |
| dir.DeleteFile(IndexFileNames.SEGMENTS_GEN); |
| while (gen > 0) |
| { |
| try |
| { |
| IndexReader reader = IndexReader.Open(dir, true); |
| reader.Close(); |
| fileName = IndexFileNames.FileNameFromGeneration(IndexFileNames.SEGMENTS, "", gen); |
| long modTime = dir.FileModified(fileName); |
| Assert.IsTrue(lastDeleteTime - modTime <= (SECONDS * 1000), "commit point was older than " + SECONDS + " seconds (" + (lastDeleteTime - modTime) + " msec) but did not get deleted"); |
| } |
| catch (System.IO.IOException) |
| { |
| // OK |
| break; |
| } |
| |
| dir.DeleteFile(IndexFileNames.FileNameFromGeneration(IndexFileNames.SEGMENTS, "", gen)); |
| gen--; |
| } |
| |
| dir.Close(); |
| } |
| |
| /* |
| * Test a silly deletion policy that keeps all commits around. |
| */ |
| [Test] |
| public virtual void TestKeepAllDeletionPolicy() |
| { |
| |
| for (int pass = 0; pass < 2; pass++) |
| { |
| bool useCompoundFile = (pass % 2) != 0; |
| |
| // Never deletes a commit |
| KeepAllDeletionPolicy policy = new KeepAllDeletionPolicy(this); |
| |
| Directory dir = new RAMDirectory(); |
| policy.dir = dir; |
| |
| IndexWriter writer = new IndexWriter(dir, new WhitespaceAnalyzer(), true, policy, IndexWriter.MaxFieldLength.UNLIMITED); |
| writer.SetMaxBufferedDocs(10); |
| writer.UseCompoundFile = useCompoundFile; |
| writer.SetMergeScheduler(new SerialMergeScheduler()); |
| for (int i = 0; i < 107; i++) |
| { |
| AddDoc(writer); |
| } |
| writer.Close(); |
| |
| writer = new IndexWriter(dir, new WhitespaceAnalyzer(), false, policy, IndexWriter.MaxFieldLength.UNLIMITED); |
| writer.UseCompoundFile = useCompoundFile; |
| writer.Optimize(); |
| writer.Close(); |
| |
| Assert.AreEqual(2, policy.numOnInit); |
| |
| // If we are not auto committing then there should |
| // be exactly 2 commits (one per close above): |
| Assert.AreEqual(2, policy.numOnCommit); |
| |
| // Test listCommits |
| ICollection<IndexCommit> commits = IndexReader.ListCommits(dir); |
| // 1 from opening writer + 2 from closing writer |
| Assert.AreEqual(3, commits.Count); |
| |
| System.Collections.IEnumerator it = commits.GetEnumerator(); |
| // Make sure we can open a reader on each commit: |
| while (it.MoveNext()) |
| { |
| IndexCommit commit = (IndexCommit) it.Current; |
| IndexReader r = IndexReader.Open(commit, null, false); |
| r.Close(); |
| } |
| |
| // Simplistic check: just verify all segments_N's still |
| // exist, and, I can open a reader on each: |
| dir.DeleteFile(IndexFileNames.SEGMENTS_GEN); |
| long gen = SegmentInfos.GetCurrentSegmentGeneration(dir); |
| while (gen > 0) |
| { |
| IndexReader reader = IndexReader.Open(dir, true); |
| reader.Close(); |
| dir.DeleteFile(IndexFileNames.FileNameFromGeneration(IndexFileNames.SEGMENTS, "", gen)); |
| gen--; |
| |
| if (gen > 0) |
| { |
| // Now that we've removed a commit point, which |
| // should have orphan'd at least one index file. |
| // Open & close a writer and assert that it |
| // actually removed something: |
| int preCount = dir.ListAll().Length; |
| writer = new IndexWriter(dir, new WhitespaceAnalyzer(), false, policy, IndexWriter.MaxFieldLength.LIMITED); |
| writer.Close(); |
| int postCount = dir.ListAll().Length; |
| Assert.IsTrue(postCount < preCount); |
| } |
| } |
| |
| dir.Close(); |
| } |
| } |
| |
| /* Uses KeepAllDeletionPolicy to keep all commits around, |
| * then, opens a new IndexWriter on a previous commit |
| * point. */ |
| [Test] |
| public virtual void TestOpenPriorSnapshot() |
| { |
| |
| // Never deletes a commit |
| KeepAllDeletionPolicy policy = new KeepAllDeletionPolicy(this); |
| |
| Directory dir = new MockRAMDirectory(); |
| policy.dir = dir; |
| |
| IndexWriter writer = new IndexWriter(dir, new WhitespaceAnalyzer(), policy, IndexWriter.MaxFieldLength.LIMITED); |
| writer.SetMaxBufferedDocs(2); |
| for (int i = 0; i < 10; i++) |
| { |
| AddDoc(writer); |
| if ((1 + i) % 2 == 0) |
| writer.Commit(); |
| } |
| writer.Close(); |
| |
| ICollection<IndexCommit> commits = IndexReader.ListCommits(dir); |
| Assert.AreEqual(6, commits.Count); |
| IndexCommit lastCommit = null; |
| System.Collections.IEnumerator it = commits.GetEnumerator(); |
| while (it.MoveNext()) |
| { |
| IndexCommit commit = (IndexCommit) it.Current; |
| if (lastCommit == null || commit.Generation > lastCommit.Generation) |
| lastCommit = commit; |
| } |
| Assert.IsTrue(lastCommit != null); |
| |
| // Now add 1 doc and optimize |
| writer = new IndexWriter(dir, new WhitespaceAnalyzer(), policy, IndexWriter.MaxFieldLength.LIMITED); |
| AddDoc(writer); |
| Assert.AreEqual(11, writer.NumDocs()); |
| writer.Optimize(); |
| writer.Close(); |
| |
| Assert.AreEqual(7, IndexReader.ListCommits(dir).Count); |
| |
| // Now open writer on the commit just before optimize: |
| writer = new IndexWriter(dir, new WhitespaceAnalyzer(), policy, IndexWriter.MaxFieldLength.LIMITED, lastCommit); |
| Assert.AreEqual(10, writer.NumDocs()); |
| |
| // Should undo our rollback: |
| writer.Rollback(); |
| |
| IndexReader r = IndexReader.Open(dir, true); |
| // Still optimized, still 11 docs |
| Assert.IsTrue(r.IsOptimized()); |
| Assert.AreEqual(11, r.NumDocs()); |
| r.Close(); |
| |
| writer = new IndexWriter(dir, new WhitespaceAnalyzer(), policy, IndexWriter.MaxFieldLength.LIMITED, lastCommit); |
| Assert.AreEqual(10, writer.NumDocs()); |
| // Commits the rollback: |
| writer.Close(); |
| |
| // Now 8 because we made another commit |
| Assert.AreEqual(8, IndexReader.ListCommits(dir).Count); |
| |
| r = IndexReader.Open(dir, true); |
| // Not optimized because we rolled it back, and now only |
| // 10 docs |
| Assert.IsTrue(!r.IsOptimized()); |
| Assert.AreEqual(10, r.NumDocs()); |
| r.Close(); |
| |
| // Reoptimize |
| writer = new IndexWriter(dir, new WhitespaceAnalyzer(), policy, IndexWriter.MaxFieldLength.LIMITED); |
| writer.Optimize(); |
| writer.Close(); |
| |
| r = IndexReader.Open(dir, true); |
| Assert.IsTrue(r.IsOptimized()); |
| Assert.AreEqual(10, r.NumDocs()); |
| r.Close(); |
| |
| // Now open writer on the commit just before optimize, |
| // but this time keeping only the last commit: |
| writer = new IndexWriter(dir, new WhitespaceAnalyzer(), new KeepOnlyLastCommitDeletionPolicy(), IndexWriter.MaxFieldLength.LIMITED, lastCommit); |
| Assert.AreEqual(10, writer.NumDocs()); |
| |
| // Reader still sees optimized index, because writer |
| // opened on the prior commit has not yet committed: |
| r = IndexReader.Open(dir, true); |
| Assert.IsTrue(r.IsOptimized()); |
| Assert.AreEqual(10, r.NumDocs()); |
| r.Close(); |
| |
| writer.Close(); |
| |
| // Now reader sees unoptimized index: |
| r = IndexReader.Open(dir, true); |
| Assert.IsTrue(!r.IsOptimized()); |
| Assert.AreEqual(10, r.NumDocs()); |
| r.Close(); |
| |
| dir.Close(); |
| } |
| |
| |
| /* Test keeping NO commit points. This is a viable and |
| * useful case eg where you want to build a big index and |
| * you know there are no readers. |
| */ |
| [Test] |
| public virtual void TestKeepNoneOnInitDeletionPolicy() |
| { |
| for (int pass = 0; pass < 2; pass++) |
| { |
| bool useCompoundFile = (pass % 2) != 0; |
| |
| KeepNoneOnInitDeletionPolicy policy = new KeepNoneOnInitDeletionPolicy(this); |
| |
| Directory dir = new RAMDirectory(); |
| |
| IndexWriter writer = new IndexWriter(dir, new WhitespaceAnalyzer(), true, policy, IndexWriter.MaxFieldLength.UNLIMITED); |
| writer.SetMaxBufferedDocs(10); |
| writer.UseCompoundFile = useCompoundFile; |
| for (int i = 0; i < 107; i++) |
| { |
| AddDoc(writer); |
| } |
| writer.Close(); |
| |
| writer = new IndexWriter(dir, new WhitespaceAnalyzer(), false, policy, IndexWriter.MaxFieldLength.UNLIMITED); |
| writer.UseCompoundFile = useCompoundFile; |
| writer.Optimize(); |
| writer.Close(); |
| |
| Assert.AreEqual(2, policy.numOnInit); |
| // If we are not auto committing then there should |
| // be exactly 2 commits (one per close above): |
| Assert.AreEqual(2, policy.numOnCommit); |
| |
| // Simplistic check: just verify the index is in fact |
| // readable: |
| IndexReader reader = IndexReader.Open(dir, true); |
| reader.Close(); |
| |
| dir.Close(); |
| } |
| } |
| |
| /* |
| * Test a deletion policy that keeps last N commits. |
| */ |
| [Test] |
| public virtual void TestKeepLastNDeletionPolicy() |
| { |
| int N = 5; |
| |
| for (int pass = 0; pass < 2; pass++) |
| { |
| bool useCompoundFile = (pass % 2) != 0; |
| |
| Directory dir = new RAMDirectory(); |
| |
| KeepLastNDeletionPolicy policy = new KeepLastNDeletionPolicy(this, N); |
| |
| for (int j = 0; j < N + 1; j++) |
| { |
| IndexWriter writer = new IndexWriter(dir, new WhitespaceAnalyzer(), true, policy, IndexWriter.MaxFieldLength.UNLIMITED); |
| writer.SetMaxBufferedDocs(10); |
| writer.UseCompoundFile = useCompoundFile; |
| for (int i = 0; i < 17; i++) |
| { |
| AddDoc(writer); |
| } |
| writer.Optimize(); |
| writer.Close(); |
| } |
| |
| Assert.IsTrue(policy.numDelete > 0); |
| Assert.AreEqual(N + 1, policy.numOnInit); |
| Assert.AreEqual(N + 1, policy.numOnCommit); |
| |
| // Simplistic check: just verify only the past N segments_N's still |
| // exist, and, I can open a reader on each: |
| dir.DeleteFile(IndexFileNames.SEGMENTS_GEN); |
| long gen = SegmentInfos.GetCurrentSegmentGeneration(dir); |
| for (int i = 0; i < N + 1; i++) |
| { |
| try |
| { |
| IndexReader reader = IndexReader.Open(dir, true); |
| reader.Close(); |
| if (i == N) |
| { |
| Assert.Fail("should have failed on commits prior to last " + N); |
| } |
| } |
| catch (System.IO.IOException e) |
| { |
| if (i != N) |
| { |
| throw e; |
| } |
| } |
| if (i < N) |
| { |
| dir.DeleteFile(IndexFileNames.FileNameFromGeneration(IndexFileNames.SEGMENTS, "", gen)); |
| } |
| gen--; |
| } |
| |
| dir.Close(); |
| } |
| } |
| |
| /* |
| * Test a deletion policy that keeps last N commits |
| * around, with reader doing deletes. |
| */ |
| [Test] |
| public virtual void TestKeepLastNDeletionPolicyWithReader() |
| { |
| int N = 10; |
| |
| for (int pass = 0; pass < 2; pass++) |
| { |
| bool useCompoundFile = (pass % 2) != 0; |
| |
| KeepLastNDeletionPolicy policy = new KeepLastNDeletionPolicy(this, N); |
| |
| Directory dir = new RAMDirectory(); |
| IndexWriter writer = new IndexWriter(dir, new WhitespaceAnalyzer(), true, policy, IndexWriter.MaxFieldLength.UNLIMITED); |
| writer.UseCompoundFile = useCompoundFile; |
| writer.Close(); |
| Term searchTerm = new Term("content", "aaa"); |
| Query query = new TermQuery(searchTerm); |
| |
| for (int i = 0; i < N + 1; i++) |
| { |
| writer = new IndexWriter(dir, new WhitespaceAnalyzer(), false, policy, IndexWriter.MaxFieldLength.UNLIMITED); |
| writer.UseCompoundFile = useCompoundFile; |
| for (int j = 0; j < 17; j++) |
| { |
| AddDoc(writer); |
| } |
| // this is a commit |
| writer.Close(); |
| IndexReader reader = IndexReader.Open(dir, policy, false); |
| reader.DeleteDocument(3 * i + 1); |
| reader.SetNorm(4 * i + 1, "content", 2.0F); |
| IndexSearcher searcher = new IndexSearcher(reader); |
| ScoreDoc[] hits = searcher.Search(query, null, 1000).ScoreDocs; |
| Assert.AreEqual(16 * (1 + i), hits.Length); |
| // this is a commit |
| reader.Close(); |
| searcher.Close(); |
| } |
| writer = new IndexWriter(dir, new WhitespaceAnalyzer(), false, policy, IndexWriter.MaxFieldLength.UNLIMITED); |
| writer.UseCompoundFile = useCompoundFile; |
| writer.Optimize(); |
| // this is a commit |
| writer.Close(); |
| |
| Assert.AreEqual(2 * (N + 2), policy.numOnInit); |
| Assert.AreEqual(2 * (N + 2) - 1, policy.numOnCommit); |
| |
| IndexSearcher searcher2 = new IndexSearcher(dir, false); |
| ScoreDoc[] hits2 = searcher2.Search(query, null, 1000).ScoreDocs; |
| Assert.AreEqual(176, hits2.Length); |
| |
| // Simplistic check: just verify only the past N segments_N's still |
| // exist, and, I can open a reader on each: |
| long gen = SegmentInfos.GetCurrentSegmentGeneration(dir); |
| |
| dir.DeleteFile(IndexFileNames.SEGMENTS_GEN); |
| int expectedCount = 176; |
| |
| for (int i = 0; i < N + 1; i++) |
| { |
| try |
| { |
| IndexReader reader = IndexReader.Open(dir, true); |
| |
| // Work backwards in commits on what the expected |
| // count should be. |
| searcher2 = new IndexSearcher(reader); |
| hits2 = searcher2.Search(query, null, 1000).ScoreDocs; |
| if (i > 1) |
| { |
| if (i % 2 == 0) |
| { |
| expectedCount += 1; |
| } |
| else |
| { |
| expectedCount -= 17; |
| } |
| } |
| Assert.AreEqual(expectedCount, hits2.Length); |
| searcher2.Close(); |
| reader.Close(); |
| if (i == N) |
| { |
| Assert.Fail("should have failed on commits before last 5"); |
| } |
| } |
| catch (System.IO.IOException e) |
| { |
| if (i != N) |
| { |
| throw e; |
| } |
| } |
| if (i < N) |
| { |
| dir.DeleteFile(IndexFileNames.FileNameFromGeneration(IndexFileNames.SEGMENTS, "", gen)); |
| } |
| gen--; |
| } |
| |
| dir.Close(); |
| } |
| } |
| |
| /* |
| * Test a deletion policy that keeps last N commits |
| * around, through creates. |
| */ |
| [Test] |
| public virtual void TestKeepLastNDeletionPolicyWithCreates() |
| { |
| int N = 10; |
| |
| for (int pass = 0; pass < 2; pass++) |
| { |
| bool useCompoundFile = (pass % 2) != 0; |
| |
| KeepLastNDeletionPolicy policy = new KeepLastNDeletionPolicy(this, N); |
| |
| Directory dir = new RAMDirectory(); |
| IndexWriter writer = new IndexWriter(dir, new WhitespaceAnalyzer(), true, policy, IndexWriter.MaxFieldLength.UNLIMITED); |
| writer.SetMaxBufferedDocs(10); |
| writer.UseCompoundFile = useCompoundFile; |
| writer.Close(); |
| Term searchTerm = new Term("content", "aaa"); |
| Query query = new TermQuery(searchTerm); |
| |
| for (int i = 0; i < N + 1; i++) |
| { |
| |
| writer = new IndexWriter(dir, new WhitespaceAnalyzer(), false, policy, IndexWriter.MaxFieldLength.UNLIMITED); |
| writer.SetMaxBufferedDocs(10); |
| writer.UseCompoundFile = useCompoundFile; |
| for (int j = 0; j < 17; j++) |
| { |
| AddDoc(writer); |
| } |
| // this is a commit |
| writer.Close(); |
| IndexReader reader = IndexReader.Open(dir, policy, false); |
| reader.DeleteDocument(3); |
| reader.SetNorm(5, "content", 2.0F); |
| IndexSearcher searcher = new IndexSearcher(reader); |
| ScoreDoc[] hits = searcher.Search(query, null, 1000).ScoreDocs; |
| Assert.AreEqual(16, hits.Length); |
| // this is a commit |
| reader.Close(); |
| searcher.Close(); |
| |
| writer = new IndexWriter(dir, new WhitespaceAnalyzer(), true, policy, IndexWriter.MaxFieldLength.UNLIMITED); |
| // This will not commit: there are no changes |
| // pending because we opened for "create": |
| writer.Close(); |
| } |
| |
| Assert.AreEqual(1 + 3 * (N + 1), policy.numOnInit); |
| Assert.AreEqual(3 * (N + 1), policy.numOnCommit); |
| |
| IndexSearcher searcher2 = new IndexSearcher(dir, false); |
| ScoreDoc[] hits2 = searcher2.Search(query, null, 1000).ScoreDocs; |
| Assert.AreEqual(0, hits2.Length); |
| |
| // Simplistic check: just verify only the past N segments_N's still |
| // exist, and, I can open a reader on each: |
| long gen = SegmentInfos.GetCurrentSegmentGeneration(dir); |
| |
| dir.DeleteFile(IndexFileNames.SEGMENTS_GEN); |
| int expectedCount = 0; |
| |
| for (int i = 0; i < N + 1; i++) |
| { |
| try |
| { |
| IndexReader reader = IndexReader.Open(dir, true); |
| |
| // Work backwards in commits on what the expected |
| // count should be. |
| searcher2 = new IndexSearcher(reader); |
| hits2 = searcher2.Search(query, null, 1000).ScoreDocs; |
| Assert.AreEqual(expectedCount, hits2.Length); |
| searcher2.Close(); |
| if (expectedCount == 0) |
| { |
| expectedCount = 16; |
| } |
| else if (expectedCount == 16) |
| { |
| expectedCount = 17; |
| } |
| else if (expectedCount == 17) |
| { |
| expectedCount = 0; |
| } |
| reader.Close(); |
| if (i == N) |
| { |
| Assert.Fail("should have failed on commits before last " + N); |
| } |
| } |
| catch (System.IO.IOException e) |
| { |
| if (i != N) |
| { |
| throw e; |
| } |
| } |
| if (i < N) |
| { |
| dir.DeleteFile(IndexFileNames.FileNameFromGeneration(IndexFileNames.SEGMENTS, "", gen)); |
| } |
| gen--; |
| } |
| |
| dir.Close(); |
| } |
| } |
| |
| private void AddDoc(IndexWriter writer) |
| { |
| Document doc = new Document(); |
| doc.Add(new Field("content", "aaa", Field.Store.NO, Field.Index.ANALYZED)); |
| writer.AddDocument(doc); |
| } |
| } |
| } |