/* * 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 System; using IndexOutput = Lucene.Net.Store.IndexOutput; using UnicodeUtil = Lucene.Net.Util.UnicodeUtil; namespace Lucene.Net.Index { /// Consumes doc and freq, writing them using the current /// index file format /// sealed class FormatPostingsDocsWriter : FormatPostingsDocsConsumer, IDisposable { internal IndexOutput out_Renamed; internal FormatPostingsTermsWriter parent; internal FormatPostingsPositionsWriter posWriter; internal DefaultSkipListWriter skipListWriter; internal int skipInterval; internal int totalNumDocs; internal bool omitTermFreqAndPositions; internal bool storePayloads; internal long freqStart; internal FieldInfo fieldInfo; internal FormatPostingsDocsWriter(SegmentWriteState state, FormatPostingsTermsWriter parent):base() { this.parent = parent; System.String fileName = IndexFileNames.SegmentFileName(parent.parent.segment, IndexFileNames.FREQ_EXTENSION); state.flushedFiles.Add(fileName); out_Renamed = parent.parent.dir.CreateOutput(fileName); totalNumDocs = parent.parent.totalNumDocs; // TODO: abstraction violation skipInterval = parent.parent.termsOut.skipInterval; skipListWriter = parent.parent.skipListWriter; skipListWriter.SetFreqOutput(out_Renamed); posWriter = new FormatPostingsPositionsWriter(state, this); } internal void SetField(FieldInfo fieldInfo) { this.fieldInfo = fieldInfo; omitTermFreqAndPositions = fieldInfo.omitTermFreqAndPositions; storePayloads = fieldInfo.storePayloads; posWriter.SetField(fieldInfo); } internal int lastDocID; internal int df; /// Adds a new doc in this term. If this returns null /// then we just skip consuming positions/payloads. /// internal override FormatPostingsPositionsConsumer AddDoc(int docID, int termDocFreq) { int delta = docID - lastDocID; if (docID < 0 || (df > 0 && delta <= 0)) throw new CorruptIndexException("docs out of order (" + docID + " <= " + lastDocID + " )"); if ((++df % skipInterval) == 0) { // TODO: abstraction violation skipListWriter.SetSkipData(lastDocID, storePayloads, posWriter.lastPayloadLength); skipListWriter.BufferSkip(df); } System.Diagnostics.Debug.Assert(docID < totalNumDocs, "docID=" + docID + " totalNumDocs=" + totalNumDocs); lastDocID = docID; if (omitTermFreqAndPositions) out_Renamed.WriteVInt(delta); else if (1 == termDocFreq) out_Renamed.WriteVInt((delta << 1) | 1); else { out_Renamed.WriteVInt(delta << 1); out_Renamed.WriteVInt(termDocFreq); } return posWriter; } private TermInfo termInfo = new TermInfo(); // minimize consing internal UnicodeUtil.UTF8Result utf8 = new UnicodeUtil.UTF8Result(); /// Called when we are done adding docs to this term internal override void Finish() { long skipPointer = skipListWriter.WriteSkip(out_Renamed); // TODO: this is abstraction violation -- we should not // peek up into parents terms encoding format termInfo.Set(df, parent.freqStart, parent.proxStart, (int) (skipPointer - parent.freqStart)); // TODO: we could do this incrementally UnicodeUtil.UTF16toUTF8(parent.currentTerm, parent.currentTermStart, utf8); if (df > 0) { parent.termsOut.Add(fieldInfo.number, utf8.result, utf8.length, termInfo); } lastDocID = 0; df = 0; } public void Dispose() { // Move to protected method if class becomes unsealed out_Renamed.Dispose(); posWriter.Dispose(); } } }