Lucene.Net.Index.IndexWriter.StartCommit C# (CSharp) Method

StartCommit() private method

Walk through all files referenced by the current segmentInfos and ask the Directory to sync each file, if it wasn't already. If that succeeds, then we prepare a new segments_N file but do not fully commit it.
private StartCommit ( long sizeInBytes, string>.IDictionary commitUserData ) : void
sizeInBytes long
commitUserData string>.IDictionary
return void
        private void StartCommit(long sizeInBytes, IDictionary<string, string> commitUserData)
		{
			
			System.Diagnostics.Debug.Assert(TestPoint("startStartCommit"));

            // TODO: as of LUCENE-2095, we can simplify this method,
            // since only 1 thread can be in here at once
			
			if (hitOOM)
			{
				throw new System.SystemException("this writer hit an OutOfMemoryError; cannot commit");
			}
			
			try
			{
				
				if (infoStream != null)
					Message("startCommit(): start sizeInBytes=" + sizeInBytes);
				
				SegmentInfos toSync = null;
				long myChangeCount;
				
				lock (this)
				{
					// Wait for any running addIndexes to complete
					// first, then block any from running until we've
					// copied the segmentInfos we intend to sync:
					BlockAddIndexes(false);
					
					// On commit the segmentInfos must never
					// reference a segment in another directory:
					System.Diagnostics.Debug.Assert(!HasExternalSegments());
					
					try
					{
						
						System.Diagnostics.Debug.Assert(lastCommitChangeCount <= changeCount);
                        myChangeCount = changeCount;
						
						if (changeCount == lastCommitChangeCount)
						{
							if (infoStream != null)
								Message("  skip startCommit(): no changes pending");
							return ;
						}
						
						// First, we clone & incref the segmentInfos we intend
						// to sync, then, without locking, we sync() each file
						// referenced by toSync, in the background.  Multiple
						// threads can be doing this at once, if say a large
						// merge and a small merge finish at the same time:
						
						if (infoStream != null)
							Message("startCommit index=" + SegString(segmentInfos) + " changeCount=" + changeCount);

                        readerPool.Commit();
						
						// It's possible another flush (that did not close
                        // the open do stores) snuck in after the flush we
                        // just did, so we remove any tail segments
                        // referencing the open doc store from the
                        // SegmentInfos we are about to sync (the main
                        // SegmentInfos will keep them):
                        toSync = (SegmentInfos) segmentInfos.Clone();
                        string dss = docWriter.DocStoreSegment;
                        if (dss != null)
                        {
                            while (true)
                            {
                                String dss2 = toSync.Info(toSync.Count - 1).DocStoreSegment;
                                if (dss2 == null || !dss2.Equals(dss))
                                {
                                    break;
                                }
                                toSync.RemoveAt(toSync.Count - 1);
                                changeCount++;
                            }
                        }
						
						if (commitUserData != null)
							toSync.UserData = commitUserData;
						
						deleter.IncRef(toSync, false);
												
						ICollection<string> files = toSync.Files(directory, false);
						foreach(string fileName in files)
						{
							System.Diagnostics.Debug.Assert(directory.FileExists(fileName), "file " + fileName + " does not exist");
                            // If this trips it means we are missing a call to
                            // .checkpoint somewhere, because by the time we
                            // are called, deleter should know about every
                            // file referenced by the current head
                            // segmentInfos:
                            System.Diagnostics.Debug.Assert(deleter.Exists(fileName));
						}
					}
					finally
					{
						ResumeAddIndexes();
					}
				}
				
				System.Diagnostics.Debug.Assert(TestPoint("midStartCommit"));
				
				bool setPending = false;
				
				try
				{
					// Loop until all files toSync references are sync'd:
					while (true)
					{
                        ICollection<string> pending = new List<string>();
						
						IEnumerator<string> it = toSync.Files(directory, false).GetEnumerator();
						while (it.MoveNext())
						{
                            string fileName = it.Current;
							if (StartSync(fileName, pending))
							{
								bool success = false;
								try
								{
									// Because we incRef'd this commit point, above,
									// the file had better exist:
									System.Diagnostics.Debug.Assert(directory.FileExists(fileName), "file '" + fileName + "' does not exist dir=" + directory);
									if (infoStream != null)
										Message("now sync " + fileName);
									directory.Sync(fileName);
									success = true;
								}
								finally
								{
									FinishSync(fileName, success);
								}
							}
						}
						
						// All files that I require are either synced or being
						// synced by other threads.  If they are being synced,
						// we must at this point block until they are done.
						// If this returns false, that means an error in
						// another thread resulted in failing to actually
						// sync one of our files, so we repeat:
						if (WaitForAllSynced(pending))
							break;
					}
					
					System.Diagnostics.Debug.Assert(TestPoint("midStartCommit2"));
					
					lock (this)
					{
						// If someone saved a newer version of segments file
						// since I first started syncing my version, I can
						// safely skip saving myself since I've been
						// superseded:
						
						while (true)
						{
							if (myChangeCount <= lastCommitChangeCount)
							{
								if (infoStream != null)
								{
									Message("sync superseded by newer infos");
								}
								break;
							}
							else if (pendingCommit == null)
							{
								// My turn to commit
								
								if (segmentInfos.Generation > toSync.Generation)
									toSync.UpdateGeneration(segmentInfos);
								
								bool success = false;
								try
								{
									
									// Exception here means nothing is prepared
									// (this method unwinds everything it did on
									// an exception)
									try
									{
										toSync.PrepareCommit(directory);
									}
									finally
									{
										// Have our master segmentInfos record the
										// generations we just prepared.  We do this
										// on error or success so we don't
										// double-write a segments_N file.
										segmentInfos.UpdateGeneration(toSync);
									}
									
									System.Diagnostics.Debug.Assert(pendingCommit == null);
									setPending = true;
									pendingCommit = toSync;
									pendingCommitChangeCount = (uint) myChangeCount;
									success = true;
								}
								finally
								{
									if (!success && infoStream != null)
										Message("hit exception committing segments file");
								}
								break;
							}
							else
							{
								// Must wait for other commit to complete
								DoWait();
							}
						}
					}
					
					if (infoStream != null)
						Message("done all syncs");
					
					System.Diagnostics.Debug.Assert(TestPoint("midStartCommitSuccess"));
				}
				finally
				{
					lock (this)
					{
						if (!setPending)
							deleter.DecRef(toSync);
					}
				}
			}
			catch (System.OutOfMemoryException oom)
			{
				HandleOOM(oom, "startCommit");
			}
			System.Diagnostics.Debug.Assert(TestPoint("finishStartCommit"));
		}
		
IndexWriter