Пример #1
0
		private void CloseInternal(bool waitForMerges)
		{
			
			docWriter.PauseAllThreads();
			
			try
			{
				if (infoStream != null)
					Message("now flush at close");
				
				docWriter.Dispose();
				
				// Only allow a new merge to be triggered if we are
				// going to wait for merges:
				if (!hitOOM)
				{
					Flush(waitForMerges, true, true);
				}
				
				if (waitForMerges)
				// Give merge scheduler last chance to run, in case
				// any pending merges are waiting:
					mergeScheduler.Merge(this);
				
				mergePolicy.Close();
				
				FinishMerges(waitForMerges);
				stopMerges = true;
				
				mergeScheduler.Close();
				
				if (infoStream != null)
					Message("now call final commit()");
				
				if (!hitOOM)
				{
					Commit(0);
				}
				
				if (infoStream != null)
					Message("at close: " + SegString());
				
				lock (this)
				{
					readerPool.Dispose();
					docWriter = null;
					deleter.Dispose();
				}
				
				if (writeLock != null)
				{
					writeLock.Release(); // release write lock
					writeLock = null;
				}
				lock (this)
				{
					closed = true;
				}
			}
			catch (System.OutOfMemoryException oom)
			{
				HandleOOM(oom, "closeInternal");
			}
			finally
			{
				lock (this)
				{
					closing = false;
					System.Threading.Monitor.PulseAll(this);
					if (!closed)
					{
						if (docWriter != null)
							docWriter.ResumeAllThreads();
						if (infoStream != null)
							Message("hit exception while closing");
					}
				}
			}
		}
Пример #2
0
		private void  Init(Directory d, Analyzer a, bool create, IndexDeletionPolicy deletionPolicy, int maxFieldLength, DocumentsWriter.IndexingChain indexingChain, IndexCommit commit)
		{
			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)
					{
						// Likely this means it's a fresh directory
						doCommit = true;
					}
					
					if (doCommit)
					{
						// Only commit if there is no segments file 
                        // in this dir already.
						segmentInfos.Commit(directory);
                        synced.UnionWith(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.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);
						changeCount++;
						if (infoStream != null)
							Message("init: loaded commit \"" + commit.SegmentsFileName + "\"");
					}
					
					// We assume that this segments_N was previously
					// properly sync'd:
                    synced.UnionWith(segmentInfos.Files(directory, true));
				}
				
				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)
                    {
                        // don't mask the original exception
                    }
                    writeLock = null;
                }
			}
		}
Пример #3
0
			/// <summary>Constructs an executor that will grab the named lock. </summary>
			protected With(Lock lock_Renamed, long lockWaitTimeout)
			{
				this.lock_Renamed = lock_Renamed;
				this.lockWaitTimeout = lockWaitTimeout;
			}
Пример #4
0
        /// <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;
        }
Пример #5
0
 /// <summary> Tries to acquire the WriteLock on this directory. this method is only valid if this IndexReader is directory
 /// owner.
 /// 
 /// </summary>
 /// <throws>  StaleReaderException  if the index has changed since this reader was opened </throws>
 /// <throws>  CorruptIndexException if the index is corrupt </throws>
 /// <throws>  Lucene.Net.Store.LockObtainFailedException </throws>
 /// <summary>                               if another writer has this index open (<c>write.lock</c> could not be
 /// obtained)
 /// </summary>
 /// <throws>  IOException           if there is a low-level IO error </throws>
 protected internal override void  AcquireWriteLock()
 {
     
     if (readOnly)
     {
         // NOTE: we should not reach this code w/ the core
         // IndexReader classes; however, an external subclass
         // of IndexReader could reach this.
         ReadOnlySegmentReader.NoWrite();
     }
     
     if (segmentInfos != null)
     {
         EnsureOpen();
         if (stale)
             throw new StaleReaderException("IndexReader out of date and no longer valid for delete, undelete, or setNorm operations");
         
         if (this.writeLock == null)
         {
             Lock writeLock = internalDirectory.MakeLock(IndexWriter.WRITE_LOCK_NAME);
             if (!writeLock.Obtain(IndexWriter.WRITE_LOCK_TIMEOUT))
             // obtain write lock
             {
                 throw new LockObtainFailedException("Index locked for write: " + writeLock);
             }
             this.writeLock = writeLock;
             
             // we have to check whether index has changed since this reader was opened.
             // if so, this reader is no longer valid for
             // deletion
             if (SegmentInfos.ReadCurrentVersion(internalDirectory) > maxIndexVersion)
             {
                 stale = true;
                 this.writeLock.Release();
                 this.writeLock = null;
                 throw new StaleReaderException("IndexReader out of date and no longer valid for delete, undelete, or setNorm operations");
             }
         }
     }
 }
Пример #6
0
 public override IndexReader Clone(bool openReadOnly)
 {
     lock (this)
     {
         DirectoryReader newReader = DoReopen((SegmentInfos) segmentInfos.Clone(), true, openReadOnly);
         
         if (this != newReader)
         {
             newReader.deletionPolicy = deletionPolicy;
         }
         newReader.writer = writer;
         // If we're cloning a non-readOnly reader, move the
         // writeLock (if there is one) to the new reader:
         if (!openReadOnly && writeLock != null)
         {
             // In near real-time search, reader is always readonly
             System.Diagnostics.Debug.Assert(writer == null);
             newReader.writeLock = writeLock;
             newReader.hasChanges = hasChanges;
             newReader.hasDeletions = hasDeletions;
             writeLock = null;
             hasChanges = false;
         }
         
         return newReader;
     }
 }