Merge pull request #409 from Alkarex/patch-1
[mono.git] / mcs / tools / monkeydoc / Lucene.Net / Lucene.Net / Index / StoredFieldsWriter.cs
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 = Mono.Lucene.Net.Store.RAMOutputStream;
21 using ArrayUtil = Mono.Lucene.Net.Util.ArrayUtil;
22
23 namespace Mono.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.GetDocStoreOffset());
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.GetDocStoreSegment();
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.GetDocStoreOffset());
101                                 }
102                                 
103                                 if (fieldsWriter != null)
104                                 {
105                                         fieldsWriter.Close();
106                                         fieldsWriter = null;
107                                         lastDocID = 0;
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);
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.Close();
156                                         }
157                                         catch (System.Exception t)
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.GetDocStoreOffset();
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.GetFilePointer());
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.GetSizeInBytes();
258                         }
259                         
260                         public override void  Finish()
261                         {
262                                 Enclosing_Instance.FinishDocument(this);
263                         }
264                 }
265         }
266 }