/* * 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 NUnit.Framework; using Document = Lucene.Net.Documents.Document; using Field = Lucene.Net.Documents.Field; using IndexCommitPoint = Lucene.Net.Index.IndexCommitPoint; using IndexWriter = Lucene.Net.Index.IndexWriter; using KeepOnlyLastCommitDeletionPolicy = Lucene.Net.Index.KeepOnlyLastCommitDeletionPolicy; using SnapshotDeletionPolicy = Lucene.Net.Index.SnapshotDeletionPolicy; using Directory = Lucene.Net.Store.Directory; using FSDirectory = Lucene.Net.Store.FSDirectory; using IndexInput = Lucene.Net.Store.IndexInput; using MockRAMDirectory = Lucene.Net.Store.MockRAMDirectory; using LuceneTestCase = Lucene.Net.Util.LuceneTestCase; using _TestUtil = Lucene.Net.Util._TestUtil; using StandardAnalyzer = Lucene.Net.Analysis.Standard.StandardAnalyzer; using TestIndexWriter = Lucene.Net.Index.TestIndexWriter; namespace Lucene.Net { // // This was developed for Lucene In Action, // http://lucenebook.com // [TestFixture] public class TestSnapshotDeletionPolicy : LuceneTestCase { private class AnonymousClassThread : SupportClass.ThreadClass { public AnonymousClassThread(long stopTime, Lucene.Net.Index.IndexWriter writer, TestSnapshotDeletionPolicy enclosingInstance) { InitBlock(stopTime, writer, enclosingInstance); } private void InitBlock(long stopTime, Lucene.Net.Index.IndexWriter writer, TestSnapshotDeletionPolicy enclosingInstance) { this.stopTime = stopTime; this.writer = writer; this.enclosingInstance = enclosingInstance; } private long stopTime; private Lucene.Net.Index.IndexWriter writer; private TestSnapshotDeletionPolicy enclosingInstance; public TestSnapshotDeletionPolicy Enclosing_Instance { get { return enclosingInstance; } } override public void Run() { Document doc = new Document(); doc.Add(new Field("content", "aaa", Field.Store.YES, Field.Index.TOKENIZED, Field.TermVector.WITH_POSITIONS_OFFSETS)); while ((System.DateTime.Now.Ticks - 621355968000000000) / 10000 < stopTime) { for (int i = 0; i < 27; i++) { try { writer.AddDocument(doc); } catch (System.IO.IOException cie) { System.SystemException re = new System.SystemException("addDocument failed", cie); throw re; } } try { System.Threading.Thread.Sleep(new System.TimeSpan((System.Int64) 10000 * 1)); } catch (System.Threading.ThreadInterruptedException) { SupportClass.ThreadClass.Current().Interrupt(); } } } } public const System.String INDEX_PATH = "test.snapshots"; [Test] public virtual void TestSnapshotDeletionPolicy_Renamed_Method() { System.IO.FileInfo dir = new System.IO.FileInfo(System.IO.Path.Combine(SupportClass.AppSettings.Get("tempDir", ""), INDEX_PATH)); try { Directory fsDir = FSDirectory.GetDirectory(dir); RunTest(fsDir); fsDir.Close(); } finally { _TestUtil.RmDir(dir); } MockRAMDirectory dir2 = new MockRAMDirectory(); RunTest(dir2); } private void RunTest(Directory dir) { // Run for ~7 seconds long stopTime = (System.DateTime.Now.Ticks - 621355968000000000) / 10000 + 7000; SnapshotDeletionPolicy dp = new SnapshotDeletionPolicy(new KeepOnlyLastCommitDeletionPolicy()); IndexWriter writer = new IndexWriter(dir, true, new StandardAnalyzer(), dp); // Force frequent commits writer.SetMaxBufferedDocs(2); SupportClass.ThreadClass t = new AnonymousClassThread(stopTime, writer, this); t.Start(); // While the above indexing thread is running, take many // backups: while ((System.DateTime.Now.Ticks - 621355968000000000) / 10000 < stopTime) { BackupIndex(dir, dp); try { System.Threading.Thread.Sleep(new System.TimeSpan((System.Int64) 10000 * 20)); } catch (System.Threading.ThreadInterruptedException) { SupportClass.ThreadClass.Current().Interrupt(); } if (!t.IsAlive) break; } try { t.Join(); } catch (System.Threading.ThreadInterruptedException) { SupportClass.ThreadClass.Current().Interrupt(); } // Add one more document to force writer to commit a // final segment, so deletion policy has a chance to // delete again: Document doc = new Document(); doc.Add(new Field("content", "aaa", Field.Store.YES, Field.Index.TOKENIZED, Field.TermVector.WITH_POSITIONS_OFFSETS)); writer.AddDocument(doc); // Make sure we don't have any leftover files in the // directory: writer.Close(); TestIndexWriter.AssertNoUnreferencedFiles(dir, "some files were not deleted but should have been"); } /// Example showing how to use the SnapshotDeletionPolicy /// to take a backup. This method does not really do a /// backup; instead, it reads every byte of every file /// just to test that the files indeed exist and are /// readable even while the index is changing. /// public virtual void BackupIndex(Directory dir, SnapshotDeletionPolicy dp) { // To backup an index we first take a snapshot: IndexCommitPoint cp = dp.Snapshot(); try { // While we hold the snapshot, and nomatter how long // we take to do the backup, the IndexWriter will // never delete the files in the snapshot: System.Collections.ICollection files = cp.GetFileNames(); System.Collections.IEnumerator it = files.GetEnumerator(); while (it.MoveNext()) { System.String fileName = (System.String) it.Current; // NOTE: in a real backup you would not use // readFile; you would need to use something else // that copies the file to a backup location. This // could even be a spawned shell process (eg "tar", // "zip") that takes the list of files and builds a // backup. ReadFile(dir, fileName); } } finally { // Make sure to release the snapshot, otherwise these // files will never be deleted during this IndexWriter // session: dp.Release(); } } internal byte[] buffer = new byte[4096]; private void ReadFile(Directory dir, System.String name) { IndexInput input = dir.OpenInput(name); try { long size = dir.FileLength(name); long bytesLeft = size; while (bytesLeft > 0) { int numToRead; if (bytesLeft < buffer.Length) numToRead = (int) bytesLeft; else numToRead = buffer.Length; input.ReadBytes(buffer, 0, numToRead, false); bytesLeft -= numToRead; } // Don't do this in your real backups! This is just // to force a backup to take a somewhat long time, to // make sure we are exercising the fact that the // IndexWriter should not delete this file even when I // take my time reading it. try { System.Threading.Thread.Sleep(new System.TimeSpan((System.Int64) 10000 * 1)); } catch (System.Threading.ThreadInterruptedException) { SupportClass.ThreadClass.Current().Interrupt(); } } finally { input.Close(); } } } }