blob: 2febb8b333c70d47a324f41ea59d850d86a9c2a0 [file] [log] [blame]
using Lucene.Net.Support;
using System.Runtime.CompilerServices;
namespace Lucene.Net.Codecs.Lucene41
{
/*
* 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 IndexOutput = Lucene.Net.Store.IndexOutput;
/// <summary>
/// Write skip lists with multiple levels, and support skip within block ints.
/// <para/>
/// Assume that docFreq = 28, skipInterval = blockSize = 12
///
/// | block#0 | | block#1 | |vInts|
/// d d d d d d d d d d d d d d d d d d d d d d d d d d d d (posting list)
/// ^ ^ (level 0 skip point)
/// <para/>
/// Note that skipWriter will ignore first document in block#0, since
/// it is useless as a skip point. Also, we'll never skip into the vInts
/// block, only record skip data at the start its start point(if it exist).
/// <para/>
/// For each skip point, we will record:
/// 1. docID in former position, i.e. for position 12, record docID[11], etc.
/// 2. its related file points(position, payload),
/// 3. related numbers or uptos(position, payload).
/// 4. start offset.
/// </summary>
internal sealed class Lucene41SkipWriter : MultiLevelSkipListWriter
{
// private boolean DEBUG = Lucene41PostingsReader.DEBUG;
private readonly int[] lastSkipDoc; // LUCENENET: marked readonly
private readonly long[] lastSkipDocPointer; // LUCENENET: marked readonly
private readonly long[] lastSkipPosPointer; // LUCENENET: marked readonly
private readonly long[] lastSkipPayPointer; // LUCENENET: marked readonly
private readonly int[] lastPayloadByteUpto; // LUCENENET: marked readonly
private readonly IndexOutput docOut;
private readonly IndexOutput posOut;
private readonly IndexOutput payOut;
private int curDoc;
private long curDocPointer;
private long curPosPointer;
private long curPayPointer;
private int curPosBufferUpto;
private int curPayloadByteUpto;
private bool fieldHasPositions;
private bool fieldHasOffsets;
private bool fieldHasPayloads;
public Lucene41SkipWriter(int maxSkipLevels, int blockSize, int docCount, IndexOutput docOut, IndexOutput posOut, IndexOutput payOut)
: base(blockSize, 8, maxSkipLevels, docCount)
{
this.docOut = docOut;
this.posOut = posOut;
this.payOut = payOut;
lastSkipDoc = new int[maxSkipLevels];
lastSkipDocPointer = new long[maxSkipLevels];
if (posOut != null)
{
lastSkipPosPointer = new long[maxSkipLevels];
if (payOut != null)
{
lastSkipPayPointer = new long[maxSkipLevels];
}
lastPayloadByteUpto = new int[maxSkipLevels];
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void SetField(bool fieldHasPositions, bool fieldHasOffsets, bool fieldHasPayloads)
{
this.fieldHasPositions = fieldHasPositions;
this.fieldHasOffsets = fieldHasOffsets;
this.fieldHasPayloads = fieldHasPayloads;
}
public override void ResetSkip()
{
base.ResetSkip();
Arrays.Fill(lastSkipDoc, 0);
Arrays.Fill(lastSkipDocPointer, docOut.GetFilePointer());
if (fieldHasPositions)
{
Arrays.Fill(lastSkipPosPointer, posOut.GetFilePointer());
if (fieldHasPayloads)
{
Arrays.Fill(lastPayloadByteUpto, 0);
}
if (fieldHasOffsets || fieldHasPayloads)
{
Arrays.Fill(lastSkipPayPointer, payOut.GetFilePointer());
}
}
}
/// <summary>
/// Sets the values for the current skip data.
/// </summary>
public void BufferSkip(int doc, int numDocs, long posFP, long payFP, int posBufferUpto, int payloadByteUpto)
{
this.curDoc = doc;
this.curDocPointer = docOut.GetFilePointer();
this.curPosPointer = posFP;
this.curPayPointer = payFP;
this.curPosBufferUpto = posBufferUpto;
this.curPayloadByteUpto = payloadByteUpto;
BufferSkip(numDocs);
}
protected override void WriteSkipData(int level, IndexOutput skipBuffer)
{
int delta = curDoc - lastSkipDoc[level];
// if (DEBUG) {
// System.out.println("writeSkipData level=" + level + " lastDoc=" + curDoc + " delta=" + delta + " curDocPointer=" + curDocPointer);
// }
skipBuffer.WriteVInt32(delta);
lastSkipDoc[level] = curDoc;
skipBuffer.WriteVInt32((int)(curDocPointer - lastSkipDocPointer[level]));
lastSkipDocPointer[level] = curDocPointer;
if (fieldHasPositions)
{
// if (DEBUG) {
// System.out.println(" curPosPointer=" + curPosPointer + " curPosBufferUpto=" + curPosBufferUpto);
// }
skipBuffer.WriteVInt32((int)(curPosPointer - lastSkipPosPointer[level]));
lastSkipPosPointer[level] = curPosPointer;
skipBuffer.WriteVInt32(curPosBufferUpto);
if (fieldHasPayloads)
{
skipBuffer.WriteVInt32(curPayloadByteUpto);
}
if (fieldHasOffsets || fieldHasPayloads)
{
skipBuffer.WriteVInt32((int)(curPayPointer - lastSkipPayPointer[level]));
lastSkipPayPointer[level] = curPayPointer;
}
}
}
}
}