mirror of https://github.com/apache/lucene.git
remove dead code
git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/trunk@990803 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
c5256c2445
commit
46f0f8c559
|
@ -1,169 +0,0 @@
|
||||||
package org.apache.lucene.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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
import org.apache.lucene.util.ArrayUtil;
|
|
||||||
import org.apache.lucene.util.RamUsageEstimator;
|
|
||||||
|
|
||||||
/** This is just a "splitter" class: it lets you wrap two
|
|
||||||
* DocFieldConsumer instances as a single consumer. */
|
|
||||||
|
|
||||||
final class DocFieldConsumers extends DocFieldConsumer {
|
|
||||||
final DocFieldConsumer one;
|
|
||||||
final DocFieldConsumer two;
|
|
||||||
|
|
||||||
public DocFieldConsumers(DocFieldConsumer one, DocFieldConsumer two) {
|
|
||||||
this.one = one;
|
|
||||||
this.two = two;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
void setFieldInfos(FieldInfos fieldInfos) {
|
|
||||||
super.setFieldInfos(fieldInfos);
|
|
||||||
one.setFieldInfos(fieldInfos);
|
|
||||||
two.setFieldInfos(fieldInfos);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void flush(Map<DocFieldConsumerPerThread,Collection<DocFieldConsumerPerField>> threadsAndFields, SegmentWriteState state) throws IOException {
|
|
||||||
|
|
||||||
Map<DocFieldConsumerPerThread,Collection<DocFieldConsumerPerField>> oneThreadsAndFields = new HashMap<DocFieldConsumerPerThread,Collection<DocFieldConsumerPerField>>();
|
|
||||||
Map<DocFieldConsumerPerThread,Collection<DocFieldConsumerPerField>> twoThreadsAndFields = new HashMap<DocFieldConsumerPerThread,Collection<DocFieldConsumerPerField>>();
|
|
||||||
|
|
||||||
for (Map.Entry<DocFieldConsumerPerThread,Collection<DocFieldConsumerPerField>> entry : threadsAndFields.entrySet()) {
|
|
||||||
|
|
||||||
final DocFieldConsumersPerThread perThread = (DocFieldConsumersPerThread) entry.getKey();
|
|
||||||
|
|
||||||
final Collection<DocFieldConsumerPerField> fields = entry.getValue();
|
|
||||||
|
|
||||||
Iterator<DocFieldConsumerPerField> fieldsIt = fields.iterator();
|
|
||||||
Collection<DocFieldConsumerPerField> oneFields = new HashSet<DocFieldConsumerPerField>();
|
|
||||||
Collection<DocFieldConsumerPerField> twoFields = new HashSet<DocFieldConsumerPerField>();
|
|
||||||
while(fieldsIt.hasNext()) {
|
|
||||||
DocFieldConsumersPerField perField = (DocFieldConsumersPerField) fieldsIt.next();
|
|
||||||
oneFields.add(perField.one);
|
|
||||||
twoFields.add(perField.two);
|
|
||||||
}
|
|
||||||
|
|
||||||
oneThreadsAndFields.put(perThread.one, oneFields);
|
|
||||||
twoThreadsAndFields.put(perThread.two, twoFields);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
one.flush(oneThreadsAndFields, state);
|
|
||||||
two.flush(twoThreadsAndFields, state);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void closeDocStore(SegmentWriteState state) throws IOException {
|
|
||||||
try {
|
|
||||||
one.closeDocStore(state);
|
|
||||||
} finally {
|
|
||||||
two.closeDocStore(state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void abort() {
|
|
||||||
try {
|
|
||||||
one.abort();
|
|
||||||
} finally {
|
|
||||||
two.abort();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean freeRAM() {
|
|
||||||
boolean any = one.freeRAM();
|
|
||||||
any |= two.freeRAM();
|
|
||||||
return any;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public DocFieldConsumerPerThread addThread(DocFieldProcessorPerThread docFieldProcessorPerThread) throws IOException {
|
|
||||||
return new DocFieldConsumersPerThread(docFieldProcessorPerThread, this, one.addThread(docFieldProcessorPerThread), two.addThread(docFieldProcessorPerThread));
|
|
||||||
}
|
|
||||||
|
|
||||||
PerDoc[] docFreeList = new PerDoc[1];
|
|
||||||
int freeCount;
|
|
||||||
int allocCount;
|
|
||||||
|
|
||||||
synchronized PerDoc getPerDoc() {
|
|
||||||
if (freeCount == 0) {
|
|
||||||
allocCount++;
|
|
||||||
if (allocCount > docFreeList.length) {
|
|
||||||
// Grow our free list up front to make sure we have
|
|
||||||
// enough space to recycle all outstanding PerDoc
|
|
||||||
// instances
|
|
||||||
assert allocCount == 1+docFreeList.length;
|
|
||||||
docFreeList = new PerDoc[ArrayUtil.oversize(allocCount, RamUsageEstimator.NUM_BYTES_OBJECT_REF)];
|
|
||||||
}
|
|
||||||
return new PerDoc();
|
|
||||||
} else
|
|
||||||
return docFreeList[--freeCount];
|
|
||||||
}
|
|
||||||
|
|
||||||
synchronized void freePerDoc(PerDoc perDoc) {
|
|
||||||
assert freeCount < docFreeList.length;
|
|
||||||
docFreeList[freeCount++] = perDoc;
|
|
||||||
}
|
|
||||||
|
|
||||||
class PerDoc extends DocumentsWriter.DocWriter {
|
|
||||||
|
|
||||||
DocumentsWriter.DocWriter writerOne;
|
|
||||||
DocumentsWriter.DocWriter writerTwo;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long sizeInBytes() {
|
|
||||||
return writerOne.sizeInBytes() + writerTwo.sizeInBytes();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void finish() throws IOException {
|
|
||||||
try {
|
|
||||||
try {
|
|
||||||
writerOne.finish();
|
|
||||||
} finally {
|
|
||||||
writerTwo.finish();
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
freePerDoc(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void abort() {
|
|
||||||
try {
|
|
||||||
try {
|
|
||||||
writerOne.abort();
|
|
||||||
} finally {
|
|
||||||
writerTwo.abort();
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
freePerDoc(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,49 +0,0 @@
|
||||||
package org.apache.lucene.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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import org.apache.lucene.document.Fieldable;
|
|
||||||
|
|
||||||
final class DocFieldConsumersPerField extends DocFieldConsumerPerField {
|
|
||||||
|
|
||||||
final DocFieldConsumerPerField one;
|
|
||||||
final DocFieldConsumerPerField two;
|
|
||||||
final DocFieldConsumersPerThread perThread;
|
|
||||||
|
|
||||||
public DocFieldConsumersPerField(DocFieldConsumersPerThread perThread, DocFieldConsumerPerField one, DocFieldConsumerPerField two) {
|
|
||||||
this.perThread = perThread;
|
|
||||||
this.one = one;
|
|
||||||
this.two = two;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void processFields(Fieldable[] fields, int count) throws IOException {
|
|
||||||
one.processFields(fields, count);
|
|
||||||
two.processFields(fields, count);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void abort() {
|
|
||||||
try {
|
|
||||||
one.abort();
|
|
||||||
} finally {
|
|
||||||
two.abort();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,75 +0,0 @@
|
||||||
package org.apache.lucene.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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
final class DocFieldConsumersPerThread extends DocFieldConsumerPerThread {
|
|
||||||
|
|
||||||
final DocFieldConsumerPerThread one;
|
|
||||||
final DocFieldConsumerPerThread two;
|
|
||||||
final DocFieldConsumers parent;
|
|
||||||
final DocumentsWriter.DocState docState;
|
|
||||||
|
|
||||||
public DocFieldConsumersPerThread(DocFieldProcessorPerThread docFieldProcessorPerThread,
|
|
||||||
DocFieldConsumers parent, DocFieldConsumerPerThread one, DocFieldConsumerPerThread two) {
|
|
||||||
this.parent = parent;
|
|
||||||
this.one = one;
|
|
||||||
this.two = two;
|
|
||||||
docState = docFieldProcessorPerThread.docState;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void startDocument() throws IOException {
|
|
||||||
one.startDocument();
|
|
||||||
two.startDocument();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void abort() {
|
|
||||||
try {
|
|
||||||
one.abort();
|
|
||||||
} finally {
|
|
||||||
two.abort();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public DocumentsWriter.DocWriter finishDocument() throws IOException {
|
|
||||||
final DocumentsWriter.DocWriter oneDoc = one.finishDocument();
|
|
||||||
final DocumentsWriter.DocWriter twoDoc = two.finishDocument();
|
|
||||||
if (oneDoc == null)
|
|
||||||
return twoDoc;
|
|
||||||
else if (twoDoc == null)
|
|
||||||
return oneDoc;
|
|
||||||
else {
|
|
||||||
DocFieldConsumers.PerDoc both = parent.getPerDoc();
|
|
||||||
both.docID = docState.docID;
|
|
||||||
assert oneDoc.docID == docState.docID;
|
|
||||||
assert twoDoc.docID == docState.docID;
|
|
||||||
both.writerOne = oneDoc;
|
|
||||||
both.writerTwo = twoDoc;
|
|
||||||
return both;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public DocFieldConsumerPerField addField(FieldInfo fi) {
|
|
||||||
return new DocFieldConsumersPerField(this, one.addField(fi), two.addField(fi));
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,279 +0,0 @@
|
||||||
package org.apache.lucene.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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.Arrays;
|
|
||||||
|
|
||||||
import org.apache.lucene.store.BufferedIndexInput;
|
|
||||||
import org.apache.lucene.store.IndexInput;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This abstract class reads skip lists with multiple levels.
|
|
||||||
*
|
|
||||||
* See {@link MultiLevelSkipListWriter} for the information about the encoding
|
|
||||||
* of the multi level skip lists.
|
|
||||||
*
|
|
||||||
* Subclasses must implement the abstract method {@link #readSkipData(int, IndexInput)}
|
|
||||||
* which defines the actual format of the skip data.
|
|
||||||
*/
|
|
||||||
abstract class MultiLevelSkipListReader {
|
|
||||||
// the maximum number of skip levels possible for this index
|
|
||||||
private int maxNumberOfSkipLevels;
|
|
||||||
|
|
||||||
// number of levels in this skip list
|
|
||||||
private int numberOfSkipLevels;
|
|
||||||
|
|
||||||
// Expert: defines the number of top skip levels to buffer in memory.
|
|
||||||
// Reducing this number results in less memory usage, but possibly
|
|
||||||
// slower performance due to more random I/Os.
|
|
||||||
// Please notice that the space each level occupies is limited by
|
|
||||||
// the skipInterval. The top level can not contain more than
|
|
||||||
// skipLevel entries, the second top level can not contain more
|
|
||||||
// than skipLevel^2 entries and so forth.
|
|
||||||
private int numberOfLevelsToBuffer = 1;
|
|
||||||
|
|
||||||
private int docCount;
|
|
||||||
private boolean haveSkipped;
|
|
||||||
|
|
||||||
private IndexInput[] skipStream; // skipStream for each level
|
|
||||||
private long skipPointer[]; // the start pointer of each skip level
|
|
||||||
private int skipInterval[]; // skipInterval of each level
|
|
||||||
private int[] numSkipped; // number of docs skipped per level
|
|
||||||
|
|
||||||
private int[] skipDoc; // doc id of current skip entry per level
|
|
||||||
private int lastDoc; // doc id of last read skip entry with docId <= target
|
|
||||||
private long[] childPointer; // child pointer of current skip entry per level
|
|
||||||
private long lastChildPointer; // childPointer of last read skip entry with docId <= target
|
|
||||||
|
|
||||||
private boolean inputIsBuffered;
|
|
||||||
|
|
||||||
public MultiLevelSkipListReader(IndexInput skipStream, int maxSkipLevels, int skipInterval) {
|
|
||||||
this.skipStream = new IndexInput[maxSkipLevels];
|
|
||||||
this.skipPointer = new long[maxSkipLevels];
|
|
||||||
this.childPointer = new long[maxSkipLevels];
|
|
||||||
this.numSkipped = new int[maxSkipLevels];
|
|
||||||
this.maxNumberOfSkipLevels = maxSkipLevels;
|
|
||||||
this.skipInterval = new int[maxSkipLevels];
|
|
||||||
this.skipStream [0]= skipStream;
|
|
||||||
this.inputIsBuffered = (skipStream instanceof BufferedIndexInput);
|
|
||||||
this.skipInterval[0] = skipInterval;
|
|
||||||
for (int i = 1; i < maxSkipLevels; i++) {
|
|
||||||
// cache skip intervals
|
|
||||||
this.skipInterval[i] = this.skipInterval[i - 1] * skipInterval;
|
|
||||||
}
|
|
||||||
skipDoc = new int[maxSkipLevels];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** Returns the id of the doc to which the last call of {@link #skipTo(int)}
|
|
||||||
* has skipped. */
|
|
||||||
int getDoc() {
|
|
||||||
return lastDoc;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** Skips entries to the first beyond the current whose document number is
|
|
||||||
* greater than or equal to <i>target</i>. Returns the current doc count.
|
|
||||||
*/
|
|
||||||
int skipTo(int target) throws IOException {
|
|
||||||
if (!haveSkipped) {
|
|
||||||
// first time, load skip levels
|
|
||||||
loadSkipLevels();
|
|
||||||
haveSkipped = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// walk up the levels until highest level is found that has a skip
|
|
||||||
// for this target
|
|
||||||
int level = 0;
|
|
||||||
while (level < numberOfSkipLevels - 1 && target > skipDoc[level + 1]) {
|
|
||||||
level++;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (level >= 0) {
|
|
||||||
if (target > skipDoc[level]) {
|
|
||||||
if (!loadNextSkip(level)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// no more skips on this level, go down one level
|
|
||||||
if (level > 0 && lastChildPointer > skipStream[level - 1].getFilePointer()) {
|
|
||||||
seekChild(level - 1);
|
|
||||||
}
|
|
||||||
level--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return numSkipped[0] - skipInterval[0] - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean loadNextSkip(int level) throws IOException {
|
|
||||||
// we have to skip, the target document is greater than the current
|
|
||||||
// skip list entry
|
|
||||||
setLastSkipData(level);
|
|
||||||
|
|
||||||
numSkipped[level] += skipInterval[level];
|
|
||||||
|
|
||||||
if (numSkipped[level] > docCount) {
|
|
||||||
// this skip list is exhausted
|
|
||||||
skipDoc[level] = Integer.MAX_VALUE;
|
|
||||||
if (numberOfSkipLevels > level) numberOfSkipLevels = level;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// read next skip entry
|
|
||||||
skipDoc[level] += readSkipData(level, skipStream[level]);
|
|
||||||
|
|
||||||
if (level != 0) {
|
|
||||||
// read the child pointer if we are not on the leaf level
|
|
||||||
childPointer[level] = skipStream[level].readVLong() + skipPointer[level - 1];
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Seeks the skip entry on the given level */
|
|
||||||
protected void seekChild(int level) throws IOException {
|
|
||||||
skipStream[level].seek(lastChildPointer);
|
|
||||||
numSkipped[level] = numSkipped[level + 1] - skipInterval[level + 1];
|
|
||||||
skipDoc[level] = lastDoc;
|
|
||||||
if (level > 0) {
|
|
||||||
childPointer[level] = skipStream[level].readVLong() + skipPointer[level - 1];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void close() throws IOException {
|
|
||||||
for (int i = 1; i < skipStream.length; i++) {
|
|
||||||
if (skipStream[i] != null) {
|
|
||||||
skipStream[i].close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** initializes the reader */
|
|
||||||
void init(long skipPointer, int df) {
|
|
||||||
this.skipPointer[0] = skipPointer;
|
|
||||||
this.docCount = df;
|
|
||||||
Arrays.fill(skipDoc, 0);
|
|
||||||
Arrays.fill(numSkipped, 0);
|
|
||||||
Arrays.fill(childPointer, 0);
|
|
||||||
|
|
||||||
haveSkipped = false;
|
|
||||||
for (int i = 1; i < numberOfSkipLevels; i++) {
|
|
||||||
skipStream[i] = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Loads the skip levels */
|
|
||||||
private void loadSkipLevels() throws IOException {
|
|
||||||
numberOfSkipLevels = docCount == 0 ? 0 : (int) Math.floor(Math.log(docCount) / Math.log(skipInterval[0]));
|
|
||||||
if (numberOfSkipLevels > maxNumberOfSkipLevels) {
|
|
||||||
numberOfSkipLevels = maxNumberOfSkipLevels;
|
|
||||||
}
|
|
||||||
|
|
||||||
skipStream[0].seek(skipPointer[0]);
|
|
||||||
|
|
||||||
int toBuffer = numberOfLevelsToBuffer;
|
|
||||||
|
|
||||||
for (int i = numberOfSkipLevels - 1; i > 0; i--) {
|
|
||||||
// the length of the current level
|
|
||||||
long length = skipStream[0].readVLong();
|
|
||||||
|
|
||||||
// the start pointer of the current level
|
|
||||||
skipPointer[i] = skipStream[0].getFilePointer();
|
|
||||||
if (toBuffer > 0) {
|
|
||||||
// buffer this level
|
|
||||||
skipStream[i] = new SkipBuffer(skipStream[0], (int) length);
|
|
||||||
toBuffer--;
|
|
||||||
} else {
|
|
||||||
// clone this stream, it is already at the start of the current level
|
|
||||||
skipStream[i] = (IndexInput) skipStream[0].clone();
|
|
||||||
if (inputIsBuffered && length < BufferedIndexInput.BUFFER_SIZE) {
|
|
||||||
((BufferedIndexInput) skipStream[i]).setBufferSize((int) length);
|
|
||||||
}
|
|
||||||
|
|
||||||
// move base stream beyond the current level
|
|
||||||
skipStream[0].seek(skipStream[0].getFilePointer() + length);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// use base stream for the lowest level
|
|
||||||
skipPointer[0] = skipStream[0].getFilePointer();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Subclasses must implement the actual skip data encoding in this method.
|
|
||||||
*
|
|
||||||
* @param level the level skip data shall be read from
|
|
||||||
* @param skipStream the skip stream to read from
|
|
||||||
*/
|
|
||||||
protected abstract int readSkipData(int level, IndexInput skipStream) throws IOException;
|
|
||||||
|
|
||||||
/** Copies the values of the last read skip entry on this level */
|
|
||||||
protected void setLastSkipData(int level) {
|
|
||||||
lastDoc = skipDoc[level];
|
|
||||||
lastChildPointer = childPointer[level];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** used to buffer the top skip levels */
|
|
||||||
private final static class SkipBuffer extends IndexInput {
|
|
||||||
private byte[] data;
|
|
||||||
private long pointer;
|
|
||||||
private int pos;
|
|
||||||
|
|
||||||
SkipBuffer(IndexInput input, int length) throws IOException {
|
|
||||||
data = new byte[length];
|
|
||||||
pointer = input.getFilePointer();
|
|
||||||
input.readBytes(data, 0, length);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void close() throws IOException {
|
|
||||||
data = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getFilePointer() {
|
|
||||||
return pointer + pos;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long length() {
|
|
||||||
return data.length;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public byte readByte() throws IOException {
|
|
||||||
return data[pos++];
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void readBytes(byte[] b, int offset, int len) throws IOException {
|
|
||||||
System.arraycopy(data, pos, b, offset, len);
|
|
||||||
pos += len;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void seek(long pos) throws IOException {
|
|
||||||
this.pos = (int) (pos - pointer);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,151 +0,0 @@
|
||||||
package org.apache.lucene.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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
import org.apache.lucene.store.IndexOutput;
|
|
||||||
import org.apache.lucene.store.RAMOutputStream;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This abstract class writes skip lists with multiple levels.
|
|
||||||
*
|
|
||||||
* Example for skipInterval = 3:
|
|
||||||
* c (skip level 2)
|
|
||||||
* c c c (skip level 1)
|
|
||||||
* x x x x x x x x x x (skip level 0)
|
|
||||||
* 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 d d d d (posting list)
|
|
||||||
* 3 6 9 12 15 18 21 24 27 30 (df)
|
|
||||||
*
|
|
||||||
* d - document
|
|
||||||
* x - skip data
|
|
||||||
* c - skip data with child pointer
|
|
||||||
*
|
|
||||||
* Skip level i contains every skipInterval-th entry from skip level i-1.
|
|
||||||
* Therefore the number of entries on level i is: floor(df / ((skipInterval ^ (i + 1))).
|
|
||||||
*
|
|
||||||
* Each skip entry on a level i>0 contains a pointer to the corresponding skip entry in list i-1.
|
|
||||||
* This guarantees a logarithmic amount of skips to find the target document.
|
|
||||||
*
|
|
||||||
* While this class takes care of writing the different skip levels,
|
|
||||||
* subclasses must define the actual format of the skip data.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
abstract class MultiLevelSkipListWriter {
|
|
||||||
// number of levels in this skip list
|
|
||||||
private int numberOfSkipLevels;
|
|
||||||
|
|
||||||
// the skip interval in the list with level = 0
|
|
||||||
private int skipInterval;
|
|
||||||
|
|
||||||
// for every skip level a different buffer is used
|
|
||||||
private RAMOutputStream[] skipBuffer;
|
|
||||||
|
|
||||||
protected MultiLevelSkipListWriter(int skipInterval, int maxSkipLevels, int df) {
|
|
||||||
this.skipInterval = skipInterval;
|
|
||||||
|
|
||||||
// calculate the maximum number of skip levels for this document frequency
|
|
||||||
numberOfSkipLevels = df == 0 ? 0 : (int) Math.floor(Math.log(df) / Math.log(skipInterval));
|
|
||||||
|
|
||||||
// make sure it does not exceed maxSkipLevels
|
|
||||||
if (numberOfSkipLevels > maxSkipLevels) {
|
|
||||||
numberOfSkipLevels = maxSkipLevels;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void init() {
|
|
||||||
skipBuffer = new RAMOutputStream[numberOfSkipLevels];
|
|
||||||
for (int i = 0; i < numberOfSkipLevels; i++) {
|
|
||||||
skipBuffer[i] = new RAMOutputStream();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void resetSkip() {
|
|
||||||
// creates new buffers or empties the existing ones
|
|
||||||
if (skipBuffer == null) {
|
|
||||||
init();
|
|
||||||
} else {
|
|
||||||
for (int i = 0; i < skipBuffer.length; i++) {
|
|
||||||
skipBuffer[i].reset();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Subclasses must implement the actual skip data encoding in this method.
|
|
||||||
*
|
|
||||||
* @param level the level skip data shall be writing for
|
|
||||||
* @param skipBuffer the skip buffer to write to
|
|
||||||
*/
|
|
||||||
protected abstract void writeSkipData(int level, IndexOutput skipBuffer) throws IOException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Writes the current skip data to the buffers. The current document frequency determines
|
|
||||||
* the max level is skip data is to be written to.
|
|
||||||
*
|
|
||||||
* @param df the current document frequency
|
|
||||||
* @throws IOException
|
|
||||||
*/
|
|
||||||
void bufferSkip(int df) throws IOException {
|
|
||||||
int numLevels;
|
|
||||||
|
|
||||||
// determine max level
|
|
||||||
for (numLevels = 0; (df % skipInterval) == 0 && numLevels < numberOfSkipLevels; df /= skipInterval) {
|
|
||||||
numLevels++;
|
|
||||||
}
|
|
||||||
|
|
||||||
long childPointer = 0;
|
|
||||||
|
|
||||||
for (int level = 0; level < numLevels; level++) {
|
|
||||||
writeSkipData(level, skipBuffer[level]);
|
|
||||||
|
|
||||||
long newChildPointer = skipBuffer[level].getFilePointer();
|
|
||||||
|
|
||||||
if (level != 0) {
|
|
||||||
// store child pointers for all levels except the lowest
|
|
||||||
skipBuffer[level].writeVLong(childPointer);
|
|
||||||
}
|
|
||||||
|
|
||||||
//remember the childPointer for the next level
|
|
||||||
childPointer = newChildPointer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Writes the buffered skip lists to the given output.
|
|
||||||
*
|
|
||||||
* @param output the IndexOutput the skip lists shall be written to
|
|
||||||
* @return the pointer the skip list starts
|
|
||||||
*/
|
|
||||||
long writeSkip(IndexOutput output) throws IOException {
|
|
||||||
long skipPointer = output.getFilePointer();
|
|
||||||
if (skipBuffer == null || skipBuffer.length == 0) return skipPointer;
|
|
||||||
|
|
||||||
for (int level = numberOfSkipLevels - 1; level > 0; level--) {
|
|
||||||
long length = skipBuffer[level].getFilePointer();
|
|
||||||
if (length > 0) {
|
|
||||||
output.writeVLong(length);
|
|
||||||
skipBuffer[level].writeTo(output);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
skipBuffer[0].writeTo(output);
|
|
||||||
|
|
||||||
return skipPointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
Loading…
Reference in New Issue