internal DocumentsWriterThreadState GetThreadState(Document doc, Term delTerm)
{
lock (this)
{
// First, find a thread state. If this thread already
// has affinity to a specific ThreadState, use that one
// again.
DocumentsWriterThreadState state = threadBindings[ThreadClass.Current()];
if (state == null)
{
// First time this thread has called us since last
// flush. Find the least loaded thread state:
DocumentsWriterThreadState minThreadState = null;
for (int i = 0; i < threadStates.Length; i++)
{
DocumentsWriterThreadState ts = threadStates[i];
if (minThreadState == null || ts.numThreads < minThreadState.numThreads)
minThreadState = ts;
}
if (minThreadState != null && (minThreadState.numThreads == 0 || threadStates.Length >= MAX_THREAD_STATE))
{
state = minThreadState;
state.numThreads++;
}
else
{
// Just create a new "private" thread state
DocumentsWriterThreadState[] newArray = new DocumentsWriterThreadState[1 + threadStates.Length];
if (threadStates.Length > 0)
Array.Copy(threadStates, 0, newArray, 0, threadStates.Length);
state = newArray[threadStates.Length] = new DocumentsWriterThreadState(this);
threadStates = newArray;
}
threadBindings[ThreadClass.Current()] = state;
}
// Next, wait until my thread state is idle (in case
// it's shared with other threads) and for threads to
// not be paused nor a flush pending:
WaitReady(state);
// Allocate segment name if this is the first doc since
// last flush:
InitSegmentName(false);
state.isIdle = false;
bool success = false;
try
{
state.docState.docID = nextDocID;
System.Diagnostics.Debug.Assert(writer.TestPoint("DocumentsWriter.ThreadState.init start"));
if (delTerm != null)
{
AddDeleteTerm(delTerm, state.docState.docID);
state.doFlushAfter = TimeToFlushDeletes();
}
System.Diagnostics.Debug.Assert(writer.TestPoint("DocumentsWriter.ThreadState.init after delTerm"));
nextDocID++;
numDocsInRAM++;
// We must at this point commit to flushing to ensure we
// always get N docs when we flush by doc count, even if
// > 1 thread is adding documents:
if (!flushPending && maxBufferedDocs != IndexWriter.DISABLE_AUTO_FLUSH && numDocsInRAM >= maxBufferedDocs)
{
flushPending = true;
state.doFlushAfter = true;
}
success = true;
}
finally
{
if (!success)
{
// Forcefully idle this ThreadState:
state.isIdle = true;
System.Threading.Monitor.PulseAll(this);
if (state.doFlushAfter)
{
state.doFlushAfter = false;
flushPending = false;
}
}
}
return state;
}
}