2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
20 using RAMOutputStream = Mono.Lucene.Net.Store.RAMOutputStream;
21 using ArrayUtil = Mono.Lucene.Net.Util.ArrayUtil;
23 namespace Mono.Lucene.Net.Index
26 /// <summary>This is a DocFieldConsumer that writes stored fields. </summary>
27 sealed class StoredFieldsWriter
29 private void InitBlock()
31 docFreeList = new PerDoc[1];
34 internal FieldsWriter fieldsWriter;
35 internal DocumentsWriter docWriter;
36 internal FieldInfos fieldInfos;
37 internal int lastDocID;
39 internal PerDoc[] docFreeList;
40 internal int freeCount;
42 public StoredFieldsWriter(DocumentsWriter docWriter, FieldInfos fieldInfos)
45 this.docWriter = docWriter;
46 this.fieldInfos = fieldInfos;
49 public StoredFieldsWriterPerThread AddThread(DocumentsWriter.DocState docState)
51 return new StoredFieldsWriterPerThread(docState, this);
54 public void Flush(SegmentWriteState state)
59 if (state.numDocsInStore > 0)
61 // It's possible that all documents seen in this segment
62 // hit non-aborting exceptions, in which case we will
63 // not have yet init'd the FieldsWriter:
66 // Fill fdx file to include any final docs that we
67 // skipped because they hit non-aborting exceptions
68 Fill(state.numDocsInStore - docWriter.GetDocStoreOffset());
71 if (fieldsWriter != null)
76 private void InitFieldsWriter()
78 if (fieldsWriter == null)
80 System.String docStoreSegment = docWriter.GetDocStoreSegment();
81 if (docStoreSegment != null)
83 System.Diagnostics.Debug.Assert(docStoreSegment != null);
84 fieldsWriter = new FieldsWriter(docWriter.directory, docStoreSegment, fieldInfos);
85 docWriter.AddOpenFile(docStoreSegment + "." + IndexFileNames.FIELDS_EXTENSION);
86 docWriter.AddOpenFile(docStoreSegment + "." + IndexFileNames.FIELDS_INDEX_EXTENSION);
92 public void CloseDocStore(SegmentWriteState state)
96 int inc = state.numDocsInStore - lastDocID;
100 Fill(state.numDocsInStore - docWriter.GetDocStoreOffset());
103 if (fieldsWriter != null)
105 fieldsWriter.Close();
108 System.Diagnostics.Debug.Assert(state.docStoreSegmentName != null);
109 SupportClass.CollectionsHelper.AddIfNotContains(state.flushedFiles, state.docStoreSegmentName + "." + IndexFileNames.FIELDS_EXTENSION);
110 SupportClass.CollectionsHelper.AddIfNotContains(state.flushedFiles, state.docStoreSegmentName + "." + IndexFileNames.FIELDS_INDEX_EXTENSION);
112 state.docWriter.RemoveOpenFile(state.docStoreSegmentName + "." + IndexFileNames.FIELDS_EXTENSION);
113 state.docWriter.RemoveOpenFile(state.docStoreSegmentName + "." + IndexFileNames.FIELDS_INDEX_EXTENSION);
115 System.String fileName = state.docStoreSegmentName + "." + IndexFileNames.FIELDS_INDEX_EXTENSION;
117 if (4 + ((long) state.numDocsInStore) * 8 != state.directory.FileLength(fileName))
118 throw new System.SystemException("after flush: fdx size mismatch: " + state.numDocsInStore + " docs vs " + state.directory.FileLength(fileName) + " length in bytes of " + fileName + " file exists?=" + state.directory.FileExists(fileName));
123 internal int allocCount;
125 internal PerDoc GetPerDoc()
132 if (allocCount > docFreeList.Length)
134 // Grow our free list up front to make sure we have
135 // enough space to recycle all outstanding PerDoc
137 System.Diagnostics.Debug.Assert(allocCount == 1 + docFreeList.Length);
138 docFreeList = new PerDoc[ArrayUtil.GetNextSize(allocCount)];
140 return new PerDoc(this);
143 return docFreeList[--freeCount];
147 internal void Abort()
151 if (fieldsWriter != null)
155 fieldsWriter.Close();
157 catch (System.Exception t)
166 /// <summary>Fills in any hole in the docIDs </summary>
167 internal void Fill(int docID)
169 int docStoreOffset = docWriter.GetDocStoreOffset();
171 // We must "catch up" for all docs before us
172 // that had no stored fields:
173 int end = docID + docStoreOffset;
174 while (lastDocID < end)
176 fieldsWriter.SkipDocument();
181 internal void FinishDocument(PerDoc perDoc)
185 System.Diagnostics.Debug.Assert(docWriter.writer.TestPoint("StoredFieldsWriter.finishDocument start"));
190 // Append stored fields to the real FieldsWriter:
191 fieldsWriter.FlushDocument(perDoc.numStoredFields, perDoc.fdt);
195 System.Diagnostics.Debug.Assert(docWriter.writer.TestPoint("StoredFieldsWriter.finishDocument end"));
199 public bool FreeRAM()
204 internal void Free(PerDoc perDoc)
208 System.Diagnostics.Debug.Assert(freeCount < docFreeList.Length);
209 System.Diagnostics.Debug.Assert(0 == perDoc.numStoredFields);
210 System.Diagnostics.Debug.Assert(0 == perDoc.fdt.Length());
211 System.Diagnostics.Debug.Assert(0 == perDoc.fdt.GetFilePointer());
212 docFreeList[freeCount++] = perDoc;
216 internal class PerDoc:DocumentsWriter.DocWriter
218 public PerDoc(StoredFieldsWriter enclosingInstance)
220 InitBlock(enclosingInstance);
222 private void InitBlock(StoredFieldsWriter enclosingInstance)
224 this.enclosingInstance = enclosingInstance;
225 buffer = enclosingInstance.docWriter.NewPerDocBuffer();
226 fdt = new RAMOutputStream(buffer);
228 private StoredFieldsWriter enclosingInstance;
229 public StoredFieldsWriter Enclosing_Instance
233 return enclosingInstance;
238 internal DocumentsWriter.PerDocBuffer buffer ;
239 internal RAMOutputStream fdt;
240 internal int numStoredFields;
242 internal void Reset()
249 public override void Abort()
252 Enclosing_Instance.Free(this);
255 public override long SizeInBytes()
257 return buffer.GetSizeInBytes();
260 public override void Finish()
262 Enclosing_Instance.FinishDocument(this);