Lucene.Net  3.0.3
Lucene.Net is a port of the Lucene search engine library, written in C# and targeted at .NET runtime users.
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Properties Pages
StoredFieldsWriter.cs
Go to the documentation of this file.
1 /*
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
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
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.
16  */
17 
18 using System;
19 
20 using RAMOutputStream = Lucene.Net.Store.RAMOutputStream;
21 using ArrayUtil = Lucene.Net.Util.ArrayUtil;
22 
23 namespace Lucene.Net.Index
24 {
25 
26  /// <summary>This is a DocFieldConsumer that writes stored fields. </summary>
27  sealed class StoredFieldsWriter
28  {
29  private void InitBlock()
30  {
31  docFreeList = new PerDoc[1];
32  }
33 
34  internal FieldsWriter fieldsWriter;
35  internal DocumentsWriter docWriter;
36  internal FieldInfos fieldInfos;
37  internal int lastDocID;
38 
39  internal PerDoc[] docFreeList;
40  internal int freeCount;
41 
42  public StoredFieldsWriter(DocumentsWriter docWriter, FieldInfos fieldInfos)
43  {
44  InitBlock();
45  this.docWriter = docWriter;
46  this.fieldInfos = fieldInfos;
47  }
48 
49  public StoredFieldsWriterPerThread AddThread(DocumentsWriter.DocState docState)
50  {
51  return new StoredFieldsWriterPerThread(docState, this);
52  }
53 
54  public void Flush(SegmentWriteState state)
55  {
56  lock (this)
57  {
58 
59  if (state.numDocsInStore > 0)
60  {
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:
64  InitFieldsWriter();
65 
66  // Fill fdx file to include any final docs that we
67  // skipped because they hit non-aborting exceptions
68  Fill(state.numDocsInStore - docWriter.DocStoreOffset);
69  }
70 
71  if (fieldsWriter != null)
72  fieldsWriter.Flush();
73  }
74  }
75 
76  private void InitFieldsWriter()
77  {
78  if (fieldsWriter == null)
79  {
80  System.String docStoreSegment = docWriter.DocStoreSegment;
81  if (docStoreSegment != null)
82  {
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);
87  lastDocID = 0;
88  }
89  }
90  }
91 
92  public void CloseDocStore(SegmentWriteState state)
93  {
94  lock (this)
95  {
96  int inc = state.numDocsInStore - lastDocID;
97  if (inc > 0)
98  {
99  InitFieldsWriter();
100  Fill(state.numDocsInStore - docWriter.DocStoreOffset);
101  }
102 
103  if (fieldsWriter != null)
104  {
105  fieldsWriter.Dispose();
106  fieldsWriter = null;
107  lastDocID = 0;
108  System.Diagnostics.Debug.Assert(state.docStoreSegmentName != null);
109  state.flushedFiles.Add(state.docStoreSegmentName + "." + IndexFileNames.FIELDS_EXTENSION);
110  state.flushedFiles.Add(state.docStoreSegmentName + "." + IndexFileNames.FIELDS_INDEX_EXTENSION);
111 
112  state.docWriter.RemoveOpenFile(state.docStoreSegmentName + "." + IndexFileNames.FIELDS_EXTENSION);
113  state.docWriter.RemoveOpenFile(state.docStoreSegmentName + "." + IndexFileNames.FIELDS_INDEX_EXTENSION);
114 
115  System.String fileName = state.docStoreSegmentName + "." + IndexFileNames.FIELDS_INDEX_EXTENSION;
116 
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));
119  }
120  }
121  }
122 
123  internal int allocCount;
124 
125  internal PerDoc GetPerDoc()
126  {
127  lock (this)
128  {
129  if (freeCount == 0)
130  {
131  allocCount++;
132  if (allocCount > docFreeList.Length)
133  {
134  // Grow our free list up front to make sure we have
135  // enough space to recycle all outstanding PerDoc
136  // instances
137  System.Diagnostics.Debug.Assert(allocCount == 1 + docFreeList.Length);
138  docFreeList = new PerDoc[ArrayUtil.GetNextSize(allocCount)];
139  }
140  return new PerDoc(this);
141  }
142  else
143  return docFreeList[--freeCount];
144  }
145  }
146 
147  internal void Abort()
148  {
149  lock (this)
150  {
151  if (fieldsWriter != null)
152  {
153  try
154  {
155  fieldsWriter.Dispose();
156  }
157  catch (System.Exception)
158  {
159  }
160  fieldsWriter = null;
161  lastDocID = 0;
162  }
163  }
164  }
165 
166  /// <summary>Fills in any hole in the docIDs </summary>
167  internal void Fill(int docID)
168  {
169  int docStoreOffset = docWriter.DocStoreOffset;
170 
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)
175  {
176  fieldsWriter.SkipDocument();
177  lastDocID++;
178  }
179  }
180 
181  internal void FinishDocument(PerDoc perDoc)
182  {
183  lock (this)
184  {
185  System.Diagnostics.Debug.Assert(docWriter.writer.TestPoint("StoredFieldsWriter.finishDocument start"));
186  InitFieldsWriter();
187 
188  Fill(perDoc.docID);
189 
190  // Append stored fields to the real FieldsWriter:
191  fieldsWriter.FlushDocument(perDoc.numStoredFields, perDoc.fdt);
192  lastDocID++;
193  perDoc.Reset();
194  Free(perDoc);
195  System.Diagnostics.Debug.Assert(docWriter.writer.TestPoint("StoredFieldsWriter.finishDocument end"));
196  }
197  }
198 
199  public bool FreeRAM()
200  {
201  return false;
202  }
203 
204  internal void Free(PerDoc perDoc)
205  {
206  lock (this)
207  {
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.FilePointer);
212  docFreeList[freeCount++] = perDoc;
213  }
214  }
215 
216  internal class PerDoc:DocumentsWriter.DocWriter
217  {
218  public PerDoc(StoredFieldsWriter enclosingInstance)
219  {
220  InitBlock(enclosingInstance);
221  }
222  private void InitBlock(StoredFieldsWriter enclosingInstance)
223  {
224  this.enclosingInstance = enclosingInstance;
225  buffer = enclosingInstance.docWriter.NewPerDocBuffer();
226  fdt = new RAMOutputStream(buffer);
227  }
228  private StoredFieldsWriter enclosingInstance;
229  public StoredFieldsWriter Enclosing_Instance
230  {
231  get
232  {
233  return enclosingInstance;
234  }
235 
236  }
237 
238  internal DocumentsWriter.PerDocBuffer buffer ;
239  internal RAMOutputStream fdt;
240  internal int numStoredFields;
241 
242  internal void Reset()
243  {
244  fdt.Reset();
245  buffer.Recycle();
246  numStoredFields = 0;
247  }
248 
249  public override void Abort()
250  {
251  Reset();
252  Enclosing_Instance.Free(this);
253  }
254 
255  public override long SizeInBytes()
256  {
257  return buffer.SizeInBytes;
258  }
259 
260  public override void Finish()
261  {
262  Enclosing_Instance.FinishDocument(this);
263  }
264  }
265  }
266 }