/* * 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; } }