/*
* Copyright (C) 2014 Indeed Inc.
*
* Licensed 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.
*/
package com.indeed.imhotep.local;
import java.io.IOException;
import java.util.ArrayDeque;
import java.util.List;
import org.apache.log4j.Logger;
import com.indeed.util.core.Pair;
import com.indeed.flamdex.api.TermDocIterator;
public abstract class MergingTermDocIterator implements TermDocIterator {
static final Logger log = Logger.getLogger(MergingTermDocIterator.class);
protected final List<TermDocIterator> iters;
protected final ArrayDeque<Pair<Integer, TermDocIterator>> itersAndOffsetsForTerm;
protected int[] oldToNewDocIdMapping;
protected List<Integer> iterNumToDocOffset;
public MergingTermDocIterator(List<TermDocIterator> tdIters,
int[] mapping,
List<Integer> iterNumToDocOffset) {
this.iters = tdIters;
this.itersAndOffsetsForTerm = new ArrayDeque<Pair<Integer, TermDocIterator>>(iters.size());
this.oldToNewDocIdMapping = mapping;
this.iterNumToDocOffset = iterNumToDocOffset;
}
@Override
public int fillDocIdBuffer(int[] docIdBuffer) {
int len;
int start;
Pair<Integer, TermDocIterator> pair = itersAndOffsetsForTerm.peek();
len = pair.getSecond().fillDocIdBuffer(docIdBuffer);
renumberDocIds(pair.getFirst(), docIdBuffer, 0, len);
start = 0;
while (len + start < docIdBuffer.length) {
/* read all the data from one iterator, try the next */
itersAndOffsetsForTerm.pop();
pair = itersAndOffsetsForTerm.peek();
if (pair == null) {
/* read all the data */
return start + len;
}
/* copy the rest of the data we need into a new buffer */
start += len;
int[] tmpBuf = new int[docIdBuffer.length - start];
len = pair.getSecond().fillDocIdBuffer(tmpBuf);
for (int i = 0; i < len; i++) {
docIdBuffer[i + start] = tmpBuf[i];
}
renumberDocIds(pair.getFirst(), docIdBuffer, start, start + len);
}
return docIdBuffer.length;
}
@Override
public int docFreq() {
return 0;
}
private void renumberDocIds(int offset, int[] docIdBuffer, int start, int end) {
for (int i = start; i < end; ++i) {
final int oldDocId = docIdBuffer[i];
final int newDocId = oldToNewDocIdMapping[oldDocId + offset];
docIdBuffer[i] = newDocId;
}
}
public void close() {
for (TermDocIterator iter : this.iters) {
try {
iter.close();
} catch(IOException e) {
log.error("Could not close TermDocIterator while optimizing index", e);
}
}
}
}