package org.apache.lucene.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. */ import java.io.IOException; import java.util.Arrays; import org.apache.lucene.store.IndexOutput; import org.apache.lucene.codecs.MultiLevelSkipListWriter; /** * Write skip lists with multiple levels, and support skip within block ints. * * 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) * * 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). * * 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. * */ final class Lucene41SkipWriter extends MultiLevelSkipListWriter { // private boolean DEBUG = Lucene41PostingsReader.DEBUG; private int[] lastSkipDoc; private long[] lastSkipDocPointer; private long[] lastSkipPosPointer; private long[] lastSkipPayPointer; private int[] lastPayloadByteUpto; private final IndexOutput docOut; private final IndexOutput posOut; private final IndexOutput payOut; private int curDoc; private long curDocPointer; private long curPosPointer; private long curPayPointer; private int curPosBufferUpto; private int curPayloadByteUpto; private boolean fieldHasPositions; private boolean fieldHasOffsets; private boolean fieldHasPayloads; public Lucene41SkipWriter(int maxSkipLevels, int blockSize, int docCount, IndexOutput docOut, IndexOutput posOut, IndexOutput payOut) { super(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]; } } public void setField(boolean fieldHasPositions, boolean fieldHasOffsets, boolean fieldHasPayloads) { this.fieldHasPositions = fieldHasPositions; this.fieldHasOffsets = fieldHasOffsets; this.fieldHasPayloads = fieldHasPayloads; } @Override public void resetSkip() { super.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()); } } } /** * Sets the values for the current skip data. */ public void bufferSkip(int doc, int numDocs, long posFP, long payFP, int posBufferUpto, int payloadByteUpto) throws IOException { this.curDoc = doc; this.curDocPointer = docOut.getFilePointer(); this.curPosPointer = posFP; this.curPayPointer = payFP; this.curPosBufferUpto = posBufferUpto; this.curPayloadByteUpto = payloadByteUpto; bufferSkip(numDocs); } @Override protected void writeSkipData(int level, IndexOutput skipBuffer) throws IOException { int delta = curDoc - lastSkipDoc[level]; // if (DEBUG) { // System.out.println("writeSkipData level=" + level + " lastDoc=" + curDoc + " delta=" + delta + " curDocPointer=" + curDocPointer); // } skipBuffer.writeVInt(delta); lastSkipDoc[level] = curDoc; skipBuffer.writeVInt((int) (curDocPointer - lastSkipDocPointer[level])); lastSkipDocPointer[level] = curDocPointer; if (fieldHasPositions) { // if (DEBUG) { // System.out.println(" curPosPointer=" + curPosPointer + " curPosBufferUpto=" + curPosBufferUpto); // } skipBuffer.writeVInt((int) (curPosPointer - lastSkipPosPointer[level])); lastSkipPosPointer[level] = curPosPointer; skipBuffer.writeVInt(curPosBufferUpto); if (fieldHasPayloads) { skipBuffer.writeVInt(curPayloadByteUpto); } if (fieldHasOffsets || fieldHasPayloads) { skipBuffer.writeVInt((int) (curPayPointer - lastSkipPayPointer[level])); lastSkipPayPointer[level] = curPayPointer; } } } }