blob: f5e784a66b7cf387e419693d6aa41834f4cce15a [file] [log] [blame]
/*
* 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 Lucene.Net.Support;
using NUnit.Framework;
using WhitespaceAnalyzer = Lucene.Net.Analysis.WhitespaceAnalyzer;
using Document = Lucene.Net.Documents.Document;
using Field = Lucene.Net.Documents.Field;
using Index = Lucene.Net.Documents.Field.Index;
using Store = Lucene.Net.Documents.Field.Store;
using TermVector = Lucene.Net.Documents.Field.TermVector;
using AlreadyClosedException = Lucene.Net.Store.AlreadyClosedException;
using Directory = Lucene.Net.Store.Directory;
using MockRAMDirectory = Lucene.Net.Store.MockRAMDirectory;
using IndexSearcher = Lucene.Net.Search.IndexSearcher;
using Query = Lucene.Net.Search.Query;
using TermQuery = Lucene.Net.Search.TermQuery;
using LuceneTestCase = Lucene.Net.Util.LuceneTestCase;
using _TestUtil = Lucene.Net.Util._TestUtil;
namespace Lucene.Net.Index
{
[TestFixture]
public class TestIndexWriterReader:LuceneTestCase
{
private class AnonymousClassThread:ThreadClass
{
public AnonymousClassThread(long endTime, Lucene.Net.Index.IndexWriter writer, Lucene.Net.Store.Directory[] dirs, System.Collections.IList excs, TestIndexWriterReader enclosingInstance)
{
InitBlock(endTime, writer, dirs, excs, enclosingInstance);
}
private void InitBlock(long endTime, Lucene.Net.Index.IndexWriter writer, Lucene.Net.Store.Directory[] dirs, System.Collections.IList excs, TestIndexWriterReader enclosingInstance)
{
this.endTime = endTime;
this.writer = writer;
this.dirs = dirs;
this.excs = excs;
this.enclosingInstance = enclosingInstance;
}
private long endTime;
private Lucene.Net.Index.IndexWriter writer;
private Lucene.Net.Store.Directory[] dirs;
private System.Collections.IList excs;
private TestIndexWriterReader enclosingInstance;
public TestIndexWriterReader Enclosing_Instance
{
get
{
return enclosingInstance;
}
}
override public void Run()
{
while ((DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond) < endTime)
{
try
{
writer.AddIndexesNoOptimize(dirs);
}
catch (System.Exception t)
{
excs.Add(t);
throw new System.SystemException("", t);
}
}
}
}
private class AnonymousClassThread1:ThreadClass
{
public AnonymousClassThread1(long endTime, Lucene.Net.Index.IndexWriter writer, System.Collections.IList excs, TestIndexWriterReader enclosingInstance)
{
InitBlock(endTime, writer, excs, enclosingInstance);
}
private void InitBlock(long endTime, Lucene.Net.Index.IndexWriter writer, System.Collections.IList excs, TestIndexWriterReader enclosingInstance)
{
this.endTime = endTime;
this.writer = writer;
this.excs = excs;
this.enclosingInstance = enclosingInstance;
}
private long endTime;
private Lucene.Net.Index.IndexWriter writer;
private System.Collections.IList excs;
private TestIndexWriterReader enclosingInstance;
public TestIndexWriterReader Enclosing_Instance
{
get
{
return enclosingInstance;
}
}
override public void Run()
{
int count = 0;
System.Random r = new System.Random();
while ((DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond) < endTime)
{
try
{
for (int docUpto = 0; docUpto < 10; docUpto++)
{
writer.AddDocument(Lucene.Net.Index.TestIndexWriterReader.CreateDocument(10 * count + docUpto, "test", 4));
}
count++;
int limit = count * 10;
for (int delUpto = 0; delUpto < 5; delUpto++)
{
int x = r.Next(limit);
writer.DeleteDocuments(new Term("field3", "b" + x));
}
}
catch (System.Exception t)
{
excs.Add(t);
throw new System.SystemException("", t);
}
}
}
}
internal static System.IO.StreamWriter infoStream;
public class HeavyAtomicInt
{
private int value_Renamed;
public HeavyAtomicInt(int start)
{
value_Renamed = start;
}
public virtual int AddAndGet(int inc)
{
lock (this)
{
value_Renamed += inc;
return value_Renamed;
}
}
public virtual int IncrementAndGet()
{
lock (this)
{
value_Renamed++;
return value_Renamed;
}
}
public virtual int IntValue()
{
lock (this)
{
return value_Renamed;
}
}
}
public static int Count(Term t, IndexReader r)
{
int count = 0;
TermDocs td = r.TermDocs(t);
while (td.Next())
{
var d = td.Doc;
count++;
}
td.Close();
return count;
}
[Test]
public virtual void TestUpdateDocument()
{
bool optimize = true;
Directory dir1 = new MockRAMDirectory();
IndexWriter writer = new IndexWriter(dir1, new WhitespaceAnalyzer(), IndexWriter.MaxFieldLength.LIMITED);
// create the index
CreateIndexNoClose(!optimize, "index1", writer);
// writer.flush(false, true, true);
// get a reader
IndexReader r1 = writer.GetReader();
Assert.IsTrue(r1.IsCurrent());
System.String id10 = r1.Document(10).GetField("id").StringValue;
Document newDoc = r1.Document(10);
newDoc.RemoveField("id");
newDoc.Add(new Field("id", System.Convert.ToString(8000), Field.Store.YES, Field.Index.NOT_ANALYZED));
writer.UpdateDocument(new Term("id", id10), newDoc);
Assert.IsFalse(r1.IsCurrent());
IndexReader r2 = writer.GetReader();
Assert.IsTrue(r2.IsCurrent());
Assert.AreEqual(0, Count(new Term("id", id10), r2));
Assert.AreEqual(1, Count(new Term("id", System.Convert.ToString(8000)), r2));
r1.Close();
writer.Close();
Assert.IsTrue(r2.IsCurrent());
IndexReader r3 = IndexReader.Open(dir1, true);
Assert.IsTrue(r3.IsCurrent());
Assert.IsTrue(r2.IsCurrent());
Assert.AreEqual(0, Count(new Term("id", id10), r3));
Assert.AreEqual(1, Count(new Term("id", System.Convert.ToString(8000)), r3));
writer = new IndexWriter(dir1, new WhitespaceAnalyzer(), IndexWriter.MaxFieldLength.LIMITED);
Document doc = new Document();
doc.Add(new Field("field", "a b c", Field.Store.NO, Field.Index.ANALYZED));
writer.AddDocument(doc);
Assert.IsTrue(r2.IsCurrent());
Assert.IsTrue(r3.IsCurrent());
writer.Close();
Assert.IsFalse(r2.IsCurrent());
Assert.IsTrue(!r3.IsCurrent());
r2.Close();
r3.Close();
dir1.Close();
}
/// <summary> Test using IW.addIndexes
///
/// </summary>
/// <throws> Exception </throws>
[Test]
public virtual void TestAddIndexes()
{
bool optimize = false;
Directory dir1 = new MockRAMDirectory();
IndexWriter writer = new IndexWriter(dir1, new WhitespaceAnalyzer(), IndexWriter.MaxFieldLength.LIMITED);
writer.SetInfoStream(infoStream);
// create the index
CreateIndexNoClose(!optimize, "index1", writer);
writer.Flush(false, true, true);
// create a 2nd index
Directory dir2 = new MockRAMDirectory();
IndexWriter writer2 = new IndexWriter(dir2, new WhitespaceAnalyzer(), IndexWriter.MaxFieldLength.LIMITED);
writer2.SetInfoStream(infoStream);
CreateIndexNoClose(!optimize, "index2", writer2);
writer2.Close();
IndexReader r0 = writer.GetReader();
Assert.IsTrue(r0.IsCurrent());
writer.AddIndexesNoOptimize(new Directory[]{dir2});
Assert.IsFalse(r0.IsCurrent());
r0.Close();
IndexReader r1 = writer.GetReader();
Assert.IsTrue(r1.IsCurrent());
writer.Commit();
Assert.IsFalse(r1.IsCurrent());
Assert.AreEqual(200, r1.MaxDoc);
int index2df = r1.DocFreq(new Term("indexname", "index2"));
Assert.AreEqual(100, index2df);
// verify the docs are from different indexes
Document doc5 = r1.Document(5);
Assert.AreEqual("index1", doc5.Get("indexname"));
Document doc150 = r1.Document(150);
Assert.AreEqual("index2", doc150.Get("indexname"));
r1.Close();
writer.Close();
dir1.Close();
}
[Test]
public virtual void TestAddIndexes2()
{
bool optimize = false;
Directory dir1 = new MockRAMDirectory();
IndexWriter writer = new IndexWriter(dir1, new WhitespaceAnalyzer(), IndexWriter.MaxFieldLength.LIMITED);
writer.SetInfoStream(infoStream);
// create a 2nd index
Directory dir2 = new MockRAMDirectory();
IndexWriter writer2 = new IndexWriter(dir2, new WhitespaceAnalyzer(), IndexWriter.MaxFieldLength.LIMITED);
writer2.SetInfoStream(infoStream);
CreateIndexNoClose(!optimize, "index2", writer2);
writer2.Close();
writer.AddIndexesNoOptimize(new Directory[]{dir2});
writer.AddIndexesNoOptimize(new Directory[]{dir2});
writer.AddIndexesNoOptimize(new Directory[]{dir2});
writer.AddIndexesNoOptimize(new Directory[]{dir2});
writer.AddIndexesNoOptimize(new Directory[]{dir2});
IndexReader r1 = writer.GetReader();
Assert.AreEqual(500, r1.MaxDoc);
r1.Close();
writer.Close();
dir1.Close();
}
/// <summary> Deletes using IW.deleteDocuments
///
/// </summary>
/// <throws> Exception </throws>
[Test]
public virtual void TestDeleteFromIndexWriter()
{
bool optimize = true;
Directory dir1 = new MockRAMDirectory();
IndexWriter writer = new IndexWriter(dir1, new WhitespaceAnalyzer(), IndexWriter.MaxFieldLength.LIMITED);
writer.ReaderTermsIndexDivisor = 2;
writer.SetInfoStream(infoStream);
// create the index
CreateIndexNoClose(!optimize, "index1", writer);
writer.Flush(false, true, true);
// get a reader
IndexReader r1 = writer.GetReader();
System.String id10 = r1.Document(10).GetField("id").StringValue;
// deleted IW docs should not show up in the next getReader
writer.DeleteDocuments(new Term("id", id10));
IndexReader r2 = writer.GetReader();
Assert.AreEqual(1, Count(new Term("id", id10), r1));
Assert.AreEqual(0, Count(new Term("id", id10), r2));
System.String id50 = r1.Document(50).GetField("id").StringValue;
Assert.AreEqual(1, Count(new Term("id", id50), r1));
writer.DeleteDocuments(new Term("id", id50));
IndexReader r3 = writer.GetReader();
Assert.AreEqual(0, Count(new Term("id", id10), r3));
Assert.AreEqual(0, Count(new Term("id", id50), r3));
System.String id75 = r1.Document(75).GetField("id").StringValue;
writer.DeleteDocuments(new TermQuery(new Term("id", id75)));
IndexReader r4 = writer.GetReader();
Assert.AreEqual(1, Count(new Term("id", id75), r3));
Assert.AreEqual(0, Count(new Term("id", id75), r4));
r1.Close();
r2.Close();
r3.Close();
r4.Close();
writer.Close();
// reopen the writer to verify the delete made it to the directory
writer = new IndexWriter(dir1, new WhitespaceAnalyzer(), IndexWriter.MaxFieldLength.LIMITED);
writer.SetInfoStream(infoStream);
IndexReader w2r1 = writer.GetReader();
Assert.AreEqual(0, Count(new Term("id", id10), w2r1));
w2r1.Close();
writer.Close();
dir1.Close();
}
[Test]
public virtual void TestAddIndexesAndDoDeletesThreads()
{
int numIter = 5;
int numDirs = 3;
Directory mainDir = new MockRAMDirectory();
IndexWriter mainWriter = new IndexWriter(mainDir, new WhitespaceAnalyzer(), IndexWriter.MaxFieldLength.LIMITED);
mainWriter.SetInfoStream(infoStream);
AddDirectoriesThreads addDirThreads = new AddDirectoriesThreads(this, numIter, mainWriter);
addDirThreads.LaunchThreads(numDirs);
addDirThreads.JoinThreads();
//Assert.AreEqual(100 + numDirs * (3 * numIter / 4) * addDirThreads.NUM_THREADS
// * addDirThreads.NUM_INIT_DOCS, addDirThreads.mainWriter.numDocs());
Assert.AreEqual(addDirThreads.count.IntValue(), addDirThreads.mainWriter.NumDocs());
addDirThreads.Close(true);
Assert.IsTrue(addDirThreads.failures.Count == 0);
_TestUtil.CheckIndex(mainDir);
IndexReader reader = IndexReader.Open(mainDir, true);
Assert.AreEqual(addDirThreads.count.IntValue(), reader.NumDocs());
//Assert.AreEqual(100 + numDirs * (3 * numIter / 4) * addDirThreads.NUM_THREADS
// * addDirThreads.NUM_INIT_DOCS, reader.numDocs());
reader.Close();
addDirThreads.CloseDir();
mainDir.Close();
}
private class DeleteThreads
{
private class AnonymousClassThread2:ThreadClass
{
public AnonymousClassThread2(DeleteThreads enclosingInstance)
{
InitBlock(enclosingInstance);
}
private void InitBlock(DeleteThreads enclosingInstance)
{
this.enclosingInstance = enclosingInstance;
}
private DeleteThreads enclosingInstance;
public DeleteThreads Enclosing_Instance
{
get
{
return enclosingInstance;
}
}
override public void Run()
{
try
{
Term term = Enclosing_Instance.GetDeleteTerm();
Enclosing_Instance.mainWriter.DeleteDocuments(term);
lock (Enclosing_Instance.deletedTerms.SyncRoot)
{
Enclosing_Instance.deletedTerms.Add(term);
}
}
catch (System.Exception t)
{
Enclosing_Instance.Handle(t);
}
}
}
private void InitBlock(TestIndexWriterReader enclosingInstance)
{
this.enclosingInstance = enclosingInstance;
threads = new ThreadClass[NUM_THREADS];
}
private TestIndexWriterReader enclosingInstance;
public TestIndexWriterReader Enclosing_Instance
{
get
{
return enclosingInstance;
}
}
internal const int NUM_THREADS = 5;
internal ThreadClass[] threads;
internal IndexWriter mainWriter;
internal System.Collections.IList deletedTerms = new System.Collections.ArrayList();
internal System.Collections.ArrayList toDeleteTerms = new System.Collections.ArrayList();
internal System.Random random;
internal System.Collections.IList failures = new System.Collections.ArrayList();
public DeleteThreads(TestIndexWriterReader enclosingInstance, IndexWriter mainWriter)
{
InitBlock(enclosingInstance);
this.mainWriter = mainWriter;
IndexReader reader = mainWriter.GetReader();
int maxDoc = reader.MaxDoc;
random = Enclosing_Instance.NewRandom();
int iter = random.Next(maxDoc);
for (int x = 0; x < iter; x++)
{
int doc = random.Next(iter);
System.String id = reader.Document(doc).Get("id");
toDeleteTerms.Add(new Term("id", id));
}
}
internal virtual Term GetDeleteTerm()
{
lock (toDeleteTerms.SyncRoot)
{
System.Object tempObject;
tempObject = toDeleteTerms[0];
toDeleteTerms.RemoveAt(0);
return (Term) tempObject;
}
}
internal virtual void LaunchThreads(int numIter)
{
for (int i = 0; i < NUM_THREADS; i++)
{
threads[i] = new AnonymousClassThread2(this);
}
}
internal virtual void Handle(System.Exception t)
{
System.Console.Out.WriteLine(t.StackTrace);
lock (failures.SyncRoot)
{
failures.Add(t);
}
}
internal virtual void JoinThreads()
{
for (int i = 0; i < NUM_THREADS; i++)
try
{
threads[i].Join();
}
catch (System.Threading.ThreadInterruptedException ie)
{
throw;
}
}
}
private class AddDirectoriesThreads
{
private class AnonymousClassThread2:ThreadClass
{
public AnonymousClassThread2(int numIter, AddDirectoriesThreads enclosingInstance)
{
InitBlock(numIter, enclosingInstance);
}
private void InitBlock(int numIter, AddDirectoriesThreads enclosingInstance)
{
this.numIter = numIter;
this.enclosingInstance = enclosingInstance;
}
private int numIter;
private AddDirectoriesThreads enclosingInstance;
public AddDirectoriesThreads Enclosing_Instance
{
get
{
return enclosingInstance;
}
}
override public void Run()
{
try
{
Directory[] dirs = new Directory[Enclosing_Instance.numDirs];
for (int k = 0; k < Enclosing_Instance.numDirs; k++)
dirs[k] = new MockRAMDirectory(Enclosing_Instance.addDir);
//int j = 0;
//while (true) {
// System.out.println(Thread.currentThread().getName() + ": iter
// j=" + j);
for (int x = 0; x < numIter; x++)
{
// only do addIndexesNoOptimize
Enclosing_Instance.DoBody(x, dirs);
}
//if (numIter > 0 && j == numIter)
// break;
//doBody(j++, dirs);
//doBody(5, dirs);
//}
}
catch (System.Exception t)
{
Enclosing_Instance.Handle(t);
}
}
}
private void InitBlock(TestIndexWriterReader enclosingInstance)
{
this.enclosingInstance = enclosingInstance;
threads = new ThreadClass[NUM_THREADS];
}
private TestIndexWriterReader enclosingInstance;
public TestIndexWriterReader Enclosing_Instance
{
get
{
return enclosingInstance;
}
}
internal Directory addDir;
internal const int NUM_THREADS = 5;
internal const int NUM_INIT_DOCS = 100;
internal int numDirs;
internal ThreadClass[] threads;
internal IndexWriter mainWriter;
internal System.Collections.IList failures = new System.Collections.ArrayList();
internal IndexReader[] readers;
internal bool didClose = false;
internal HeavyAtomicInt count = new HeavyAtomicInt(0);
internal HeavyAtomicInt numAddIndexesNoOptimize = new HeavyAtomicInt(0);
public AddDirectoriesThreads(TestIndexWriterReader enclosingInstance, int numDirs, IndexWriter mainWriter)
{
InitBlock(enclosingInstance);
this.numDirs = numDirs;
this.mainWriter = mainWriter;
addDir = new MockRAMDirectory();
IndexWriter writer = new IndexWriter(addDir, new WhitespaceAnalyzer(), IndexWriter.MaxFieldLength.LIMITED);
writer.SetMaxBufferedDocs(2);
for (int i = 0; i < NUM_INIT_DOCS; i++)
{
Document doc = Lucene.Net.Index.TestIndexWriterReader.CreateDocument(i, "addindex", 4);
writer.AddDocument(doc);
}
writer.Close();
readers = new IndexReader[numDirs];
for (int i = 0; i < numDirs; i++)
readers[i] = IndexReader.Open(addDir, false);
}
internal virtual void JoinThreads()
{
for (int i = 0; i < NUM_THREADS; i++)
try
{
threads[i].Join();
}
catch (System.Threading.ThreadInterruptedException ie)
{
throw;
}
}
internal virtual void Close(bool doWait)
{
didClose = true;
mainWriter.Close(doWait);
}
internal virtual void CloseDir()
{
for (int i = 0; i < numDirs; i++)
readers[i].Close();
addDir.Close();
}
internal virtual void Handle(System.Exception t)
{
System.Console.Out.WriteLine(t.StackTrace);
lock (failures.SyncRoot)
{
failures.Add(t);
}
}
internal virtual void LaunchThreads(int numIter)
{
for (int i = 0; i < NUM_THREADS; i++)
{
threads[i] = new AnonymousClassThread2(numIter, this);
}
for (int i = 0; i < NUM_THREADS; i++)
threads[i].Start();
}
internal virtual void DoBody(int j, Directory[] dirs)
{
switch (j % 4)
{
case 0:
mainWriter.AddIndexesNoOptimize(dirs);
mainWriter.Optimize();
break;
case 1:
mainWriter.AddIndexesNoOptimize(dirs);
numAddIndexesNoOptimize.IncrementAndGet();
break;
case 2:
mainWriter.AddIndexes(readers);
break;
case 3:
mainWriter.Commit();
break;
}
count.AddAndGet(dirs.Length * NUM_INIT_DOCS);
}
}
[Test]
public virtual void TestIndexWriterReopenSegmentOptimize()
{
DoTestIndexWriterReopenSegment(true);
}
[Test]
public virtual void TestIndexWriterReopenSegment()
{
DoTestIndexWriterReopenSegment(false);
}
/// <summary> Tests creating a segment, then check to insure the segment can be seen via
/// IW.getReader
/// </summary>
public virtual void DoTestIndexWriterReopenSegment(bool optimize)
{
Directory dir1 = new MockRAMDirectory();
IndexWriter writer = new IndexWriter(dir1, new WhitespaceAnalyzer(), IndexWriter.MaxFieldLength.LIMITED);
writer.SetInfoStream(infoStream);
IndexReader r1 = writer.GetReader();
Assert.AreEqual(0, r1.MaxDoc);
CreateIndexNoClose(false, "index1", writer);
writer.Flush(!optimize, true, true);
IndexReader iwr1 = writer.GetReader();
Assert.AreEqual(100, iwr1.MaxDoc);
IndexReader r2 = writer.GetReader();
Assert.AreEqual(r2.MaxDoc, 100);
// add 100 documents
for (int x = 10000; x < 10000 + 100; x++)
{
Document d = CreateDocument(x, "index1", 5);
writer.AddDocument(d);
}
writer.Flush(false, true, true);
// verify the reader was reopened internally
IndexReader iwr2 = writer.GetReader();
Assert.IsTrue(iwr2 != r1);
Assert.AreEqual(200, iwr2.MaxDoc);
// should have flushed out a segment
IndexReader r3 = writer.GetReader();
Assert.IsTrue(r2 != r3);
Assert.AreEqual(200, r3.MaxDoc);
// dec ref the readers rather than close them because
// closing flushes changes to the writer
r1.Close();
iwr1.Close();
r2.Close();
r3.Close();
iwr2.Close();
writer.Close();
// test whether the changes made it to the directory
writer = new IndexWriter(dir1, new WhitespaceAnalyzer(), IndexWriter.MaxFieldLength.LIMITED);
IndexReader w2r1 = writer.GetReader();
// insure the deletes were actually flushed to the directory
Assert.AreEqual(200, w2r1.MaxDoc);
w2r1.Close();
writer.Close();
dir1.Close();
}
public static Document CreateDocument(int n, System.String indexName, int numFields)
{
System.Text.StringBuilder sb = new System.Text.StringBuilder();
Document doc = new Document();
doc.Add(new Field("id", System.Convert.ToString(n), Field.Store.YES, Field.Index.NOT_ANALYZED, TermVector.WITH_POSITIONS_OFFSETS));
doc.Add(new Field("indexname", indexName, Field.Store.YES, Field.Index.NOT_ANALYZED, TermVector.WITH_POSITIONS_OFFSETS));
sb.Append("a");
sb.Append(n);
doc.Add(new Field("field1", sb.ToString(), Field.Store.YES, Field.Index.ANALYZED, TermVector.WITH_POSITIONS_OFFSETS));
sb.Append(" b");
sb.Append(n);
for (int i = 1; i < numFields; i++)
{
doc.Add(new Field("field" + (i + 1), sb.ToString(), Field.Store.YES, Field.Index.ANALYZED, TermVector.WITH_POSITIONS_OFFSETS));
}
return doc;
}
/// <summary> Delete a document by term and return the doc id
///
/// </summary>
/// <returns>
///
/// public static int deleteDocument(Term term, IndexWriter writer) throws
/// IOException { IndexReader reader = writer.getReader(); TermDocs td =
/// reader.termDocs(term); int doc = -1; //if (td.next()) { // doc = td.doc();
/// //} //writer.deleteDocuments(term); td.close(); return doc; }
/// </returns>
public static void CreateIndex(Directory dir1, System.String indexName, bool multiSegment)
{
IndexWriter w = new IndexWriter(dir1, new WhitespaceAnalyzer(), IndexWriter.MaxFieldLength.LIMITED);
w.SetMergePolicy(new LogDocMergePolicy(w));
for (int i = 0; i < 100; i++)
{
w.AddDocument(CreateDocument(i, indexName, 4));
if (multiSegment && (i % 10) == 0)
{
}
}
if (!multiSegment)
{
w.Optimize();
}
w.Close();
}
public static void CreateIndexNoClose(bool multiSegment, System.String indexName, IndexWriter w)
{
for (int i = 0; i < 100; i++)
{
w.AddDocument(CreateDocument(i, indexName, 4));
}
if (!multiSegment)
{
w.Optimize();
}
}
private class MyWarmer:IndexWriter.IndexReaderWarmer
{
internal int warmCount;
public override void Warm(IndexReader reader)
{
warmCount++;
}
}
[Test]
public virtual void TestMergeWarmer()
{
Directory dir1 = new MockRAMDirectory();
IndexWriter writer = new IndexWriter(dir1, new WhitespaceAnalyzer(), IndexWriter.MaxFieldLength.LIMITED);
writer.SetInfoStream(infoStream);
// create the index
CreateIndexNoClose(false, "test", writer);
// get a reader to put writer into near real-time mode
IndexReader r1 = writer.GetReader();
// Enroll warmer
MyWarmer warmer = new MyWarmer();
writer.MergedSegmentWarmer = warmer;
writer.MergeFactor = 2;
writer.SetMaxBufferedDocs(2);
for (int i = 0; i < 100; i++)
{
writer.AddDocument(CreateDocument(i, "test", 4));
}
((ConcurrentMergeScheduler) writer.MergeScheduler).Sync();
Assert.IsTrue(warmer.warmCount > 0);
int count = warmer.warmCount;
writer.AddDocument(CreateDocument(17, "test", 4));
writer.Optimize();
Assert.IsTrue(warmer.warmCount > count);
writer.Close();
r1.Close();
dir1.Close();
}
[Test]
public virtual void TestAfterCommit()
{
Directory dir1 = new MockRAMDirectory();
IndexWriter writer = new IndexWriter(dir1, new WhitespaceAnalyzer(), IndexWriter.MaxFieldLength.LIMITED);
writer.SetInfoStream(infoStream);
// create the index
CreateIndexNoClose(false, "test", writer);
// get a reader to put writer into near real-time mode
IndexReader r1 = writer.GetReader();
_TestUtil.CheckIndex(dir1);
writer.Commit();
_TestUtil.CheckIndex(dir1);
Assert.AreEqual(100, r1.NumDocs());
for (int i = 0; i < 10; i++)
{
writer.AddDocument(CreateDocument(i, "test", 4));
}
((ConcurrentMergeScheduler) writer.MergeScheduler).Sync();
IndexReader r2 = r1.Reopen();
if (r2 != r1)
{
r1.Close();
r1 = r2;
}
Assert.AreEqual(110, r1.NumDocs());
writer.Close();
r1.Close();
dir1.Close();
}
// Make sure reader remains usable even if IndexWriter closes
[Test]
public virtual void TestAfterClose()
{
Directory dir1 = new MockRAMDirectory();
IndexWriter writer = new IndexWriter(dir1, new WhitespaceAnalyzer(), IndexWriter.MaxFieldLength.LIMITED);
writer.SetInfoStream(infoStream);
// create the index
CreateIndexNoClose(false, "test", writer);
IndexReader r = writer.GetReader();
writer.Close();
_TestUtil.CheckIndex(dir1);
// reader should remain usable even after IndexWriter is closed:
Assert.AreEqual(100, r.NumDocs());
Query q = new TermQuery(new Term("indexname", "test"));
Assert.AreEqual(100, new IndexSearcher(r).Search(q, 10).TotalHits);
Assert.Throws<AlreadyClosedException>(() => r.Reopen(), "failed to hit AlreadyClosedException");
r.Close();
dir1.Close();
}
// Stress test reopen during addIndexes
[Test]
public virtual void TestDuringAddIndexes()
{
MockRAMDirectory dir1 = new MockRAMDirectory();
IndexWriter writer = new IndexWriter(dir1, new WhitespaceAnalyzer(), IndexWriter.MaxFieldLength.LIMITED);
writer.SetInfoStream(infoStream);
writer.MergeFactor = 2;
// create the index
CreateIndexNoClose(false, "test", writer);
writer.Commit();
Directory[] dirs = new Directory[10];
for (int i = 0; i < 10; i++)
{
dirs[i] = new MockRAMDirectory(dir1);
}
IndexReader r = writer.GetReader();
int NUM_THREAD = 5;
float SECONDS = 3;
long endTime = (long) ((DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond) + 1000.0 * SECONDS);
System.Collections.IList excs = (System.Collections.IList) System.Collections.ArrayList.Synchronized(new System.Collections.ArrayList(new System.Collections.ArrayList()));
ThreadClass[] threads = new ThreadClass[NUM_THREAD];
for (int i = 0; i < NUM_THREAD; i++)
{
threads[i] = new AnonymousClassThread(endTime, writer, dirs, excs, this);
threads[i].IsBackground = true;
threads[i].Start();
}
int lastCount = 0;
while ((DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond) < endTime)
{
IndexReader r2 = r.Reopen();
if (r2 != r)
{
r.Close();
r = r2;
}
Query q = new TermQuery(new Term("indexname", "test"));
int count = new IndexSearcher(r).Search(q, 10).TotalHits;
Assert.IsTrue(count >= lastCount);
lastCount = count;
}
for (int i = 0; i < NUM_THREAD; i++)
{
threads[i].Join();
}
Assert.AreEqual(0, excs.Count);
r.Close();
try
{
Assert.AreEqual(0, dir1.GetOpenDeletedFiles().Count);
}
catch
{
//DIGY:
//I think this is an expected behaviour.
//There isn't any pending files to be deleted after "writer.Close()".
//But, since lucene.java's test case is designed that way
//and I might be wrong, I will add a warning
// Assert only in debug mode, so that CheckIndex is called during release.
#if DEBUG
Assert.Inconclusive("", 0, dir1.GetOpenDeletedFiles().Count);
#endif
}
writer.Close();
_TestUtil.CheckIndex(dir1);
dir1.Close();
}
// Stress test GetReader during addIndexes. Similar to the test above. But this one uses writer.GetReader()
// instead of reader.Reopen(). (only for Lucene.Net)
[Test]
public virtual void TestDuringAddIndexes_LuceneNet()
{
MockRAMDirectory dir1 = new MockRAMDirectory();
IndexWriter writer = new IndexWriter(dir1, new WhitespaceAnalyzer(), IndexWriter.MaxFieldLength.LIMITED);
writer.SetInfoStream(infoStream);
writer.MergeFactor = 2;
// create the index
CreateIndexNoClose(false, "test", writer);
writer.Commit();
Directory[] dirs = new Directory[10];
for (int i = 0; i < 10; i++)
{
dirs[i] = new MockRAMDirectory(dir1);
}
IndexReader r = writer.GetReader();
int NUM_THREAD = 5;
float SECONDS = 3;
long endTime = (long)((DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond) + 1000.0 * SECONDS);
System.Collections.IList excs = (System.Collections.IList)System.Collections.ArrayList.Synchronized(new System.Collections.ArrayList(new System.Collections.ArrayList()));
ThreadClass[] threads = new ThreadClass[NUM_THREAD];
for (int i = 0; i < NUM_THREAD; i++)
{
threads[i] = new AnonymousClassThread(endTime, writer, dirs, excs, this);
threads[i].IsBackground = true;
threads[i].Start();
}
int lastCount = 0;
while ((DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond) < endTime)
{
using (IndexReader r2 = writer.GetReader())
{
Query q = new TermQuery(new Term("indexname", "test"));
int count = new IndexSearcher(r2).Search(q, 10).TotalHits;
Assert.IsTrue(count >= lastCount);
lastCount = count;
}
}
for (int i = 0; i < NUM_THREAD; i++)
{
threads[i].Join();
}
Assert.AreEqual(0, excs.Count);
r.Close();
Assert.AreEqual(0, dir1.GetOpenDeletedFiles().Count);
writer.Close();
_TestUtil.CheckIndex(dir1);
dir1.Close();
}
// Stress test reopen during add/delete
[Test]
public virtual void TestDuringAddDelete()
{
Directory dir1 = new MockRAMDirectory();
IndexWriter writer = new IndexWriter(dir1, new WhitespaceAnalyzer(), IndexWriter.MaxFieldLength.LIMITED);
writer.SetInfoStream(infoStream);
writer.MergeFactor = 2;
// create the index
CreateIndexNoClose(false, "test", writer);
writer.Commit();
IndexReader r = writer.GetReader();
int NUM_THREAD = 5;
float SECONDS = 3;
long endTime = (long) ((DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond) + 1000.0 * SECONDS);
System.Collections.IList excs = (System.Collections.IList) System.Collections.ArrayList.Synchronized(new System.Collections.ArrayList(new System.Collections.ArrayList()));
ThreadClass[] threads = new ThreadClass[NUM_THREAD];
for (int i = 0; i < NUM_THREAD; i++)
{
threads[i] = new AnonymousClassThread1(endTime, writer, excs, this);
threads[i].IsBackground = true;
threads[i].Start();
}
int sum = 0;
while ((DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond) < endTime)
{
IndexReader r2 = r.Reopen();
if (r2 != r)
{
r.Close();
r = r2;
}
Query q = new TermQuery(new Term("indexname", "test"));
sum += new IndexSearcher(r).Search(q, 10).TotalHits;
}
for (int i = 0; i < NUM_THREAD; i++)
{
threads[i].Join();
}
Assert.IsTrue(sum > 0);
Assert.AreEqual(0, excs.Count);
writer.Close();
_TestUtil.CheckIndex(dir1);
r.Close();
dir1.Close();
}
[Test]
public virtual void TestExpungeDeletes()
{
Directory dir = new MockRAMDirectory();
IndexWriter w = new IndexWriter(dir, new WhitespaceAnalyzer(), IndexWriter.MaxFieldLength.LIMITED);
Document doc = new Document();
doc.Add(new Field("field", "a b c", Field.Store.NO, Field.Index.ANALYZED));
Field id = new Field("id", "", Field.Store.NO, Field.Index.NOT_ANALYZED);
doc.Add(id);
id.SetValue("0");
w.AddDocument(doc);
id.SetValue("1");
w.AddDocument(doc);
w.DeleteDocuments(new Term("id", "0"));
IndexReader r = w.GetReader();
w.ExpungeDeletes();
w.Close();
r.Close();
r = IndexReader.Open(dir, true);
Assert.AreEqual(1, r.NumDocs());
Assert.IsFalse(r.HasDeletions);
r.Close();
dir.Close();
}
[Test]
public void TestDeletesNumDocs()
{
Directory dir = new MockRAMDirectory();
IndexWriter w = new IndexWriter(dir, new WhitespaceAnalyzer(),
IndexWriter.MaxFieldLength.LIMITED);
Document doc = new Document();
doc.Add(new Field("field", "a b c", Field.Store.NO, Field.Index.ANALYZED));
Field id = new Field("id", "", Field.Store.NO, Field.Index.NOT_ANALYZED);
doc.Add(id);
id.SetValue("0");
w.AddDocument(doc);
id.SetValue("1");
w.AddDocument(doc);
IndexReader r = w.GetReader();
Assert.AreEqual(2, r.NumDocs());
r.Close();
w.DeleteDocuments(new Term("id", "0"));
r = w.GetReader();
Assert.AreEqual(1, r.NumDocs());
r.Close();
w.DeleteDocuments(new Term("id", "1"));
r = w.GetReader();
Assert.AreEqual(0, r.NumDocs());
r.Close();
w.Close();
dir.Close();
}
class AnonymousIndexReaderWarmer : IndexWriter.IndexReaderWarmer
{
public override void Warm(IndexReader r)
{
IndexSearcher s = new IndexSearcher(r);
Lucene.Net.Search.TopDocs hits = s.Search(new TermQuery(new Term("foo", "bar")), 10);
Assert.AreEqual(20, hits.TotalHits);
}
}
[Test]
public void TestSegmentWarmer()
{
Directory dir = new MockRAMDirectory();
IndexWriter w = new IndexWriter(dir, new WhitespaceAnalyzer(), IndexWriter.MaxFieldLength.UNLIMITED);
w.SetMaxBufferedDocs(2);
w.GetReader().Close();
w.MergedSegmentWarmer = new AnonymousIndexReaderWarmer();
Document doc = new Document();
doc.Add(new Field("foo", "bar", Field.Store.YES, Field.Index.NOT_ANALYZED));
for (int i = 0; i < 20; i++)
{
w.AddDocument(doc);
}
w.WaitForMerges();
w.Close();
dir.Close();
}
}
}