protected internal override void SetDeleter(IndexFileDeleter deleter) { // Share deleter to our SegmentReaders: this.deleter = deleter; for (int i = 0; i < subReaders.Length; i++) { subReaders[i].SetDeleter(deleter); } }
/// <summary> Commit changes resulting from delete, undeleteAll, or /// setNorm operations /// /// If an exception is hit, then either no changes or all /// changes will have been committed to the index /// (transactional semantics). /// </summary> /// <throws> IOException if there is a low-level IO error </throws> protected internal override void DoCommit() { if (hasChanges) { if (segmentInfos != null) { // Default deleter (for backwards compatibility) is // KeepOnlyLastCommitDeleter: IndexFileDeleter deleter = new IndexFileDeleter(directory, deletionPolicy == null ? new KeepOnlyLastCommitDeletionPolicy() : deletionPolicy, segmentInfos, null, null); // Checkpoint the state we are about to change, in // case we have to roll back: StartCommit(); bool success = false; try { CommitChanges(); segmentInfos.Write(directory); success = true; } finally { if (!success) { // Rollback changes that were made to // SegmentInfos but failed to get [fully] // committed. This way this reader instance // remains consistent (matched to what's // actually in the index): RollbackCommit(); // Recompute deletable files & remove them (so // partially written .del files, etc, are // removed): deleter.Refresh(); } } // Have the deleter remove any now unreferenced // files due to this commit: deleter.Checkpoint(segmentInfos, true); if (writeLock != null) { writeLock.Release(); // release write lock writeLock = null; } } else CommitChanges(); } hasChanges = false; }
public CommitPoint(IndexFileDeleter enclosingInstance, System.Collections.ICollection commitsToDelete, Directory directory, SegmentInfos segmentInfos) { InitBlock(enclosingInstance); this.directory = directory; this.commitsToDelete = commitsToDelete; userData = segmentInfos.GetUserData(); segmentsFileName = segmentInfos.GetCurrentSegmentFileName(); version = segmentInfos.GetVersion(); generation = segmentInfos.GetGeneration(); files = segmentInfos.Files(directory, true); gen = segmentInfos.GetGeneration(); isOptimized = segmentInfos.Count == 1 && !segmentInfos.Info(0).HasDeletions(); System.Diagnostics.Debug.Assert(!segmentInfos.HasExternalSegments(directory)); }
public CommitPoint(IndexFileDeleter enclosingInstance, SegmentInfos segmentInfos) { InitBlock(enclosingInstance); segmentsFileName = segmentInfos.GetCurrentSegmentFileName(); int size = segmentInfos.Count; files = new System.Collections.ArrayList(size); files.Add(segmentsFileName); gen = segmentInfos.GetGeneration(); for (int i = 0; i < size; i++) { SegmentInfo segmentInfo = segmentInfos.Info(i); if (segmentInfo.dir == Enclosing_Instance.directory) { System.Collections.IEnumerator filesEnum = segmentInfo.Files().GetEnumerator(); while (filesEnum.MoveNext()) { files.Add(filesEnum.Current); } } } }
public CommitPoint(IndexFileDeleter enclosingInstance, ICollection <IndexCommitPoint> commitsToDelete, Directory directory, SegmentInfos segmentInfos) { InitBlock(enclosingInstance); this.directory = directory; this.commitsToDelete = commitsToDelete; segmentsFileName = segmentInfos.GetCurrentSegmentFileName(); version = segmentInfos.GetVersion(); generation = segmentInfos.GetGeneration(); int size = segmentInfos.Count; files = new List <string>(size); files.Add(segmentsFileName); gen = segmentInfos.GetGeneration(); for (int i = 0; i < size; i++) { SegmentInfo segmentInfo = segmentInfos.Info(i); if (segmentInfo.dir == Enclosing_Instance.directory) { SupportClass.CollectionsSupport.AddAll(segmentInfo.Files(), files); } } isOptimized = segmentInfos.Count == 1 && !segmentInfos.Info(0).HasDeletions(); }
/// <summary> Commit changes resulting from delete, undeleteAll, or /// setNorm operations /// /// If an exception is hit, then either no changes or all /// changes will have been committed to the index /// (transactional semantics). /// </summary> /// <throws> IOException if there is a low-level IO error </throws> protected internal override void DoCommit() { if (hasChanges) { if (segmentInfos != null) { // Default deleter (for backwards compatibility) is // KeepOnlyLastCommitDeleter: IndexFileDeleter deleter = new IndexFileDeleter(directory, deletionPolicy == null ? new KeepOnlyLastCommitDeletionPolicy() : deletionPolicy, segmentInfos, null, null); // Checkpoint the state we are about to change, in // case we have to roll back: StartCommit(); bool success = false; try { CommitChanges(); // sync all the files we just wrote for (int i = 0; i < segmentInfos.Count; i++) { SegmentInfo info = segmentInfos.Info(i); IList<string> files = info.Files(); for (int j = 0; j < files.Count; j++) { string fileName = files[j]; if (!synced.ContainsKey(fileName)) { System.Diagnostics.Debug.Assert(directory.FileExists(fileName)); directory.Sync(fileName); synced[fileName] = fileName; } } } segmentInfos.Commit(directory); success = true; } finally { if (!success) { // Rollback changes that were made to // SegmentInfos but failed to get [fully] // committed. This way this reader instance // remains consistent (matched to what's // actually in the index): RollbackCommit(); // Recompute deletable files & remove them (so // partially written .del files, etc, are // removed): deleter.Refresh(); } } // Have the deleter remove any now unreferenced // files due to this commit: deleter.Checkpoint(segmentInfos, true); if (writeLock != null) { writeLock.Release(); // release write lock writeLock = null; } } else CommitChanges(); } hasChanges = false; }
protected internal override void SetDeleter(IndexFileDeleter deleter) { // Share deleter to our SegmentReaders: this.deleter = deleter; for (int i = 0; i < subReaders.Length; i++) subReaders[i].SetDeleter(deleter); }
internal readonly Codec Codec; // for writing new segments /// <summary> /// Constructs a new IndexWriter per the settings given in <code>conf</code>. /// If you want to make "live" changes to this writer instance, use /// <seealso cref="#getConfig()"/>. /// /// <p> /// <b>NOTE:</b> after ths writer is created, the given configuration instance /// cannot be passed to another writer. If you intend to do so, you should /// <seealso cref="IndexWriterConfig#clone() clone"/> it beforehand. /// </summary> /// <param name="d"> /// the index directory. The index is either created or appended /// according <code>conf.getOpenMode()</code>. </param> /// <param name="conf"> /// the configuration settings according to which IndexWriter should /// be initialized. </param> /// <exception cref="IOException"> /// if the directory cannot be read/written to, or if it does not /// exist and <code>conf.getOpenMode()</code> is /// <code>OpenMode.APPEND</code> or if there is any other low-level /// IO error </exception> public IndexWriter(Directory d, IndexWriterConfig conf) { /*if (!InstanceFieldsInitialized) { InitializeInstanceFields(); InstanceFieldsInitialized = true; }*/ readerPool = new ReaderPool(this); conf.SetIndexWriter(this); // prevent reuse by other instances Config_Renamed = new LiveIndexWriterConfig(conf); directory = d; analyzer = Config_Renamed.Analyzer; infoStream = Config_Renamed.InfoStream; mergePolicy = Config_Renamed.MergePolicy; mergePolicy.IndexWriter = this; mergeScheduler = Config_Renamed.MergeScheduler; Codec = Config_Renamed.Codec; BufferedUpdatesStream = new BufferedUpdatesStream(infoStream); PoolReaders = Config_Renamed.ReaderPooling; WriteLock = directory.MakeLock(WRITE_LOCK_NAME); if (!WriteLock.Obtain(Config_Renamed.WriteLockTimeout)) // obtain write lock { throw new LockObtainFailedException("Index locked for write: " + WriteLock); } bool success = false; try { OpenMode_e? mode = Config_Renamed.OpenMode; bool create; if (mode == OpenMode_e.CREATE) { create = true; } else if (mode == OpenMode_e.APPEND) { create = false; } else { // CREATE_OR_APPEND - create only if an index does not exist create = !DirectoryReader.IndexExists(directory); } // If index is too old, reading the segments will throw // IndexFormatTooOldException. segmentInfos = new SegmentInfos(); bool initialIndexExists = true; if (create) { // Try to read first. this is to allow create // against an index that's currently open for // searching. In this case we write the next // segments_N file with no segments: try { segmentInfos.Read(directory); segmentInfos.Clear(); } catch (IOException) { // Likely this means it's a fresh directory initialIndexExists = false; } // Record that we have a change (zero out all // segments) pending: Changed(); } else { segmentInfos.Read(directory); IndexCommit commit = Config_Renamed.IndexCommit; if (commit != null) { // Swap out all segments, but, keep metadata in // SegmentInfos, like version & generation, to // preserve write-once. this is important if // readers are open against the future commit // points. if (commit.Directory != directory) { throw new System.ArgumentException("IndexCommit's directory doesn't match my directory"); } SegmentInfos oldInfos = new SegmentInfos(); oldInfos.Read(directory, commit.SegmentsFileName); segmentInfos.Replace(oldInfos); Changed(); if (infoStream.IsEnabled("IW")) { infoStream.Message("IW", "init: loaded commit \"" + commit.SegmentsFileName + "\""); } } } RollbackSegments = segmentInfos.CreateBackupSegmentInfos(); // start with previous field numbers, but new FieldInfos GlobalFieldNumberMap = FieldNumberMap; Config_Renamed.FlushPolicy.Init(Config_Renamed); DocWriter = new DocumentsWriter(this, Config_Renamed, directory); eventQueue = DocWriter.EventQueue(); // Default deleter (for backwards compatibility) is // KeepOnlyLastCommitDeleter: lock (this) { Deleter = new IndexFileDeleter(directory, Config_Renamed.DelPolicy, segmentInfos, infoStream, this, initialIndexExists); } if (Deleter.StartingCommitDeleted) { // Deletion policy deleted the "head" commit point. // We have to mark ourself as changed so that if we // are closed w/o any further changes we write a new // segments_N file. Changed(); } if (infoStream.IsEnabled("IW")) { infoStream.Message("IW", "init: create=" + create); MessageState(); } success = true; } finally { if (!success) { if (infoStream.IsEnabled("IW")) { infoStream.Message("IW", "init: hit exception on init; releasing write lock"); } WriteLock.Release(); IOUtils.CloseWhileHandlingException(WriteLock); WriteLock = null; } } }
private void Init(Directory d, Analyzer a, bool create, bool closeDir, IndexDeletionPolicy deletionPolicy, bool autoCommit, int maxFieldLength, IndexingChain indexingChain, IndexCommit commit) { this.closeDir = closeDir; directory = d; analyzer = a; SetMessageID(defaultInfoStream); this.maxFieldLength = maxFieldLength; if (indexingChain == null) indexingChain = DocumentsWriter.DefaultIndexingChain; if (create) { // Clear the write lock in case it's leftover: directory.ClearLock(WRITE_LOCK_NAME); } Lock writeLock = directory.MakeLock(WRITE_LOCK_NAME); if (!writeLock.Obtain(writeLockTimeout)) // obtain write lock { throw new LockObtainFailedException("Index locked for write: " + writeLock); } this.writeLock = writeLock; // save it bool success = false; try { if (create) { // Try to read first. This is to allow create // against an index that's currently open for // searching. In this case we write the next // segments_N file with no segments: bool doCommit; try { segmentInfos.Read(directory); segmentInfos.Clear(); doCommit = false; } catch (System.IO.IOException e) { // Likely this means it's a fresh directory doCommit = true; } if (autoCommit || doCommit) { // Always commit if autoCommit=true, else only // commit if there is no segments file in this dir // already. segmentInfos.Commit(directory); SupportClass.CollectionsHelper.AddAllIfNotContains(synced, segmentInfos.Files(directory, true)); } else { // Record that we have a change (zero out all // segments) pending: changeCount++; } } else { segmentInfos.Read(directory); if (commit != null) { // Swap out all segments, but, keep metadata in // SegmentInfos, like version & generation, to // preserve write-once. This is important if // readers are open against the future commit // points. if (commit.GetDirectory() != directory) throw new System.ArgumentException("IndexCommit's directory doesn't match my directory"); SegmentInfos oldInfos = new SegmentInfos(); oldInfos.Read(directory, commit.GetSegmentsFileName()); segmentInfos.Replace(oldInfos); changeCount++; if (infoStream != null) Message("init: loaded commit \"" + commit.GetSegmentsFileName() + "\""); } // We assume that this segments_N was previously // properly sync'd: SupportClass.CollectionsHelper.AddAllIfNotContains(synced, segmentInfos.Files(directory, true)); } this.autoCommit = autoCommit; SetRollbackSegmentInfos(segmentInfos); docWriter = new DocumentsWriter(directory, this, indexingChain); docWriter.SetInfoStream(infoStream); docWriter.SetMaxFieldLength(maxFieldLength); // Default deleter (for backwards compatibility) is // KeepOnlyLastCommitDeleter: deleter = new IndexFileDeleter(directory, deletionPolicy == null?new KeepOnlyLastCommitDeletionPolicy():deletionPolicy, segmentInfos, infoStream, docWriter,synced); if (deleter.startingCommitDeleted) // Deletion policy deleted the "head" commit point. // We have to mark ourself as changed so that if we // are closed w/o any further changes we write a new // segments_N file. changeCount++; PushMaxBufferedDocs(); if (infoStream != null) { Message("init: create=" + create); MessageState(); } success = true; } finally { if (!success) { if (infoStream != null) { Message("init: hit exception on init; releasing write lock"); } try { writeLock.Release(); } catch (Exception t) { // don't mask the original exception } writeLock = null; } } }
/// <summary> Commit changes resulting from delete, undeleteAll, or setNorm operations /// <p/> /// If an exception is hit, then either no changes or all changes will have been committed to the index (transactional /// semantics). /// /// </summary> /// <throws> IOException if there is a low-level IO error </throws> protected internal override void DoCommit(IDictionary<string, string> commitUserData) { if (hasChanges) { segmentInfos.UserData = commitUserData; // Default deleter (for backwards compatibility) is // KeepOnlyLastCommitDeleter: var deleter = new IndexFileDeleter(internalDirectory, deletionPolicy ?? new KeepOnlyLastCommitDeletionPolicy(), segmentInfos, null, null, synced); segmentInfos.UpdateGeneration(deleter.LastSegmentInfos); // Checkpoint the state we are about to change, in // case we have to roll back: StartCommit(); bool success = false; try { foreach (SegmentReader t in subReaders) t.Commit(); // Sync all files we just wrote foreach(string fileName in segmentInfos.Files(internalDirectory, false)) { if(!synced.Contains(fileName)) { System.Diagnostics.Debug.Assert(internalDirectory.FileExists(fileName)); internalDirectory.Sync(fileName); synced.Add(fileName); } } segmentInfos.Commit(internalDirectory); success = true; } finally { if (!success) { // Rollback changes that were made to // SegmentInfos but failed to get [fully] // committed. This way this reader instance // remains consistent (matched to what's // actually in the index): RollbackCommit(); // Recompute deletable files & remove them (so // partially written .del files, etc, are // removed): deleter.Refresh(); } } // Have the deleter remove any now unreferenced // files due to this commit: deleter.Checkpoint(segmentInfos, true); deleter.Dispose(); maxIndexVersion = segmentInfos.Version; if (writeLock != null) { writeLock.Release(); // release write lock writeLock = null; } } hasChanges = false; }
protected internal virtual void SetDeleter(IndexFileDeleter deleter) { this.deleter = deleter; }
/// <summary> Commit changes resulting from delete, undeleteAll, or /// setNorm operations /// /// If an exception is hit, then either no changes or all /// changes will have been committed to the index /// (transactional semantics). /// </summary> /// <throws> IOException if there is a low-level IO error </throws> protected internal override void DoCommit() { if (hasChanges) { if (segmentInfos != null) { // Default deleter (for backwards compatibility) is // KeepOnlyLastCommitDeleter: IndexFileDeleter deleter = new IndexFileDeleter(directory, deletionPolicy == null ? new KeepOnlyLastCommitDeletionPolicy() : deletionPolicy, segmentInfos, null, null); // Checkpoint the state we are about to change, in // case we have to roll back: StartCommit(); bool success = false; try { CommitChanges(); // sync all the files we just wrote for (int i = 0; i < segmentInfos.Count; i++) { SegmentInfo info = segmentInfos.Info(i); IList <string> files = info.Files(); for (int j = 0; j < files.Count; j++) { string fileName = files[j]; if (!synced.ContainsKey(fileName)) { System.Diagnostics.Debug.Assert(directory.FileExists(fileName)); directory.Sync(fileName); synced[fileName] = fileName; } } } segmentInfos.Commit(directory); success = true; } finally { if (!success) { // Rollback changes that were made to // SegmentInfos but failed to get [fully] // committed. This way this reader instance // remains consistent (matched to what's // actually in the index): RollbackCommit(); // Recompute deletable files & remove them (so // partially written .del files, etc, are // removed): deleter.Refresh(); } } // Have the deleter remove any now unreferenced // files due to this commit: deleter.Checkpoint(segmentInfos, true); if (writeLock != null) { writeLock.Release(); // release write lock writeLock = null; } } else { CommitChanges(); } } hasChanges = false; }
public CommitPoint(IndexFileDeleter enclosingInstance, ICollection<IndexCommitPoint> commitsToDelete, Directory directory, SegmentInfos segmentInfos) { InitBlock(enclosingInstance); this.directory = directory; this.commitsToDelete = commitsToDelete; segmentsFileName = segmentInfos.GetCurrentSegmentFileName(); version = segmentInfos.GetVersion(); generation = segmentInfos.GetGeneration(); int size = segmentInfos.Count; files = new List<string>(size); files.Add(segmentsFileName); gen = segmentInfos.GetGeneration(); for (int i = 0; i < size; i++) { SegmentInfo segmentInfo = segmentInfos.Info(i); if (segmentInfo.dir == Enclosing_Instance.directory) { SupportClass.CollectionsSupport.AddAll(segmentInfo.Files(), files); } } isOptimized = segmentInfos.Count == 1 && !segmentInfos.Info(0).HasDeletions(); }
private void Init(Directory d, Analyzer a, bool create, bool closeDir) { this.closeDir = closeDir; directory = d; analyzer = a; if (create) { // Clear the write lock in case it's leftover: directory.ClearLock(IndexWriter.WRITE_LOCK_NAME); } Lock writeLock = directory.MakeLock(IndexWriter.WRITE_LOCK_NAME); if (!writeLock.Obtain(writeLockTimeout)) // obtain write lock { throw new System.IO.IOException("Index locked for write: " + writeLock); } this.writeLock = writeLock; // save it try { if (create) { // Try to read first. This is to allow create // against an index that's currently open for // searching. In this case we write the next // segments_N file with no segments: try { segmentInfos.Read(directory); segmentInfos.Clear(); } catch (System.IO.IOException e) { // Likely this means it's a fresh directory } segmentInfos.Write(directory); } else { segmentInfos.Read(directory); } // Create a deleter to keep track of which files can // be deleted: deleter = new IndexFileDeleter(segmentInfos, directory); deleter.SetInfoStream(infoStream); deleter.FindDeletableFiles(); deleter.DeleteFiles(); } catch (System.IO.IOException e) { this.writeLock.Release(); this.writeLock = null; throw e; } }
private void Init(Directory d, Analyzer a, bool create, bool closeDir, IndexDeletionPolicy deletionPolicy, bool autoCommit) { this.closeDir = closeDir; directory = d; analyzer = a; this.infoStream = defaultInfoStream; SetMessageID(); if (create) { // Clear the write lock in case it's leftover: directory.ClearLock(IndexWriter.WRITE_LOCK_NAME); } Lock writeLock = directory.MakeLock(IndexWriter.WRITE_LOCK_NAME); if (!writeLock.Obtain(writeLockTimeout)) // obtain write lock { throw new LockObtainFailedException("Index locked for write: " + writeLock); } this.writeLock = writeLock; // save it try { if (create) { // Try to read first. This is to allow create // against an index that's currently open for // searching. In this case we write the next // segments_N file with no segments: try { segmentInfos.Read(directory); segmentInfos.Clear(); } catch (System.IO.IOException e) { // Likely this means it's a fresh directory } segmentInfos.Write(directory); } else { segmentInfos.Read(directory); } this.autoCommit = autoCommit; if (!autoCommit) { rollbackSegmentInfos = (SegmentInfos) segmentInfos.Clone(); } docWriter = new DocumentsWriter(directory, this); docWriter.SetInfoStream(infoStream); // Default deleter (for backwards compatibility) is // KeepOnlyLastCommitDeleter: deleter = new IndexFileDeleter(directory, deletionPolicy == null ? new KeepOnlyLastCommitDeletionPolicy() : deletionPolicy, segmentInfos, infoStream, docWriter); PushMaxBufferedDocs(); if (infoStream != null) { Message("init: create=" + create); MessageState(); } } catch (System.IO.IOException e) { this.writeLock.Release(); this.writeLock = null; throw e; } }
private void InitBlock(IndexFileDeleter enclosingInstance) { this.enclosingInstance = enclosingInstance; }
public virtual void TestDiskFull() { bool debug = false; Term searchTerm = new Term("content", "aaa"); int START_COUNT = 157; int END_COUNT = 144; // First build up a starting index: RAMDirectory startDir = new MockRAMDirectory(); IndexWriter writer = new IndexWriter(startDir, new WhitespaceAnalyzer(), true); for (int i = 0; i < 157; i++) { Lucene.Net.Documents.Document d = new Lucene.Net.Documents.Document(); d.Add(new Field("id", System.Convert.ToString(i), Field.Store.YES, Field.Index.UN_TOKENIZED)); d.Add(new Field("content", "aaa " + i, Field.Store.NO, Field.Index.TOKENIZED)); writer.AddDocument(d); } writer.Close(); long diskUsage = startDir.SizeInBytes(); long diskFree = diskUsage + 100; System.IO.IOException err = null; bool done = false; // Iterate w/ ever increasing free disk space: while (!done) { MockRAMDirectory dir = new MockRAMDirectory(startDir); IndexReader reader = IndexReader.Open(dir); // For each disk size, first try to commit against // dir that will hit random IOExceptions & disk // full; after, give it infinite disk space & turn // off random IOExceptions & retry w/ same reader: bool success = false; for (int x = 0; x < 2; x++) { double rate = 0.05; double diskRatio = ((double) diskFree) / diskUsage; long thisDiskFree; System.String testName; if (0 == x) { thisDiskFree = diskFree; if (diskRatio >= 2.0) { rate /= 2; } if (diskRatio >= 4.0) { rate /= 2; } if (diskRatio >= 6.0) { rate = 0.0; } if (debug) { System.Console.Out.WriteLine("\ncycle: " + diskFree + " bytes"); } testName = "disk full during reader.Close() @ " + thisDiskFree + " bytes"; } else { thisDiskFree = 0; rate = 0.0; if (debug) { System.Console.Out.WriteLine("\ncycle: same writer: unlimited disk space"); } testName = "reader re-use after disk full"; } dir.SetMaxSizeInBytes(thisDiskFree); dir.SetRandomIOExceptionRate(rate, diskFree); try { if (0 == x) { int docId = 12; for (int i = 0; i < 13; i++) { reader.DeleteDocument(docId); reader.SetNorm(docId, "contents", (float) 2.0); docId += 12; } } reader.Close(); success = true; if (0 == x) { done = true; } } catch (System.IO.IOException e) { if (debug) { System.Console.Out.WriteLine(" hit IOException: " + e); } err = e; if (1 == x) { System.Console.Error.WriteLine(e.StackTrace); Assert.Fail(testName + " hit IOException after disk space was freed up"); } } // Whether we succeeded or failed, check that all // un-referenced files were in fact deleted (ie, // we did not create garbage). Just create a // new IndexFileDeleter, have it delete // unreferenced files, then verify that in fact // no files were deleted: System.String[] startFiles = dir.List(); SegmentInfos infos = new SegmentInfos(); infos.Read(dir); IndexFileDeleter d = new IndexFileDeleter(dir, new KeepOnlyLastCommitDeletionPolicy(), infos, null, null); System.String[] endFiles = dir.List(); System.Array.Sort(startFiles); System.Array.Sort(endFiles); //for(int i=0;i<startFiles.length;i++) { // System.out.println(" startFiles: " + i + ": " + startFiles[i]); //} if (SupportClass.Compare.CompareStringArrays(startFiles, endFiles) == false) { System.String successStr; if (success) { successStr = "success"; } else { successStr = "IOException"; System.Console.Error.WriteLine(err.StackTrace); } Assert.Fail("reader.Close() failed to delete unreferenced files after " + successStr + " (" + diskFree + " bytes): before delete:\n " + ArrayToString(startFiles) + "\n after delete:\n " + ArrayToString(endFiles)); } // Finally, verify index is not corrupt, and, if // we succeeded, we see all docs changed, and if // we failed, we see either all docs or no docs // changed (transactional semantics): IndexReader newReader = null; try { newReader = IndexReader.Open(dir); } catch (System.IO.IOException e) { System.Console.Error.WriteLine(e.StackTrace); Assert.Fail(testName + ":exception when creating IndexReader after disk full during Close: " + e); } /* int result = newReader.docFreq(searchTerm); if (success) { if (result != END_COUNT) { fail(testName + ": method did not throw exception but docFreq('aaa') is " + result + " instead of expected " + END_COUNT); } } else { // On hitting exception we still may have added // all docs: if (result != START_COUNT && result != END_COUNT) { err.printStackTrace(); fail(testName + ": method did throw exception but docFreq('aaa') is " + result + " instead of expected " + START_COUNT + " or " + END_COUNT); } } */ IndexSearcher searcher = new IndexSearcher(newReader); Hits hits = null; try { hits = searcher.Search(new TermQuery(searchTerm)); } catch (System.IO.IOException e) { System.Console.Error.WriteLine(e.StackTrace); Assert.Fail(testName + ": exception when searching: " + e); } int result2 = hits.Length(); if (success) { if (result2 != END_COUNT) { Assert.Fail(testName + ": method did not throw exception but hits.length for search on term 'aaa' is " + result2 + " instead of expected " + END_COUNT); } } else { // On hitting exception we still may have added // all docs: if (result2 != START_COUNT && result2 != END_COUNT) { System.Console.Error.WriteLine(err.StackTrace); Assert.Fail(testName + ": method did throw exception but hits.length for search on term 'aaa' is " + result2 + " instead of expected " + START_COUNT); } } searcher.Close(); newReader.Close(); if (result2 == END_COUNT) { break; } } dir.Close(); // Try again with 10 more bytes of free space: diskFree += 10; } startDir.Close(); }
private void Init(Directory d, Analyzer a, bool create, bool closeDir, IndexDeletionPolicy deletionPolicy, bool autoCommit, int maxFieldLength) { this.closeDir = closeDir; directory = d; analyzer = a; SetMessageID(defaultInfoStream); this.maxFieldLength = maxFieldLength; if (create) { // Clear the write lock in case it's leftover: directory.ClearLock(WRITE_LOCK_NAME); } Lock writeLock = directory.MakeLock(WRITE_LOCK_NAME); if (!writeLock.Obtain(writeLockTimeout)) // obtain write lock { throw new LockObtainFailedException("Index locked for write: " + writeLock); } this.writeLock = writeLock; // save it try { if (create) { // Try to read first. This is to allow create // against an index that's currently open for // searching. In this case we write the next // segments_N file with no segments: try { segmentInfos.Read(directory); segmentInfos.Clear(); } catch (System.IO.IOException) { // Likely this means it's a fresh directory } segmentInfos.Commit(directory); } else { segmentInfos.Read(directory); // We assume that this segments_N was previously // properly sync'd: for (int i = 0; i < segmentInfos.Count; i++) { SegmentInfo info = segmentInfos.Info(i); List<string> files = info.Files(); for (int j = 0; j < files.Count; j++) synced[files[j]] = files[j]; } } this.autoCommit = autoCommit; SetRollbackSegmentInfos(segmentInfos); docWriter = new DocumentsWriter(directory, this); docWriter.SetInfoStream(infoStream); docWriter.SetMaxFieldLength(maxFieldLength); // Default deleter (for backwards compatibility) is // KeepOnlyLastCommitDeleter: deleter = new IndexFileDeleter(directory, deletionPolicy == null ? new KeepOnlyLastCommitDeletionPolicy() : deletionPolicy, segmentInfos, infoStream, docWriter); PushMaxBufferedDocs(); if (infoStream != null) { Message("init: create=" + create); MessageState(); } } catch (System.IO.IOException e) { this.writeLock.Release(); this.writeLock = null; throw e; } }
/// <summary> Commit changes resulting from delete, undeleteAll, or setNorm operations /// <p/> /// If an exception is hit, then either no changes or all changes will have been committed to the index (transactional /// semantics). /// /// </summary> /// <throws> IOException if there is a low-level IO error </throws> protected internal override void DoCommit(System.Collections.IDictionary commitUserData) { if (hasChanges) { segmentInfos.SetUserData(commitUserData); // Default deleter (for backwards compatibility) is // KeepOnlyLastCommitDeleter: IndexFileDeleter deleter = new IndexFileDeleter(directory, deletionPolicy == null?new KeepOnlyLastCommitDeletionPolicy():deletionPolicy, segmentInfos, null, null); // Checkpoint the state we are about to change, in // case we have to roll back: StartCommit(); bool success = false; try { for (int i = 0; i < subReaders.Length; i++) subReaders[i].Commit(); // Sync all files we just wrote System.Collections.IEnumerator it = segmentInfos.Files(directory, false).GetEnumerator(); while (it.MoveNext()) { System.String fileName = (string)((System.Collections.DictionaryEntry) it.Current).Value; if (!synced.Contains(fileName)) { System.Diagnostics.Debug.Assert(directory.FileExists(fileName)); directory.Sync(fileName); SupportClass.CollectionsHelper.AddIfNotContains(synced, fileName); } } segmentInfos.Commit(directory); success = true; } finally { if (!success) { // Rollback changes that were made to // SegmentInfos but failed to get [fully] // committed. This way this reader instance // remains consistent (matched to what's // actually in the index): RollbackCommit(); // Recompute deletable files & remove them (so // partially written .del files, etc, are // removed): deleter.Refresh(); } } // Have the deleter remove any now unreferenced // files due to this commit: deleter.Checkpoint(segmentInfos, true); deleter.Close(); if (writeLock != null) { writeLock.Release(); // release write lock writeLock = null; } } hasChanges = false; }