blob: b151b323c27a45350f2cfe12297db7a02159e05e [file] [log] [blame]
using Lucene.Net.Diagnostics;
using Lucene.Net.Index;
using Lucene.Net.Store;
using Lucene.Net.Util;
using System;
using System.Collections.Generic;
namespace Lucene.Net.Codecs.Lucene3x
{
/*
* 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.
*/
#pragma warning disable 612, 618
internal class PreFlexRWFieldsWriter : FieldsConsumer
{
#pragma warning disable CA2213 // Disposable fields should be disposed
private readonly TermInfosWriter termsOut;
private readonly IndexOutput freqOut;
private readonly IndexOutput proxOut;
#pragma warning restore CA2213 // Disposable fields should be disposed
private readonly PreFlexRWSkipListWriter skipListWriter;
private readonly int totalNumDocs;
public PreFlexRWFieldsWriter(SegmentWriteState state)
{
termsOut = new TermInfosWriter(state.Directory, state.SegmentInfo.Name, state.FieldInfos, state.TermIndexInterval);
bool success = false;
try
{
string freqFile = IndexFileNames.SegmentFileName(state.SegmentInfo.Name, "", Lucene3xPostingsFormat.FREQ_EXTENSION);
freqOut = state.Directory.CreateOutput(freqFile, state.Context);
totalNumDocs = state.SegmentInfo.DocCount;
success = true;
}
finally
{
if (!success)
{
IOUtils.DisposeWhileHandlingException(termsOut);
}
}
success = false;
try
{
if (state.FieldInfos.HasProx)
{
string proxFile = IndexFileNames.SegmentFileName(state.SegmentInfo.Name, "", Lucene3xPostingsFormat.PROX_EXTENSION);
proxOut = state.Directory.CreateOutput(proxFile, state.Context);
}
else
{
proxOut = null;
}
success = true;
}
finally
{
if (!success)
{
IOUtils.DisposeWhileHandlingException(termsOut, freqOut);
}
}
skipListWriter = new PreFlexRWSkipListWriter(termsOut.skipInterval, termsOut.maxSkipLevels, totalNumDocs, freqOut, proxOut);
//System.out.println("\nw start seg=" + segment);
}
public override TermsConsumer AddField(FieldInfo field)
{
if (Debugging.AssertsEnabled) Debugging.Assert(field.Number != -1);
// LUCENENET specific - to avoid boxing, changed from CompareTo() to IndexOptionsComparer.Compare()
if (IndexOptionsComparer.Default.Compare(field.IndexOptions, IndexOptions.DOCS_AND_FREQS_AND_POSITIONS_AND_OFFSETS) >= 0)
{
throw new NotSupportedException("this codec cannot index offsets");
}
//System.out.println("w field=" + field.Name + " storePayload=" + field.storePayloads + " number=" + field.number);
return new PreFlexTermsWriter(this, field);
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
IOUtils.Dispose(termsOut, freqOut, proxOut);
}
}
private class PreFlexTermsWriter : TermsConsumer
{
private readonly PreFlexRWFieldsWriter outerInstance;
private readonly FieldInfo fieldInfo;
private readonly bool omitTF;
private readonly bool storePayloads;
private readonly TermInfo termInfo = new TermInfo();
private readonly PostingsWriter postingsWriter; // LUCENENET: marked readonly
public PreFlexTermsWriter(PreFlexRWFieldsWriter outerInstance, FieldInfo fieldInfo)
{
this.outerInstance = outerInstance;
postingsWriter = new PostingsWriter(this);
this.fieldInfo = fieldInfo;
omitTF = fieldInfo.IndexOptions == IndexOptions.DOCS_ONLY;
storePayloads = fieldInfo.HasPayloads;
}
internal class PostingsWriter : PostingsConsumer
{
private readonly PreFlexRWFieldsWriter.PreFlexTermsWriter outerInstance;
public PostingsWriter(PreFlexRWFieldsWriter.PreFlexTermsWriter outerInstance)
{
this.outerInstance = outerInstance;
}
private int lastDocID;
private int lastPayloadLength = -1;
private int lastPosition;
private int df;
public PostingsWriter Reset()
{
df = 0;
lastDocID = 0;
lastPayloadLength = -1;
return this;
}
public override void StartDoc(int docID, int termDocFreq)
{
//System.out.println(" w doc=" + docID);
int delta = docID - lastDocID;
if (docID < 0 || (df > 0 && delta <= 0))
{
throw new CorruptIndexException("docs out of order (" + docID + " <= " + lastDocID + " )");
}
if ((++df % outerInstance.outerInstance.termsOut.skipInterval) == 0)
{
outerInstance.outerInstance.skipListWriter.SetSkipData(lastDocID, outerInstance.storePayloads, lastPayloadLength);
outerInstance.outerInstance.skipListWriter.BufferSkip(df);
}
lastDocID = docID;
if (Debugging.AssertsEnabled) Debugging.Assert(docID < outerInstance.outerInstance.totalNumDocs,"docID={0} totalNumDocs={1}", docID, outerInstance.outerInstance.totalNumDocs);
if (outerInstance.omitTF)
{
outerInstance.outerInstance.freqOut.WriteVInt32(delta);
}
else
{
int code = delta << 1;
if (termDocFreq == 1)
{
outerInstance.outerInstance.freqOut.WriteVInt32(code | 1);
}
else
{
outerInstance.outerInstance.freqOut.WriteVInt32(code);
outerInstance.outerInstance.freqOut.WriteVInt32(termDocFreq);
}
}
lastPosition = 0;
}
public override void AddPosition(int position, BytesRef payload, int startOffset, int endOffset)
{
if (Debugging.AssertsEnabled) Debugging.Assert(outerInstance.outerInstance.proxOut != null);
if (Debugging.AssertsEnabled) Debugging.Assert(startOffset == -1);
if (Debugging.AssertsEnabled) Debugging.Assert(endOffset == -1);
//System.out.println(" w pos=" + position + " payl=" + payload);
int delta = position - lastPosition;
lastPosition = position;
if (outerInstance.storePayloads)
{
int payloadLength = payload == null ? 0 : payload.Length;
if (payloadLength != lastPayloadLength)
{
//System.out.println(" write payload len=" + payloadLength);
lastPayloadLength = payloadLength;
outerInstance.outerInstance.proxOut.WriteVInt32((delta << 1) | 1);
outerInstance.outerInstance.proxOut.WriteVInt32(payloadLength);
}
else
{
outerInstance.outerInstance.proxOut.WriteVInt32(delta << 1);
}
if (payloadLength > 0)
{
outerInstance.outerInstance.proxOut.WriteBytes(payload.Bytes, payload.Offset, payload.Length);
}
}
else
{
outerInstance.outerInstance.proxOut.WriteVInt32(delta);
}
}
public override void FinishDoc()
{
}
}
public override PostingsConsumer StartTerm(BytesRef text)
{
//System.out.println(" w term=" + text.utf8ToString());
outerInstance.skipListWriter.ResetSkip();
termInfo.FreqPointer = outerInstance.freqOut.GetFilePointer();
if (outerInstance.proxOut != null)
{
termInfo.ProxPointer = outerInstance.proxOut.GetFilePointer();
}
return postingsWriter.Reset();
}
public override void FinishTerm(BytesRef text, TermStats stats)
{
if (stats.DocFreq > 0)
{
long skipPointer = outerInstance.skipListWriter.WriteSkip(outerInstance.freqOut);
termInfo.DocFreq = stats.DocFreq;
termInfo.SkipOffset = (int)(skipPointer - termInfo.FreqPointer);
//System.out.println(" w finish term=" + text.utf8ToString() + " fnum=" + fieldInfo.number);
outerInstance.termsOut.Add(fieldInfo.Number, text, termInfo);
}
}
public override void Finish(long sumTotalTermCount, long sumDocFreq, int docCount)
{
}
public override IComparer<BytesRef> Comparer => BytesRef.UTF8SortedAsUTF16Comparer;
}
}
#pragma warning restore 612, 618
}