package com.browseengine.bobo.util; import java.io.Serializable; import java.util.Arrays; import org.apache.lucene.search.DocIdSetIterator; import org.apache.lucene.util.OpenBitSet; /** * @author jko * * BigSegmentedArray that creates segments only when the corresponding index is * being accessed. */ public class LazyBigIntArray extends BigSegmentedArray implements Serializable { private static final long serialVersionUID = 1L; private int[][] _array; /* Remember that 2^SHIFT_SIZE = BLOCK_SIZE */ final private static int BLOCK_SIZE = 1024; final private static int SHIFT_SIZE = 10; final private static int MASK = BLOCK_SIZE - 1; private int _fillValue = 0; public LazyBigIntArray(int size) { super(size); // initialize empty blocks _array = new int[_numrows][]; } /* * (non-Javadoc) * @see com.browseengine.bobo.util.BigSegmentedArray#getBlockSize() */ @Override int getBlockSize() { return BLOCK_SIZE; } /* * (non-Javadoc) * @see com.browseengine.bobo.util.BigSegmentedArray#getShiftSize() */ @Override int getShiftSize() { return SHIFT_SIZE; } /* * (non-Javadoc) * @see com.browseengine.bobo.util.BigSegmentedArray#get(int) */ @Override public int get(int id) { int i = id >> SHIFT_SIZE; if (_array[i] == null) return _fillValue; // return _fillValue to mimic int[] behavior else return _array[i][id & MASK]; } /* * (non-Javadoc) * @see com.browseengine.bobo.util.BigSegmentedArray#add(int, int) */ @Override public void add(int id, int val) { int i = id >> SHIFT_SIZE; if (_array[i] == null) { _array[i] = new int[BLOCK_SIZE]; if (_fillValue != 0) Arrays.fill(_array[i], _fillValue); } _array[i][id & MASK] = val; } /* * (non-Javadoc) * @see com.browseengine.bobo.util.BigSegmentedArray#fill(int) */ @Override public void fill(int val) { for (int[] block : _array) { if (block == null) continue; Arrays.fill(block, val); } _fillValue = val; } /* * (non-Javadoc) * @see com.browseengine.bobo.util.BigSegmentedArray#ensureCapacity(int) */ @Override public void ensureCapacity(int size) { int newNumrows = (size >> SHIFT_SIZE) + 1; if (newNumrows > _array.length) { int[][] newArray = new int[newNumrows][]; // grow System.arraycopy(_array, 0, newArray, 0, _array.length); // don't allocate new rows _array = newArray; } _numrows = newNumrows; } /* * (non-Javadoc) * @see com.browseengine.bobo.util.BigSegmentedArray#maxValue() */ @Override public int maxValue() { return Integer.MAX_VALUE; } /* * (non-Javadoc) * @see com.browseengine.bobo.util.BigSegmentedArray#findValue(int, int, int) */ @Override public int findValue(int val, int id, int maxId) { while (id <= maxId) { int i = id >> SHIFT_SIZE; if (_array[i] == null) { if (val == _fillValue) return id; else id = (i + 1) << SHIFT_SIZE; // jump to next segment } else { if (_array[i][id & MASK] == val) return id; else id++; } } return DocIdSetIterator.NO_MORE_DOCS; } /* * (non-Javadoc) * @see com.browseengine.bobo.util.BigSegmentedArray#findValues(org.apache.lucene.util.OpenBitSet, * int, int) */ @Override public int findValues(OpenBitSet bitset, int id, int maxId) { while (id <= maxId) { int i = id >> SHIFT_SIZE; if (_array[i] == null) { if (bitset.fastGet(_fillValue)) return id; else id = (i + 1) << SHIFT_SIZE; // jump to next segment } else { if (bitset.fastGet(_array[i][id & MASK])) return id; else id++; } } return DocIdSetIterator.NO_MORE_DOCS; } /* * (non-Javadoc) * @see com.browseengine.bobo.util.BigSegmentedArray#findValueRange(int, int, int, int) */ @Override public int findValueRange(int minVal, int maxVal, int id, int maxId) { while (id <= maxId) { int i = id >> SHIFT_SIZE; if (_array[i] == null) { if (_fillValue >= minVal && _fillValue <= maxVal) return id; else id = (i + 1) << SHIFT_SIZE; // jump to next segment } else { int val = _array[i][id & MASK]; if (val >= minVal && val <= maxVal) return id; else id++; } } return DocIdSetIterator.NO_MORE_DOCS; } /* * (non-Javadoc) * @see com.browseengine.bobo.util.BigSegmentedArray#findBits(int, int, int) */ @Override public int findBits(int bits, int id, int maxId) { while (id <= maxId) { int i = id >> SHIFT_SIZE; if (_array[i] == null) { if ((_fillValue & bits) != 0) return id; else id = (i + 1) << SHIFT_SIZE; // jump to next segment } else { int val = _array[i][id & MASK]; if ((val & bits) != 0) return id; else id++; } } return DocIdSetIterator.NO_MORE_DOCS; } }