blob: 4cbb401060c79fd84c890e56a821710d928248ca [file] [log] [blame]
using Lucene.Net.Diagnostics;
using Lucene.Net.Support;
using System;
using System.Runtime.CompilerServices;
namespace Lucene.Net.Index
{
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using ArrayUtil = Lucene.Net.Util.ArrayUtil;
using Codec = Lucene.Net.Codecs.Codec;
using IOContext = Lucene.Net.Store.IOContext;
using IOUtils = Lucene.Net.Util.IOUtils;
using RamUsageEstimator = Lucene.Net.Util.RamUsageEstimator;
using StoredFieldsWriter = Lucene.Net.Codecs.StoredFieldsWriter;
/// <summary>
/// This is a <see cref="StoredFieldsConsumer"/> that writes stored fields. </summary>
internal sealed class StoredFieldsProcessor : StoredFieldsConsumer
{
internal StoredFieldsWriter fieldsWriter;
internal readonly DocumentsWriterPerThread docWriter;
internal int lastDocID;
internal readonly DocumentsWriterPerThread.DocState docState;
internal readonly Codec codec;
public StoredFieldsProcessor(DocumentsWriterPerThread docWriter)
{
this.docWriter = docWriter;
this.docState = docWriter.docState;
this.codec = docWriter.codec;
}
private int numStoredFields;
private IIndexableField[] storedFields = new IIndexableField[1];
private FieldInfo[] fieldInfos = new FieldInfo[1];
public void Reset()
{
numStoredFields = 0;
Arrays.Fill(storedFields, null);
Arrays.Fill(fieldInfos, null);
}
public override void StartDocument()
{
Reset();
}
[MethodImpl(MethodImplOptions.NoInlining)]
public override void Flush(SegmentWriteState state)
{
int numDocs = state.SegmentInfo.DocCount;
if (numDocs > 0)
{
// It's possible that all documents seen in this segment
// hit non-aborting exceptions, in which case we will
// not have yet init'd the FieldsWriter:
InitFieldsWriter(state.Context);
Fill(numDocs);
}
if (fieldsWriter != null)
{
bool success = false;
try
{
fieldsWriter.Finish(state.FieldInfos, numDocs);
success = true;
}
finally
{
if (success)
{
IOUtils.Dispose(fieldsWriter);
}
else
{
IOUtils.DisposeWhileHandlingException(fieldsWriter);
}
}
}
}
private void InitFieldsWriter(IOContext context)
{
lock (this)
{
if (fieldsWriter == null)
{
fieldsWriter = codec.StoredFieldsFormat.FieldsWriter(docWriter.directory, docWriter.SegmentInfo, context);
lastDocID = 0;
}
}
}
[MethodImpl(MethodImplOptions.NoInlining)]
public override void Abort()
{
Reset();
if (fieldsWriter != null)
{
fieldsWriter.Abort();
fieldsWriter = null;
lastDocID = 0;
}
}
/// <summary>
/// Fills in any hole in the docIDs </summary>
internal void Fill(int docID)
{
// We must "catch up" for all docs before us
// that had no stored fields:
while (lastDocID < docID)
{
fieldsWriter.StartDocument(0);
lastDocID++;
fieldsWriter.FinishDocument();
}
}
[MethodImpl(MethodImplOptions.NoInlining)]
internal override void FinishDocument()
{
if (Debugging.AssertsEnabled) Debugging.Assert(docWriter.TestPoint("StoredFieldsWriter.finishDocument start"));
InitFieldsWriter(IOContext.DEFAULT);
Fill(docState.docID);
if (fieldsWriter != null && numStoredFields > 0)
{
fieldsWriter.StartDocument(numStoredFields);
for (int i = 0; i < numStoredFields; i++)
{
fieldsWriter.WriteField(fieldInfos[i], storedFields[i]);
}
fieldsWriter.FinishDocument();
lastDocID++;
}
Reset();
if (Debugging.AssertsEnabled) Debugging.Assert(docWriter.TestPoint("StoredFieldsWriter.finishDocument end"));
}
public override void AddField(int docID, IIndexableField field, FieldInfo fieldInfo)
{
if (field.IndexableFieldType.IsStored)
{
if (numStoredFields == storedFields.Length)
{
int newSize = ArrayUtil.Oversize(numStoredFields + 1, RamUsageEstimator.NUM_BYTES_OBJECT_REF);
IIndexableField[] newArray = new IIndexableField[newSize];
Array.Copy(storedFields, 0, newArray, 0, numStoredFields);
storedFields = newArray;
FieldInfo[] newInfoArray = new FieldInfo[newSize];
Array.Copy(fieldInfos, 0, newInfoArray, 0, numStoredFields);
fieldInfos = newInfoArray;
}
storedFields[numStoredFields] = field;
fieldInfos[numStoredFields] = fieldInfo;
numStoredFields++;
if (Debugging.AssertsEnabled) Debugging.Assert(docState.TestPoint("StoredFieldsWriterPerThread.processFields.writeField"));
}
}
}
}