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; }