/// <summary>
 /// Returns a new <see cref="ThreadState"/> iff any new state is available otherwise
 /// <c>null</c>.
 /// <para/>
 /// NOTE: the returned <see cref="ThreadState"/> is already locked iff non-<c>null</c>.
 /// </summary>
 /// <returns> a new <see cref="ThreadState"/> iff any new state is available otherwise
 ///         <c>null</c> </returns>
 public virtual ThreadState NewThreadState()
 {
     lock (this)
     {
         if (numThreadStatesActive < threadStates.Length)
         {
             ThreadState threadState = threadStates[numThreadStatesActive];
             threadState.@Lock(); // lock so nobody else will get this ThreadState
             bool unlock = true;
             try
             {
                 if (threadState.IsActive)
                 {
                     // unreleased thread states are deactivated during DW#close()
                     numThreadStatesActive++; // increment will publish the ThreadState
                     Debug.Assert(threadState.dwpt == null);
                     unlock = false;
                     return(threadState);
                 }
                 // unlock since the threadstate is not active anymore - we are closed!
                 Debug.Assert(AssertUnreleasedThreadStatesInactive());
                 return(null);
             }
             finally
             {
                 if (unlock)
                 {
                     // in any case make sure we unlock if we fail
                     threadState.Unlock();
                 }
             }
         }
         return(null);
     }
 }
        public override ThreadState GetAndLock(Thread requestingThread, DocumentsWriter documentsWriter)
        {
            ThreadState threadState = null;

            if (NumThreadStatesActive == 0)
            {
                lock (this)
                {
                    if (NumThreadStatesActive == 0)
                    {
                        threadState = states[0] = NewThreadState();
                        return(threadState);
                    }
                }
            }
            Debug.Assert(NumThreadStatesActive > 0);
            for (int i = 0; i < maxRetry; i++)
            {
                int ord = random.Next(NumThreadStatesActive);
                lock (this)
                {
                    threadState = states[ord];
                    Debug.Assert(threadState != null);
                }

                if (threadState.TryLock())
                {
                    return(threadState);
                }
                if (random.Next(20) == 0)
                {
                    break;
                }
            }

            /*
             * only try to create a new threadstate if we can not lock the randomly
             * selected state. this is important since some tests rely on a single
             * threadstate in the single threaded case. Eventually it would be nice if
             * we would not have this limitation but for now we just make sure we only
             * allocate one threadstate if indexing is single threaded
             */

            lock (this)
            {
                ThreadState newThreadState = NewThreadState();
                if (newThreadState != null) // did we get a new state?
                {
                    threadState = states[NumThreadStatesActive - 1] = newThreadState;
                    //Debug.Assert(threadState.HeldByCurrentThread);
                    return(threadState);
                }
                // if no new state is available lock the random one
            }
            Debug.Assert(threadState != null);
            threadState.@Lock();
            return(threadState);
        }
示例#3
0
 internal void Abort(IndexWriter writer)
 {
     UninterruptableMonitor.Enter(this);
     try
     {
         if (Debugging.AssertsEnabled)
         {
             Debugging.Assert(!UninterruptableMonitor.IsEntered(writer), "IndexWriter lock should never be hold when aborting");
         }
         bool success = false;
         JCG.HashSet <string> newFilesSet = new JCG.HashSet <string>();
         try
         {
             deleteQueue.Clear();
             if (infoStream.IsEnabled("DW"))
             {
                 infoStream.Message("DW", "abort");
             }
             int limit = perThreadPool.NumThreadStatesActive;
             for (int i = 0; i < limit; i++)
             {
                 ThreadState perThread = perThreadPool.GetThreadState(i);
                 perThread.@Lock();
                 try
                 {
                     AbortThreadState(perThread, newFilesSet);
                 }
                 finally
                 {
                     perThread.Unlock();
                 }
             }
             flushControl.AbortPendingFlushes(newFilesSet);
             PutEvent(new DeleteNewFilesEvent(newFilesSet));
             flushControl.WaitForFlush();
             success = true;
         }
         finally
         {
             if (infoStream.IsEnabled("DW"))
             {
                 infoStream.Message("DW", "done abort; abortedFiles=" + string.Format(J2N.Text.StringFormatter.InvariantCulture, "{0}", newFilesSet) + " success=" + success);
             }
         }
     }
     finally
     {
         UninterruptableMonitor.Exit(this);
     }
 }
示例#4
0
 internal void LockAndAbortAll(IndexWriter indexWriter)
 {
     UninterruptableMonitor.Enter(this);
     try
     {
         if (Debugging.AssertsEnabled)
         {
             Debugging.Assert(indexWriter.HoldsFullFlushLock);
         }
         if (infoStream.IsEnabled("DW"))
         {
             infoStream.Message("DW", "lockAndAbortAll");
         }
         bool success = false;
         try
         {
             deleteQueue.Clear();
             int limit = perThreadPool.MaxThreadStates;
             JCG.HashSet <string> newFilesSet = new JCG.HashSet <string>();
             for (int i = 0; i < limit; i++)
             {
                 ThreadState perThread = perThreadPool.GetThreadState(i);
                 perThread.@Lock();
                 AbortThreadState(perThread, newFilesSet);
             }
             deleteQueue.Clear();
             flushControl.AbortPendingFlushes(newFilesSet);
             PutEvent(new DeleteNewFilesEvent(newFilesSet));
             flushControl.WaitForFlush();
             success = true;
         }
         finally
         {
             if (infoStream.IsEnabled("DW"))
             {
                 infoStream.Message("DW", "finished lockAndAbortAll success=" + success);
             }
             if (!success)
             {
                 // if something happens here we unlock all states again
                 UnlockAllAfterAbortAll(indexWriter);
             }
         }
     }
     finally
     {
         UninterruptableMonitor.Exit(this);
     }
 }
示例#5
0
 private void CheckoutAndBlock(ThreadState perThread)
 {
     perThread.@Lock();
     try
     {
         Debug.Assert(perThread.flushPending, "can not block non-pending threadstate");
         Debug.Assert(fullFlush, "can not block if fullFlush == false");
         DocumentsWriterPerThread dwpt;
         long bytes = perThread.bytesUsed;
         dwpt = perThreadPool.Reset(perThread, closed);
         numPending--;
         blockedFlushes.AddLast(new BlockedFlush(dwpt, bytes));
     }
     finally
     {
         perThread.Unlock();
     }
 }
示例#6
0
        private bool AssertActiveDeleteQueue(DocumentsWriterDeleteQueue queue)
        {
            int limit = perThreadPool.NumThreadStatesActive;

            for (int i = 0; i < limit; i++)
            {
                ThreadState next = perThreadPool.GetThreadState(i);
                next.@Lock();
                try
                {
                    Debug.Assert(!next.IsInitialized || next.dwpt.deleteQueue == queue, "isInitialized: " + next.IsInitialized + " numDocs: " + (next.IsInitialized ? next.dwpt.NumDocsInRAM : 0));
                }
                finally
                {
                    next.Unlock();
                }
            }
            return(true);
        }
 /// <summary>
 /// Deactivate all unreleased threadstates
 /// </summary>
 internal virtual void DeactivateUnreleasedStates()
 {
     lock (this)
     {
         for (int i = numThreadStatesActive; i < threadStates.Length; i++)
         {
             ThreadState threadState = threadStates[i];
             threadState.@Lock();
             try
             {
                 threadState.Deactivate();
             }
             finally
             {
                 threadState.Unlock();
             }
         }
     }
 }
示例#8
0
 internal void Abort(IndexWriter writer)
 {
     lock (this)
     {
         //Debug.Assert(!Thread.HoldsLock(writer), "IndexWriter lock should never be hold when aborting");
         bool             success     = false;
         HashSet <string> newFilesSet = new HashSet <string>();
         try
         {
             deleteQueue.Clear();
             if (infoStream.IsEnabled("DW"))
             {
                 infoStream.Message("DW", "abort");
             }
             int limit = perThreadPool.NumThreadStatesActive;
             for (int i = 0; i < limit; i++)
             {
                 ThreadState perThread = perThreadPool.GetThreadState(i);
                 perThread.@Lock();
                 try
                 {
                     AbortThreadState(perThread, newFilesSet);
                 }
                 finally
                 {
                     perThread.Unlock();
                 }
             }
             flushControl.AbortPendingFlushes(newFilesSet);
             PutEvent(new DeleteNewFilesEvent(newFilesSet));
             flushControl.WaitForFlush();
             success = true;
         }
         finally
         {
             if (infoStream.IsEnabled("DW"))
             {
                 infoStream.Message("DW", "done abort; abortedFiles=" + Arrays.ToString(newFilesSet) + " success=" + success);
             }
         }
     }
 }
        public override ThreadState GetAndLock(Thread requestingThread, DocumentsWriter documentsWriter)
        {
            if (threadBindings.TryGetValue(requestingThread, out ThreadState threadState) && threadState.TryLock())
            {
                return(threadState);
            }
            ThreadState minThreadState = null;

            /* TODO -- another thread could lock the minThreadState we just got while
             * we should somehow prevent this. */
            // Find the state that has minimum number of threads waiting
            minThreadState = MinContendedThreadState();
            if (minThreadState == null || minThreadState.HasQueuedThreads)
            {
                ThreadState newState = NewThreadState(); // state is already locked if non-null
                if (newState != null)
                {
                    if (Debugging.AssertsEnabled)
                    {
                        Debugging.Assert(newState.IsHeldByCurrentThread);
                    }
                    threadBindings[requestingThread] = newState;
                    return(newState);
                }
                else if (minThreadState == null)
                {
                    /*
                     * no new threadState available we just take the minContented one
                     * this must return a valid thread state since we accessed the
                     * synced context in newThreadState() above.
                     */
                    minThreadState = MinContendedThreadState();
                }
            }
            if (Debugging.AssertsEnabled)
            {
                Debugging.Assert(minThreadState != null, () => "ThreadState is null");
            }

            minThreadState.@Lock();
            return(minThreadState);
        }
示例#10
0
 private void CheckoutAndBlock(ThreadState perThread)
 {
     perThread.@Lock();
     try
     {
         if (Debugging.AssertsEnabled)
         {
             Debugging.Assert(perThread.flushPending, "can not block non-pending threadstate");
             Debugging.Assert(fullFlush, "can not block if fullFlush == false");
         }
         DocumentsWriterPerThread dwpt;
         long bytes = perThread.bytesUsed;
         dwpt = DocumentsWriterPerThreadPool.Reset(perThread, closed); // LUCENENET specific - made method static per CA1822
         numPending--;
         blockedFlushes.AddLast(new BlockedFlush(dwpt, bytes));
     }
     finally
     {
         perThread.Unlock();
     }
 }
        /// <summary>
        /// Returns the number of currently deactivated <see cref="ThreadState"/> instances.
        /// A deactivated <see cref="ThreadState"/> should not be used for indexing anymore.
        /// </summary>
        /// <returns> the number of currently deactivated <see cref="ThreadState"/> instances. </returns>
        internal virtual int NumDeactivatedThreadStates()
        {
            int count = 0;

            for (int i = 0; i < threadStates.Length; i++)
            {
                ThreadState threadState = threadStates[i];
                threadState.@Lock();
                try
                {
                    if (!threadState.isActive)
                    {
                        count++;
                    }
                }
                finally
                {
                    threadState.Unlock();
                }
            }
            return(count);
        }
示例#12
0
 /// <summary>
 /// Deactivate all unreleased threadstates
 /// </summary>
 internal void DeactivateUnreleasedStates()
 {
     UninterruptableMonitor.Enter(this);
     try
     {
         for (int i = numThreadStatesActive; i < threadStates.Length; i++)
         {
             ThreadState threadState = threadStates[i];
             threadState.@Lock();
             try
             {
                 threadState.Deactivate();
             }
             finally
             {
                 threadState.Unlock();
             }
         }
     }
     finally
     {
         UninterruptableMonitor.Exit(this);
     }
 }
示例#13
0
        internal void MarkForFullFlush()
        {
            DocumentsWriterDeleteQueue flushingQueue;

            lock (this)
            {
                Debug.Assert(!fullFlush, "called DWFC#markForFullFlush() while full flush is still running");
                Debug.Assert(fullFlushBuffer.Count == 0, "full flush buffer should be empty: " + fullFlushBuffer);
                fullFlush     = true;
                flushingQueue = documentsWriter.deleteQueue;
                // Set a new delete queue - all subsequent DWPT will use this queue until
                // we do another full flush
                DocumentsWriterDeleteQueue newQueue = new DocumentsWriterDeleteQueue(flushingQueue.generation + 1);
                documentsWriter.deleteQueue = newQueue;
            }
            int limit = perThreadPool.NumThreadStatesActive;

            for (int i = 0; i < limit; i++)
            {
                ThreadState next = perThreadPool.GetThreadState(i);
                next.@Lock();
                try
                {
                    if (!next.IsInitialized)
                    {
                        if (closed && next.IsActive)
                        {
                            perThreadPool.DeactivateThreadState(next);
                        }
                        continue;
                    }
                    Debug.Assert(next.dwpt.deleteQueue == flushingQueue || next.dwpt.deleteQueue == documentsWriter.deleteQueue, " flushingQueue: " + flushingQueue + " currentqueue: " + documentsWriter.deleteQueue + " perThread queue: " + next.dwpt.deleteQueue + " numDocsInRam: " + next.dwpt.NumDocsInRAM);
                    if (next.dwpt.deleteQueue != flushingQueue)
                    {
                        // this one is already a new DWPT
                        continue;
                    }
                    AddFlushableState(next);
                }
                finally
                {
                    next.Unlock();
                }
            }
            lock (this)
            {
                /* make sure we move all DWPT that are where concurrently marked as
                 * pending and moved to blocked are moved over to the flushQueue. There is
                 * a chance that this happens since we marking DWPT for full flush without
                 * blocking indexing.*/
                PruneBlockedQueue(flushingQueue);
                Debug.Assert(AssertBlockedFlushes(documentsWriter.deleteQueue));
                //FlushQueue.AddAll(FullFlushBuffer);
                foreach (var dwpt in fullFlushBuffer)
                {
                    flushQueue.Enqueue(dwpt);
                }
                fullFlushBuffer.Clear();
                UpdateStallState();
            }
            Debug.Assert(AssertActiveDeleteQueue(documentsWriter.deleteQueue));
        }