/* * 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.flamdex.search; import com.indeed.flamdex.api.DocIdStream; import com.indeed.flamdex.api.FlamdexOutOfMemoryException; import com.indeed.flamdex.api.FlamdexReader; import com.indeed.flamdex.api.IntTermIterator; import com.indeed.flamdex.datastruct.FastBitSet; import com.indeed.flamdex.datastruct.FastBitSetPooler; import java.util.Arrays; /** * @author jwolfe */ public class IntTermSetQueryEvaluator implements QueryEvaluator { private static final int BUFFER_SIZE = 64; private final String field; private final long[] terms; public IntTermSetQueryEvaluator(String field, long[] terms) { this.field = field; this.terms = new long[terms.length]; System.arraycopy(terms, 0, this.terms, 0, terms.length); Arrays.sort(this.terms); } @Override public void and(FlamdexReader r, FastBitSet bitSet, FastBitSetPooler bitSetPooler) throws FlamdexOutOfMemoryException { FastBitSet localBitSet = bitSetPooler.create(r.getNumDocs()); try { internalSearch(r, localBitSet); bitSet.and(localBitSet); } finally { final long memUsage = localBitSet.memoryUsage(); localBitSet = null; bitSetPooler.release(memUsage); } } @Override public void or(FlamdexReader r, FastBitSet bitSet, FastBitSetPooler bitSetPooler) throws FlamdexOutOfMemoryException { internalSearch(r, bitSet); } @Override public void not(FlamdexReader r, FastBitSet bitSet, FastBitSetPooler bitSetPooler) throws FlamdexOutOfMemoryException { bitSet.clearAll(); internalSearch(r, bitSet); bitSet.invertAll(); } private void internalSearch(FlamdexReader r, FastBitSet bitSet) { final IntTermIterator iterator = r.getIntTermIterator(field); int ix = 0; try { final DocIdStream docIdStream = r.getDocIdStream(); try { while (ix < terms.length) { final int[] docIdBuffer = new int[BUFFER_SIZE]; iterator.reset(terms[ix++]); if (!iterator.next()) break; if(iterator.term() != terms[ix-1]) continue; docIdStream.reset(iterator); readDocIdStream(docIdStream, docIdBuffer, bitSet); } } finally { docIdStream.close(); } } finally { iterator.close(); } } private void readDocIdStream(DocIdStream docIdStream, int[] docIdBuffer, FastBitSet bitSet) { while (true) { final int n = docIdStream.fillDocIdBuffer(docIdBuffer); for (int i = 0; i < n; ++i) { bitSet.set(docIdBuffer[i]); } if (n < docIdBuffer.length) break; } } }