/*
* 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 com.indeed.util.core.threads.ThreadSafeBitSet;
import com.indeed.flamdex.datastruct.FastBitSet;
import com.indeed.imhotep.BitTree;
import com.indeed.imhotep.GroupRemapRule;
final class BitSetGroupLookup extends GroupLookup {
/**
*
*/
private final ImhotepLocalSession session;
private final FastBitSet bitSet;
private final int size;
BitSetGroupLookup(ImhotepLocalSession imhotepLocalSession, final int size) {
this.session = imhotepLocalSession;
this.size = size;
this.bitSet = new FastBitSet(size);
}
@Override
public void nextGroupCallback(int n, long[][] termGrpStats, BitTree groupsSeen) {
int rewriteHead = 0;
// remap groups and filter out useless docids (ones with group = 0), keep track of groups that were found
for (int i = 0; i < n; i++) {
final int docId = session.docIdBuf[i];
if (!bitSet.get(docId)) continue;
session.docGroupBuffer[rewriteHead] = 1;
session.docIdBuf[rewriteHead] = docId;
rewriteHead++;
}
groupsSeen.set(session.docGroupBuffer, rewriteHead);
if (rewriteHead > 0) {
for (int statIndex = 0; statIndex < session.numStats; statIndex++) {
ImhotepLocalSession.updateGroupStatsDocIdBuf(session.statLookup[statIndex], termGrpStats[statIndex], session.docGroupBuffer, session.docIdBuf, session.valBuf, rewriteHead);
}
}
}
@Override
public void applyIntConditionsCallback(int n, ThreadSafeBitSet docRemapped, GroupRemapRule[] remapRules, String intField, long itrTerm) {
for (int i = 0; i < n; i++) {
final int docId = session.docIdBuf[i];
if (docRemapped.get(docId)) continue;
final int group = bitSet.get(docId) ? 1 : 0;
if (remapRules[group] == null) continue;
if (ImhotepLocalSession.checkIntCondition(remapRules[group].condition, intField, itrTerm)) continue;
bitSet.set(docId, remapRules[group].positiveGroup == 1);
docRemapped.set(docId);
}
}
@Override
public void applyStringConditionsCallback(int n, ThreadSafeBitSet docRemapped, GroupRemapRule[] remapRules, String stringField, String itrTerm) {
for (int i = 0; i < n; i++) {
final int docId = session.docIdBuf[i];
if (docRemapped.get(docId)) continue;
final int group = bitSet.get(docId) ? 1 : 0;
if (remapRules[group] == null) continue;
if (ImhotepLocalSession.checkStringCondition(remapRules[group].condition, stringField, itrTerm)) continue;
bitSet.set(docId, remapRules[group].positiveGroup == 1);
docRemapped.set(docId);
}
}
@Override
public int get(int doc) {
return bitSet.get(doc) ? 1 : 0;
}
@Override
public void set(int doc, int group) {
bitSet.set(doc, group == 1);
}
@Override
public void batchSet(int[] docIdBuf, int[] docGrpBuffer, int n) {
for (int i = 0; i < n; ++i) {
bitSet.set(docIdBuf[i], docGrpBuffer[i] == 1);
}
}
@Override
public void fill(int group) {
if (group == 0) {
bitSet.clearAll();
} else if (group == 1) {
bitSet.setAll();
} else {
throw new IllegalArgumentException("max allowed group is 1, was passed in "+group);
}
}
@Override
public void copyInto(GroupLookup other) {
if (size != other.size()) {
throw new IllegalArgumentException("size does not match other.size: size="+size+", other.size="+other.size());
}
for (int i = 0; i < other.size(); ++i) {
other.set(i, bitSet.get(i) ? 1 : 0);
}
other.numGroups = this.numGroups;
}
@Override
public int size() {
return size;
}
@Override
public int maxGroup() {
return 1;
}
@Override
public long memoryUsed() {
return bitSet.memoryUsage();
}
@Override
public void fillDocGrpBuffer(int[] docIdBuf, int[] docGrpBuffer, int n) {
for (int i = 0; i < n; ++i) {
docGrpBuffer[i] = bitSet.get(docIdBuf[i]) ? 1 : 0;
}
}
@Override
public void fillDocGrpBufferSequential(final int start, final int[] docGrpBuffer, final int n) {
for (int i = 0; i < n; i++) {
docGrpBuffer[i] = bitSet.get(start+i) ? 1 : 0;
}
}
@Override
public void bitSetRegroup(FastBitSet bitSet, int targetGroup, int negativeGroup, int positiveGroup) {
// assuming targetGroup == 1 since nothing else would make sense
if (negativeGroup == 0 && positiveGroup == 1) {
this.bitSet.and(bitSet);
} else {
for (int doc = 0; doc < this.bitSet.size(); ++doc) {
if (this.bitSet.get(doc)) {
this.bitSet.set(doc, bitSet.get(doc) ? positiveGroup == 1 : negativeGroup == 1);
}
}
}
}
@Override
protected void recalculateNumGroups() {
for (int i = 0; i < bitSet.size(); ++i) {
if (bitSet.get(i)) {
this.numGroups = 2;
return;
}
}
this.numGroups = 1;
return;
}
public static long calcMemUsageForSize(int sz) {
return 8L * ((sz + 64) >> 6);
}
@Override
public ImhotepLocalSession getSession() {
return this.session;
}
}