19 using System.Collections.Generic;
 
   21 using System.Threading;
 
   22 using Lucene.Net.Support;
 
   24 using Document = Lucene.Net.Documents.Document;
 
   30 using Query = Lucene.Net.Search.Query;
 
   31 using Scorer = Lucene.Net.Search.Scorer;
 
   33 using Weight = Lucene.Net.Search.Weight;
 
   35 namespace Lucene.Net.Index
 
  139         private void  InitBlock()
 
  144             waitQueuePauseBytes = (long) (ramBufferSize * 0.1);
 
  145             waitQueueResumeBytes = (long) (ramBufferSize * 0.05);
 
  149             skipDocWriter = 
new SkipDocWriter();
 
  150             byteBlockAllocator = 
new ByteBlockAllocator(
this, 
DocumentsWriter.BYTE_BLOCK_SIZE);
 
  151             perDocAllocator = 
new ByteBlockAllocator(
this,
DocumentsWriter.PER_DOC_BLOCK_SIZE);
 
  152             waitQueue = 
new WaitQueue(
this);
 
  158         internal System.String segment;             
 
  159         private System.String docStoreSegment;      
 
  160         private int docStoreOffset;                 
 
  162         private int nextDocID;                      
 
  163         private int numDocsInRAM;                   
 
  164         internal int numDocsInStore;                
 
  168         private const int MAX_THREAD_STATE = 5;
 
  170         private HashMap<ThreadClass, DocumentsWriterThreadState> threadBindings = 
new HashMap<ThreadClass, DocumentsWriterThreadState>();
 
  172         private int pauseThreads; 
 
  174         internal bool flushPending; 
 
  175         internal bool bufferIsFull; 
 
  176         private bool aborting; 
 
  180         internal System.IO.StreamWriter infoStream;
 
  181         internal int maxFieldLength;
 
  184         internal IList<string> newFiles;
 
  186         internal class DocState
 
  190             internal int maxFieldLength;
 
  191             internal System.IO.StreamWriter infoStream;
 
  195             internal System.String maxTermPrefix;
 
  198             public bool TestPoint(System.String name)
 
  216         internal abstract class DocWriter
 
  218             internal DocWriter next;
 
  220             public abstract void  Finish();
 
  221             public abstract void  Abort();
 
  222             public abstract long SizeInBytes();
 
  224             internal void  SetNext(DocWriter next)
 
  233         internal PerDocBuffer NewPerDocBuffer()
 
  235             return new PerDocBuffer(
this);
 
  241         internal class PerDocBuffer : Lucene.Net.Store.RAMFile
 
  246                 this.enclosingInstance = enclosingInstance;
 
  251             public override byte[] NewBuffer(
int size)
 
  253                 System.Diagnostics.Debug.Assert(size == PER_DOC_BLOCK_SIZE);
 
  254                 return enclosingInstance.perDocAllocator.GetByteBlock(
false);
 
  260             internal void Recycle()
 
  264                     if (buffers.Count > 0)
 
  269                         enclosingInstance.perDocAllocator.RecycleByteBlocks(buffers);
 
  273                         System.Diagnostics.Debug.Assert(NumBuffers() == 0);
 
  302         private int maxBufferedDeleteTerms;
 
  306         private long ramBufferSize;
 
  307         private long waitQueuePauseBytes;
 
  308         private long waitQueueResumeBytes;
 
  312         private long freeTrigger;
 
  313         private long freeLevel;
 
  317         private int maxBufferedDocs;
 
  319         private int flushedDocCount; 
 
  321         internal void  UpdateFlushedDocCount(
int n)
 
  325                 flushedDocCount += n;
 
  328         internal int GetFlushedDocCount()
 
  332                 return flushedDocCount;
 
  335         internal void  SetFlushedDocCount(
int n)
 
  348             this.directory = directory;
 
  349             this.writer = writer;
 
  351             flushedDocCount = writer.
MaxDoc();
 
  353             consumer = indexingChain.GetChain(
this);
 
  356                 docFieldProcessor = (DocFieldProcessor) consumer;
 
  363         internal bool HasProx()
 
  365             return (docFieldProcessor != null)?docFieldProcessor.fieldInfos.HasProx():
true;
 
  371         internal void  SetInfoStream(System.IO.StreamWriter infoStream)
 
  375                 this.infoStream = infoStream;
 
  376                 for (
int i = 0; i < threadStates.Length; i++)
 
  377                     threadStates[i].docState.infoStream = infoStream;
 
  381         internal void  SetMaxFieldLength(
int maxFieldLength)
 
  385                 this.maxFieldLength = maxFieldLength;
 
  386                 for (
int i = 0; i < threadStates.Length; i++)
 
  387                     threadStates[i].docState.maxFieldLength = maxFieldLength;
 
  391         internal void  SetSimilarity(
Similarity similarity)
 
  395                 this.similarity = similarity;
 
  396                 for (
int i = 0; i < threadStates.Length; i++)
 
  397                     threadStates[i].docState.similarity = similarity;
 
  402         internal void  SetRAMBufferSizeMB(
double mb)
 
  409                     waitQueuePauseBytes = 4 * 1024 * 1024;
 
  410                     waitQueueResumeBytes = 2 * 1024 * 1024;
 
  414                     ramBufferSize = (long) (mb * 1024 * 1024);
 
  415                     waitQueuePauseBytes = (long) (ramBufferSize * 0.1);
 
  416                     waitQueueResumeBytes = (long) (ramBufferSize * 0.05);
 
  417                     freeTrigger = (long) (1.05 * ramBufferSize);
 
  418                     freeLevel = (long) (0.95 * ramBufferSize);
 
  423         internal double GetRAMBufferSizeMB()
 
  429                     return ramBufferSize;
 
  433                     return ramBufferSize / 1024.0 / 1024.0;
 
  441         internal int MaxBufferedDocs
 
  443             get { 
return maxBufferedDocs; }
 
  444             set { maxBufferedDocs = value; }
 
  448         internal string Segment
 
  450             get { 
return segment; }
 
  454         internal int NumDocsInRAM
 
  456             get { 
return numDocsInRAM; }
 
  462         internal string DocStoreSegment
 
  468                     return docStoreSegment;
 
  476         internal int DocStoreOffset
 
  478             get { 
return docStoreOffset; }
 
  485         internal System.String CloseDocStore()
 
  490                 System.Diagnostics.Debug.Assert(AllThreadsIdle());
 
  492                 if (infoStream != null)
 
  493                     Message(
"closeDocStore: " + openFiles.Count + 
" files to flush to segment " + docStoreSegment + 
" numDocs=" + numDocsInStore);
 
  495                 bool success = 
false;
 
  499                     InitFlushState(
true);
 
  502                     consumer.CloseDocStore(flushState);
 
  503                     System.Diagnostics.Debug.Assert(0 == openFiles.Count);
 
  505                     System.String s = docStoreSegment;
 
  506                     docStoreSegment = null;
 
  522         private ICollection<string> abortedFiles; 
 
  526         internal ICollection<string> AbortedFiles()
 
  531         internal void  Message(System.String message)
 
  533             if (infoStream != null)
 
  534                 writer.
Message(
"DW: " + message);
 
  537         internal IList<string> openFiles = 
new List<string>();
 
  538         internal IList<string> closedFiles = 
new List<string>();
 
  542         internal IList<string> OpenFiles()
 
  547                 return openFiles.ToArray();
 
  551         internal IList<string> ClosedFiles()
 
  556                 return closedFiles.ToArray();
 
  560         internal void  AddOpenFile(System.String name)
 
  564                 System.Diagnostics.Debug.Assert(!openFiles.Contains(name));
 
  569         internal void  RemoveOpenFile(System.String name)
 
  573                 System.Diagnostics.Debug.Assert(openFiles.Contains(name));
 
  574                 openFiles.Remove(name);
 
  575                 closedFiles.Add(name);
 
  579         internal void  SetAborting()
 
  592         internal void  Abort()
 
  598                     if (infoStream != null)
 
  600                         Message(
"docWriter: now abort");
 
  613                         System.Diagnostics.Debug.Assert(0 == waitQueue.numWaiting);
 
  615                         waitQueue.waitingBytes = 0;
 
  619                             abortedFiles = OpenFiles();
 
  621                         catch (System.Exception)
 
  626                         deletesInRAM.Clear();
 
  627                         deletesFlushed.Clear();
 
  630                         for (
int i = 0; i < threadStates.Length; i++)
 
  633                                 threadStates[i].consumer.Abort();
 
  635                             catch (System.Exception)
 
  643                         catch (System.Exception)
 
  647                         docStoreSegment = null;
 
  662                     System.Threading.Monitor.PulseAll(
this);
 
  663                     if (infoStream != null)
 
  665                         Message(
"docWriter: done abort; abortedFiles=" + abortedFiles);
 
  672         private void  DoAfterFlush()
 
  675             System.Diagnostics.Debug.Assert(AllThreadsIdle());
 
  676             threadBindings.Clear();
 
  681             bufferIsFull = 
false;
 
  682             flushPending = 
false;
 
  683             for (
int i = 0; i < threadStates.Length; i++)
 
  684                 threadStates[i].DoAfterFlush();
 
  689         internal bool PauseAllThreads()
 
  694                 while (!AllThreadsIdle())
 
  696                     System.Threading.Monitor.Wait(
this);
 
  703         internal void  ResumeAllThreads()
 
  708                 System.Diagnostics.Debug.Assert(pauseThreads >= 0);
 
  709                 if (0 == pauseThreads)
 
  710                     System.Threading.Monitor.PulseAll(
this);
 
  714         private bool AllThreadsIdle()
 
  718                 for (
int i = 0; i < threadStates.Length; i++)
 
  719                     if (!threadStates[i].isIdle)
 
  725         internal bool AnyChanges
 
  731                     return numDocsInRAM != 0 || deletesInRAM.numTerms != 0 || deletesInRAM.docIDs.Count != 0 ||
 
  732                            deletesInRAM.queries.Count != 0;
 
  737         private void  InitFlushState(
bool onlyDocStore)
 
  741                 InitSegmentName(onlyDocStore);
 
  747         internal int Flush(
bool closeDocStore)
 
  752                 System.Diagnostics.Debug.Assert(AllThreadsIdle());
 
  754                 System.Diagnostics.Debug.Assert(numDocsInRAM > 0);
 
  756                 System.Diagnostics.Debug.Assert(nextDocID == numDocsInRAM);
 
  757                 System.Diagnostics.Debug.Assert(waitQueue.numWaiting == 0);
 
  758                 System.Diagnostics.Debug.Assert(waitQueue.waitingBytes == 0);
 
  760                 InitFlushState(
false);
 
  762                 docStoreOffset = numDocsInStore;
 
  764                 if (infoStream != null)
 
  765                     Message(
"flush postings as segment " + flushState.segmentName + 
" numDocs=" + numDocsInRAM);
 
  767                 bool success = 
false;
 
  774                         System.Diagnostics.Debug.Assert(flushState.docStoreSegmentName != null);
 
  775                         System.Diagnostics.Debug.Assert(flushState.docStoreSegmentName.Equals(flushState.segmentName));
 
  777                         flushState.numDocsInStore = 0;
 
  780                     ICollection<DocConsumerPerThread> threads = 
new HashSet<DocConsumerPerThread>();
 
  781                     for (
int i = 0; i < threadStates.Length; i++)
 
  782                         threads.Add(threadStates[i].consumer);
 
  783                     consumer.Flush(threads, flushState);
 
  785                     if (infoStream != null)
 
  789                         System.String message = System.String.Format(nf, 
"  oldRAMSize={0:d} newFlushedSize={1:d} docs/MB={2:f} new/old={3:%}",
 
  790                             new System.Object[] { numBytesUsed, newSegmentSize, (numDocsInRAM / (newSegmentSize / 1024.0 / 1024.0)), (100.0 * newSegmentSize / numBytesUsed) });
 
  794                     flushedDocCount += flushState.numDocs;
 
  808                 System.Diagnostics.Debug.Assert(waitQueue.waitingBytes == 0);
 
  810                 return flushState.numDocs;
 
  814         internal ICollection<string> GetFlushedFiles()
 
  816             return flushState.flushedFiles;
 
  820         internal void  CreateCompoundFile(System.String segment)
 
  823             CompoundFileWriter cfsWriter = 
new CompoundFileWriter(directory, segment + 
"." + IndexFileNames.COMPOUND_FILE_EXTENSION);
 
  824             foreach(
string flushedFile 
in flushState.flushedFiles)
 
  826                 cfsWriter.AddFile(flushedFile);
 
  838         internal bool SetFlushPending()
 
  852         internal void  ClearFlushPending()
 
  856                 flushPending = 
false;
 
  860         internal void  PushDeletes()
 
  864                 deletesFlushed.Update(deletesInRAM);
 
  868         public void Dispose()
 
  874                 System.Threading.Monitor.PulseAll(
this);
 
  878         internal void  InitSegmentName(
bool onlyDocStore)
 
  882                 if (segment == null && (!onlyDocStore || docStoreSegment == null))
 
  884                     segment = writer.NewSegmentName();
 
  885                     System.Diagnostics.Debug.Assert(numDocsInRAM == 0);
 
  887                 if (docStoreSegment == null)
 
  889                     docStoreSegment = segment;
 
  890                     System.Diagnostics.Debug.Assert(numDocsInStore == 0);
 
  901         internal DocumentsWriterThreadState GetThreadState(
Document doc, 
Term delTerm)
 
  915                     DocumentsWriterThreadState minThreadState = null;
 
  916                     for (
int i = 0; i < threadStates.Length; i++)
 
  918                         DocumentsWriterThreadState ts = threadStates[i];
 
  919                         if (minThreadState == null || ts.numThreads < minThreadState.numThreads)
 
  922                     if (minThreadState != null && (minThreadState.numThreads == 0 || threadStates.Length >= MAX_THREAD_STATE))
 
  924                         state = minThreadState;
 
  930                         DocumentsWriterThreadState[] newArray = 
new DocumentsWriterThreadState[1 + threadStates.Length];
 
  931                         if (threadStates.Length > 0)
 
  932                             Array.Copy(threadStates, 0, newArray, 0, threadStates.Length);
 
  933                         state = newArray[threadStates.Length] = 
new DocumentsWriterThreadState(
this);
 
  934                         threadStates = newArray;
 
  946                 InitSegmentName(
false);
 
  948                 state.isIdle = 
false;
 
  950                 bool success = 
false;
 
  953                     state.docState.docID = nextDocID;
 
  955                     System.Diagnostics.Debug.Assert(writer.TestPoint(
"DocumentsWriter.ThreadState.init start"));
 
  959                         AddDeleteTerm(delTerm, state.docState.docID);
 
  960                         state.doFlushAfter = TimeToFlushDeletes();
 
  963                     System.Diagnostics.Debug.Assert(writer.TestPoint(
"DocumentsWriter.ThreadState.init after delTerm"));
 
  971                     if (!flushPending && maxBufferedDocs != 
IndexWriter.DISABLE_AUTO_FLUSH && numDocsInRAM >= maxBufferedDocs)
 
  974                         state.doFlushAfter = 
true;
 
  985                         System.Threading.Monitor.PulseAll(
this);
 
  986                         if (state.doFlushAfter)
 
  988                             state.doFlushAfter = 
false;
 
  989                             flushPending = 
false;
 
 1003             return UpdateDocument(doc, analyzer, null);
 
 1008             return UpdateDocument(doc, analyzer, t);
 
 1015             DocumentsWriterThreadState state = GetThreadState(doc, delTerm);
 
 1017             DocState docState = state.docState;
 
 1019             docState.analyzer = analyzer;
 
 1021             bool doReturnFalse = 
false; 
 
 1023             bool success = 
false;
 
 1031                     perDoc = state.consumer.ProcessDocument();
 
 1038                 FinishDocument(state, perDoc);
 
 1050                             state.isIdle = 
true;
 
 1051                             System.Threading.Monitor.PulseAll(
this);
 
 1056                             skipDocWriter.docID = docState.docID;
 
 1057                             bool success2 = 
false;
 
 1060                                 waitQueue.Add(skipDocWriter);
 
 1067                                     state.isIdle = 
true;
 
 1068                                     System.Threading.Monitor.PulseAll(
this);
 
 1071                                     doReturnFalse = 
true;
 
 1077                                 state.isIdle = 
true;
 
 1078                                 System.Threading.Monitor.PulseAll(
this);
 
 1082                                 if (state.doFlushAfter)
 
 1084                                     state.doFlushAfter = 
false;
 
 1085                                     flushPending = 
false;
 
 1086                                     System.Threading.Monitor.PulseAll(
this);
 
 1093                                 AddDeleteDocID(state.docState.docID);
 
 1105             return state.doFlushAfter || TimeToFlushDeletes();
 
 1109         internal int GetNumBufferedDeleteTerms()
 
 1113                 return deletesInRAM.numTerms; 
 
 1118         internal IDictionary<
Term, BufferedDeletes.Num> GetBufferedDeleteTerms()
 
 1122                 return deletesInRAM.terms;
 
 1127         internal void  RemapDeletes(SegmentInfos infos, 
int[][] docMaps, 
int[] delCounts, MergePolicy.OneMerge merge, 
int mergeDocCount)
 
 1131                 if (docMaps == null)
 
 1134                 MergeDocIDRemapper mapper = 
new MergeDocIDRemapper(infos, docMaps, delCounts, merge, mergeDocCount);
 
 1135                 deletesInRAM.Remap(mapper, infos, docMaps, delCounts, merge, mergeDocCount);
 
 1136                 deletesFlushed.Remap(mapper, infos, docMaps, delCounts, merge, mergeDocCount);
 
 1137                 flushedDocCount -= mapper.docShift;
 
 1141         private void  WaitReady(DocumentsWriterThreadState state)
 
 1146                 while (!closed && ((state != null && !state.isIdle) || pauseThreads != 0 || flushPending || aborting))
 
 1148                     System.Threading.Monitor.Wait(
this);
 
 1156         internal bool BufferDeleteTerms(
Term[] terms)
 
 1161                 for (
int i = 0; i < terms.Length; i++)
 
 1162                     AddDeleteTerm(terms[i], numDocsInRAM);
 
 1163                 return TimeToFlushDeletes();
 
 1167         internal bool BufferDeleteTerm(
Term term)
 
 1172                 AddDeleteTerm(term, numDocsInRAM);
 
 1173                 return TimeToFlushDeletes();
 
 1177         internal bool BufferDeleteQueries(
Query[] queries)
 
 1182                 for (
int i = 0; i < queries.Length; i++)
 
 1183                     AddDeleteQuery(queries[i], numDocsInRAM);
 
 1184                 return TimeToFlushDeletes();
 
 1188         internal bool BufferDeleteQuery(
Query query)
 
 1193                 AddDeleteQuery(query, numDocsInRAM);
 
 1194                 return TimeToFlushDeletes();
 
 1198         internal bool DeletesFull()
 
 1202                 return (ramBufferSize != 
IndexWriter.DISABLE_AUTO_FLUSH && (deletesInRAM.bytesUsed + deletesFlushed.bytesUsed + numBytesUsed) >= ramBufferSize) || (maxBufferedDeleteTerms != 
IndexWriter.DISABLE_AUTO_FLUSH && ((deletesInRAM.Size() + deletesFlushed.Size()) >= maxBufferedDeleteTerms));
 
 1206         internal bool DoApplyDeletes()
 
 1218                 return (ramBufferSize != 
IndexWriter.DISABLE_AUTO_FLUSH && (deletesInRAM.bytesUsed + deletesFlushed.bytesUsed) >= ramBufferSize / 2) || (maxBufferedDeleteTerms != 
IndexWriter.DISABLE_AUTO_FLUSH && ((deletesInRAM.Size() + deletesFlushed.Size()) >= maxBufferedDeleteTerms));
 
 1222         private bool TimeToFlushDeletes()
 
 1226                 return (bufferIsFull || DeletesFull()) && SetFlushPending();
 
 1230         internal int MaxBufferedDeleteTerms
 
 1232             set { this.maxBufferedDeleteTerms = value; }
 
 1233             get { 
return maxBufferedDeleteTerms; }
 
 1236         internal bool HasDeletes()
 
 1240                 return deletesFlushed.Any();
 
 1244         internal bool ApplyDeletes(SegmentInfos infos)
 
 1251                 if (infoStream != null)
 
 1252                     Message(
"apply " + deletesFlushed.numTerms + 
" buffered deleted terms and " + deletesFlushed.docIDs.Count + 
" deleted docIDs and " + deletesFlushed.queries.Count + 
" deleted queries on " + (+ infos.Count) + 
" segments.");
 
 1254                 int infosEnd = infos.Count;
 
 1258                 for (
int i = 0; i < infosEnd; i++)
 
 1263                     System.Diagnostics.Debug.Assert(infos.Info(i).dir == directory);
 
 1265                     SegmentReader reader = writer.readerPool.Get(infos.Info(i), 
false);
 
 1268                         any |= ApplyDeletes(reader, docStart);
 
 1269                         docStart += reader.MaxDoc;
 
 1273                         writer.readerPool.Release(reader);
 
 1277                 deletesFlushed.Clear();
 
 1284         private Term lastDeleteTerm;
 
 1287         private bool CheckDeleteTerm(
Term term) 
 
 1290                 System.Diagnostics.Debug.Assert(lastDeleteTerm == null || term.CompareTo(lastDeleteTerm) > 0, 
"lastTerm=" + lastDeleteTerm + 
" vs term=" + term);
 
 1292             lastDeleteTerm = term;
 
 1298         private bool ApplyDeletes(
IndexReader reader, 
int docIDStart)
 
 1302                 int docEnd = docIDStart + reader.MaxDoc;
 
 1305                 System.Diagnostics.Debug.Assert(CheckDeleteTerm(null));
 
 1311                     foreach(KeyValuePair<Term, BufferedDeletes.Num> entry 
in deletesFlushed.terms)
 
 1313                         Term term = entry.Key;
 
 1316                         System.Diagnostics.Debug.Assert(CheckDeleteTerm(term));
 
 1318                         int limit = entry.Value.GetNum();
 
 1321                             int docID = docs.Doc;
 
 1322                             if (docIDStart + docID >= limit)
 
 1324                             reader.DeleteDocument(docID);
 
 1335                 foreach(
int docIdInt 
in deletesFlushed.docIDs)
 
 1337                     int docID = docIdInt;
 
 1338                     if (docID >= docIDStart && docID < docEnd)
 
 1340                         reader.DeleteDocument(docID - docIDStart);
 
 1347                 foreach(KeyValuePair<Query, int> entry 
in deletesFlushed.queries)
 
 1350                     int limit = (
int)entry.Value;
 
 1351                     Weight weight = query.Weight(searcher);
 
 1352                     Scorer scorer = weight.Scorer(reader, 
true, 
false);
 
 1357                             int doc = scorer.NextDoc();
 
 1358                             if (((
long) docIDStart) + doc >= limit)
 
 1360                             reader.DeleteDocument(doc);
 
 1374         private void  AddDeleteTerm(
Term term, 
int docCount)
 
 1378                 BufferedDeletes.Num num = deletesInRAM.terms[term];
 
 1379                 int docIDUpto = flushedDocCount + docCount;
 
 1381                     deletesInRAM.terms[term] = 
new BufferedDeletes.Num(docIDUpto);
 
 1383                     num.SetNum(docIDUpto);
 
 1384                 deletesInRAM.numTerms++;
 
 1386                 deletesInRAM.AddBytesUsed(BYTES_PER_DEL_TERM + term.Text.Length * CHAR_NUM_BYTE);
 
 1392         private void  AddDeleteDocID(
int docID)
 
 1396                 deletesInRAM.docIDs.Add(flushedDocCount + docID);
 
 1397                 deletesInRAM.AddBytesUsed(BYTES_PER_DEL_DOCID);
 
 1401         private void  AddDeleteQuery(
Query query, 
int docID)
 
 1405                 deletesInRAM.queries[query] = flushedDocCount + docID;
 
 1406                 deletesInRAM.AddBytesUsed(BYTES_PER_DEL_QUERY);
 
 1410         internal bool DoBalanceRAM()
 
 1414                 return ramBufferSize != 
IndexWriter.DISABLE_AUTO_FLUSH && !bufferIsFull && (numBytesUsed + deletesInRAM.bytesUsed + deletesFlushed.bytesUsed >= ramBufferSize || numBytesAlloc >= freeTrigger);
 
 1421         private void  FinishDocument(DocumentsWriterThreadState perThread, DocWriter docWriter)
 
 1432                 System.Diagnostics.Debug.Assert(docWriter == null || docWriter.docID == perThread.docState.docID);
 
 1441                     if (docWriter != null)
 
 1446                         catch (System.Exception)
 
 1450                     perThread.isIdle = 
true;
 
 1451                     System.Threading.Monitor.PulseAll(
this);
 
 1457                 if (docWriter != null)
 
 1458                     doPause = waitQueue.Add(docWriter);
 
 1461                     skipDocWriter.docID = perThread.docState.docID;
 
 1462                     doPause = waitQueue.Add(skipDocWriter);
 
 1468                 if (bufferIsFull && !flushPending)
 
 1470                     flushPending = 
true;
 
 1471                     perThread.doFlushAfter = 
true;
 
 1474                 perThread.isIdle = 
true;
 
 1475                 System.Threading.Monitor.PulseAll(
this);
 
 1479         internal void  WaitForWaitQueue()
 
 1485                     System.Threading.Monitor.Wait(
this);
 
 1487                 while (!waitQueue.DoResume());
 
 1491         internal class SkipDocWriter:DocWriter
 
 1493             public override void  Finish()
 
 1496             public override void  Abort()
 
 1499             public override long SizeInBytes()
 
 1504         internal SkipDocWriter skipDocWriter;
 
 1506         internal long GetRAMUsed()
 
 1508             return numBytesUsed + deletesInRAM.bytesUsed + deletesFlushed.bytesUsed;
 
 1511         internal long numBytesAlloc;
 
 1512         internal long numBytesUsed;
 
 1514         internal System.Globalization.NumberFormatInfo nf = System.Globalization.CultureInfo.CurrentCulture.NumberFormat;
 
 1517         internal const int OBJECT_HEADER_BYTES = 8;
 
 1518         internal static readonly 
int POINTER_NUM_BYTE;
 
 1519         internal const int INT_NUM_BYTE = 4;
 
 1520         internal const int CHAR_NUM_BYTE = 2;
 
 1532         internal static readonly 
int BYTES_PER_DEL_TERM = 8 * POINTER_NUM_BYTE + 5 * OBJECT_HEADER_BYTES + 6 * INT_NUM_BYTE;
 
 1537         internal static readonly 
int BYTES_PER_DEL_DOCID = 2 * POINTER_NUM_BYTE + OBJECT_HEADER_BYTES + INT_NUM_BYTE;
 
 1544         internal static readonly 
int BYTES_PER_DEL_QUERY = 5 * POINTER_NUM_BYTE + 2 * OBJECT_HEADER_BYTES + 2 * INT_NUM_BYTE + 24;
 
 1548         internal const int BYTE_BLOCK_SHIFT = 15;
 
 1549         internal static readonly 
int BYTE_BLOCK_SIZE = 1 << BYTE_BLOCK_SHIFT;
 
 1550         internal static readonly 
int BYTE_BLOCK_MASK = BYTE_BLOCK_SIZE - 1;
 
 1551         internal static readonly 
int BYTE_BLOCK_NOT_MASK = ~ BYTE_BLOCK_MASK;
 
 1553         internal class ByteBlockAllocator : ByteBlockPool.Allocator
 
 1555             public ByteBlockAllocator(DocumentsWriter enclosingInstance, 
int blockSize)
 
 1557                 this.blockSize = blockSize;
 
 1558                 InitBlock(enclosingInstance);
 
 1560             private void  InitBlock(DocumentsWriter enclosingInstance)
 
 1562                 this.enclosingInstance = enclosingInstance;
 
 1564             private DocumentsWriter enclosingInstance;
 
 1565             public DocumentsWriter Enclosing_Instance
 
 1569                     return enclosingInstance;
 
 1575             internal List<byte[]> freeByteBlocks = 
new List<byte[]>();
 
 1578             public  override byte[] GetByteBlock(
bool trackAllocations)
 
 1580                 lock (Enclosing_Instance)
 
 1582                     int size = freeByteBlocks.Count;
 
 1592                         Enclosing_Instance.numBytesAlloc += blockSize;
 
 1593                         b = 
new byte[blockSize];
 
 1597                         b = freeByteBlocks[size - 1];
 
 1598                         freeByteBlocks.RemoveAt(size - 1);
 
 1600                     if (trackAllocations)
 
 1601                         Enclosing_Instance.numBytesUsed += blockSize;
 
 1602                     System.Diagnostics.Debug.Assert(Enclosing_Instance.numBytesUsed <= Enclosing_Instance.numBytesAlloc);
 
 1608             public  override void  RecycleByteBlocks(byte[][] blocks, 
int start, 
int end)
 
 1610                 lock (Enclosing_Instance)
 
 1612                     for (
int i = start; i < end; i++)
 
 1614                         freeByteBlocks.Add(blocks[i]);
 
 1620             public  override void RecycleByteBlocks(IList<byte[]> blocks)
 
 1622                 lock (Enclosing_Instance)
 
 1624                     int size = blocks.Count;
 
 1625                     for(
int i=0;i<size;i++)
 
 1626                         freeByteBlocks.Add(blocks[i]);
 
 1633         internal const int INT_BLOCK_SHIFT = 13;
 
 1634         internal static readonly 
int INT_BLOCK_SIZE = 1 << INT_BLOCK_SHIFT;
 
 1635         internal static readonly 
int INT_BLOCK_MASK = INT_BLOCK_SIZE - 1;
 
 1637         private List<int[]> freeIntBlocks = 
new List<int[]>();
 
 1640         internal int[] GetIntBlock(
bool trackAllocations)
 
 1644                 int size = freeIntBlocks.Count;
 
 1654                     numBytesAlloc += INT_BLOCK_SIZE * INT_NUM_BYTE;
 
 1655                     b = 
new int[INT_BLOCK_SIZE];
 
 1659                     b = freeIntBlocks[size - 1];
 
 1660                     freeIntBlocks.RemoveAt(size - 1);
 
 1662                 if (trackAllocations)
 
 1663                     numBytesUsed += INT_BLOCK_SIZE * INT_NUM_BYTE;
 
 1664                 System.Diagnostics.Debug.Assert(numBytesUsed <= numBytesAlloc);
 
 1669         internal void  BytesAllocated(
long numBytes)
 
 1673                 numBytesAlloc += numBytes;
 
 1677         internal void  BytesUsed(
long numBytes)
 
 1681                 numBytesUsed += numBytes;
 
 1682                 System.Diagnostics.Debug.Assert(numBytesUsed <= numBytesAlloc);
 
 1687         internal void  RecycleIntBlocks(
int[][] blocks, 
int start, 
int end)
 
 1691                 for (
int i = start; i < end; i++)
 
 1693                     freeIntBlocks.Add(blocks[i]);
 
 1699         internal ByteBlockAllocator byteBlockAllocator;
 
 1701         internal static int PER_DOC_BLOCK_SIZE = 1024;
 
 1703         ByteBlockAllocator perDocAllocator;
 
 1707         internal const int CHAR_BLOCK_SHIFT = 14;
 
 1708         internal static readonly 
int CHAR_BLOCK_SIZE = 1 << CHAR_BLOCK_SHIFT;
 
 1709         internal static readonly 
int CHAR_BLOCK_MASK = CHAR_BLOCK_SIZE - 1;
 
 1711         internal static readonly 
int MAX_TERM_LENGTH = CHAR_BLOCK_SIZE - 1;
 
 1713         private List<char[]> freeCharBlocks = 
new List<char[]>();
 
 1716         internal char[] GetCharBlock()
 
 1720                 int size = freeCharBlocks.Count;
 
 1724                     numBytesAlloc += CHAR_BLOCK_SIZE * CHAR_NUM_BYTE;
 
 1725                     c = 
new char[CHAR_BLOCK_SIZE];
 
 1729                     c = freeCharBlocks[size - 1];
 
 1730                     freeCharBlocks.RemoveAt(size - 1);
 
 1736                 numBytesUsed += CHAR_BLOCK_SIZE * CHAR_NUM_BYTE;
 
 1737                 System.Diagnostics.Debug.Assert(numBytesUsed <= numBytesAlloc);
 
 1743         internal void  RecycleCharBlocks(
char[][] blocks, 
int numBlocks)
 
 1747                 for (
int i = 0; i < numBlocks; i++)
 
 1749                     freeCharBlocks.Add(blocks[i]);
 
 1755         internal System.String ToMB(
long v)
 
 1757             return System.String.Format(nf, 
"{0:f}", 
new System.Object[] { (v / 1024F / 1024F) });
 
 1774         internal void  BalanceRAM()
 
 1778             long flushTrigger = ramBufferSize;
 
 1780             long deletesRAMUsed = deletesInRAM.bytesUsed + deletesFlushed.bytesUsed;
 
 1782             if (numBytesAlloc + deletesRAMUsed > freeTrigger)
 
 1785                 if (infoStream != null)
 
 1787                         "  RAM: now balance allocations: usedMB=" + ToMB(numBytesUsed) + 
 
 1788                         " vs trigger=" + ToMB(flushTrigger) + 
 
 1789                         " allocMB=" + ToMB(numBytesAlloc) + 
 
 1790                         " deletesMB=" + ToMB(deletesRAMUsed) + 
 
 1791                         " vs trigger=" + ToMB(freeTrigger) + 
 
 1792                         " byteBlockFree=" + ToMB(byteBlockAllocator.freeByteBlocks.Count * BYTE_BLOCK_SIZE) +
 
 1793                         " perDocFree=" + ToMB(perDocAllocator.freeByteBlocks.Count * PER_DOC_BLOCK_SIZE) +
 
 1794                         " charBlockFree=" + ToMB(freeCharBlocks.Count * CHAR_BLOCK_SIZE * CHAR_NUM_BYTE));
 
 1796                 long startBytesAlloc = numBytesAlloc + deletesRAMUsed;
 
 1806                 while (numBytesAlloc + deletesRAMUsed > freeLevel)
 
 1811                         if (0 == perDocAllocator.freeByteBlocks.Count
 
 1812                               && 0 == byteBlockAllocator.freeByteBlocks.Count
 
 1813                               && 0 == freeCharBlocks.Count
 
 1814                               && 0 == freeIntBlocks.Count
 
 1818                             bufferIsFull = numBytesUsed + deletesRAMUsed > flushTrigger;
 
 1819                             if (infoStream != null)
 
 1822                                     Message(
"    nothing to free; now set bufferIsFull");
 
 1824                                     Message(
"    nothing to free");
 
 1826                             System.Diagnostics.Debug.Assert(numBytesUsed <= numBytesAlloc);
 
 1830                         if ((0 == iter % 5) && byteBlockAllocator.freeByteBlocks.Count > 0)
 
 1832                             byteBlockAllocator.freeByteBlocks.RemoveAt(byteBlockAllocator.freeByteBlocks.Count - 1);
 
 1833                             numBytesAlloc -= BYTE_BLOCK_SIZE;
 
 1836                         if ((1 == iter % 5) && freeCharBlocks.Count > 0)
 
 1838                             freeCharBlocks.RemoveAt(freeCharBlocks.Count - 1);
 
 1839                             numBytesAlloc -= CHAR_BLOCK_SIZE * CHAR_NUM_BYTE;
 
 1842                         if ((2 == iter % 5) && freeIntBlocks.Count > 0)
 
 1844                             freeIntBlocks.RemoveAt(freeIntBlocks.Count - 1);
 
 1845                             numBytesAlloc -= INT_BLOCK_SIZE * INT_NUM_BYTE;
 
 1848                         if ((3 == iter % 5) && perDocAllocator.freeByteBlocks.Count > 0)
 
 1851                             for (
int i = 0; i < 32; ++i)
 
 1853                                 perDocAllocator.freeByteBlocks.RemoveAt(perDocAllocator.freeByteBlocks.Count - 1);
 
 1854                                 numBytesAlloc -= PER_DOC_BLOCK_SIZE;
 
 1855                                 if (perDocAllocator.freeByteBlocks.Count == 0)
 
 1863                     if ((4 == iter % 5) && any)
 
 1865                         any = consumer.FreeRAM();
 
 1870                 if (infoStream != null)
 
 1871                     Message(System.String.Format(nf, 
"    after free: freedMB={0:f} usedMB={1:f} allocMB={2:f}",
 
 1872                         new System.Object[] { ((startBytesAlloc - numBytesAlloc) / 1024.0 / 1024.0), (numBytesUsed / 1024.0 / 1024.0), (numBytesAlloc / 1024.0 / 1024.0) }));
 
 1884                     if (numBytesUsed + deletesRAMUsed > flushTrigger)
 
 1886                         if (infoStream != null)
 
 1887                             Message(System.String.Format(nf, 
"  RAM: now flush @ usedMB={0:f} allocMB={1:f} triggerMB={2:f}",
 
 1888                                 new object[] { (numBytesUsed / 1024.0 / 1024.0), (numBytesAlloc / 1024.0 / 1024.0), (flushTrigger / 1024.0 / 1024.0) }));
 
 1890                         bufferIsFull = 
true;
 
 1896         internal WaitQueue waitQueue;
 
 1898         internal class WaitQueue
 
 1900             private void  InitBlock(DocumentsWriter enclosingInstance)
 
 1902                 this.enclosingInstance = enclosingInstance;
 
 1904             private DocumentsWriter enclosingInstance;
 
 1905             public DocumentsWriter Enclosing_Instance
 
 1909                     return enclosingInstance;
 
 1913             internal DocWriter[] waiting;
 
 1914             internal int nextWriteDocID;
 
 1915             internal int nextWriteLoc;
 
 1916             internal int numWaiting;
 
 1917             internal long waitingBytes;
 
 1919             public WaitQueue(DocumentsWriter enclosingInstance)
 
 1921                 InitBlock(enclosingInstance);
 
 1922                 waiting = 
new DocWriter[10];
 
 1925             internal void  Reset()
 
 1930                     System.Diagnostics.Debug.Assert(numWaiting == 0);
 
 1931                     System.Diagnostics.Debug.Assert(waitingBytes == 0);
 
 1936             internal bool DoResume()
 
 1940                     return waitingBytes <= Enclosing_Instance.waitQueueResumeBytes;
 
 1944             internal bool DoPause()
 
 1948                     return waitingBytes > Enclosing_Instance.waitQueuePauseBytes;
 
 1952             internal void  Abort()
 
 1957                     for (
int i = 0; i < waiting.Length; i++)
 
 1959                         DocWriter doc = waiting[i];
 
 1968                     System.Diagnostics.Debug.Assert(count == numWaiting);
 
 1973             private void  WriteDocument(DocWriter doc)
 
 1975                 System.Diagnostics.Debug.Assert(doc == Enclosing_Instance.skipDocWriter || nextWriteDocID == doc.docID);
 
 1976                 bool success = 
false;
 
 1981                     Enclosing_Instance.numDocsInStore++;
 
 1983                     System.Diagnostics.Debug.Assert(nextWriteLoc <= waiting.Length);
 
 1984                     if (nextWriteLoc == waiting.Length)
 
 1991                         Enclosing_Instance.SetAborting();
 
 1995             public bool Add(DocWriter doc)
 
 2000                     System.Diagnostics.Debug.Assert(doc.docID >= nextWriteDocID);
 
 2002                     if (doc.docID == nextWriteDocID)
 
 2007                             doc = waiting[nextWriteLoc];
 
 2011                                 waiting[nextWriteLoc] = null;
 
 2012                                 waitingBytes -= doc.SizeInBytes();
 
 2028                         int gap = doc.docID - nextWriteDocID;
 
 2029                         if (gap >= waiting.Length)
 
 2032                             DocWriter[] newArray = 
new DocWriter[
ArrayUtil.GetNextSize(gap)];
 
 2033                             System.Diagnostics.Debug.Assert(nextWriteLoc >= 0);
 
 2034                             Array.Copy(waiting, nextWriteLoc, newArray, 0, waiting.Length - nextWriteLoc);
 
 2035                             Array.Copy(waiting, 0, newArray, waiting.Length - nextWriteLoc, nextWriteLoc);
 
 2038                             gap = doc.docID - nextWriteDocID;
 
 2041                         int loc = nextWriteLoc + gap;
 
 2042                         if (loc >= waiting.Length)
 
 2043                             loc -= waiting.Length;
 
 2046                         System.Diagnostics.Debug.Assert(loc < waiting.Length);
 
 2049                         System.Diagnostics.Debug.Assert(waiting [loc] == null);
 
 2052                         waitingBytes += doc.SizeInBytes();
 
 2059         static DocumentsWriter()
 
 2061             DefaultIndexingChain = 
new AnonymousClassIndexingChain();
 
 2062             POINTER_NUM_BYTE = 
Constants.JRE_IS_64BIT?8:4;
 
 2065         public static int BYTE_BLOCK_SIZE_ForNUnit
 
 2067             get { 
return BYTE_BLOCK_SIZE; }
 
 2070         public static int CHAR_BLOCK_SIZE_ForNUnit
 
 2072             get { 
return CHAR_BLOCK_SIZE; }