You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by sh...@apache.org on 2013/10/14 23:10:37 UTC
svn commit: r1532099 - in /lucene/dev/branches/branch_4x: ./ lucene/
lucene/CHANGES.txt lucene/core/
lucene/core/src/java/org/apache/lucene/util/OpenBitSet.java
lucene/core/src/test/org/apache/lucene/util/TestOpenBitSet.java
Author: shaie
Date: Mon Oct 14 21:10:36 2013
New Revision: 1532099
URL: http://svn.apache.org/r1532099
Log:
LUCENE-5272: OpenBitSet.ensureCapacity does not modify numBits
Modified:
lucene/dev/branches/branch_4x/ (props changed)
lucene/dev/branches/branch_4x/lucene/ (props changed)
lucene/dev/branches/branch_4x/lucene/CHANGES.txt (contents, props changed)
lucene/dev/branches/branch_4x/lucene/core/ (props changed)
lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/util/OpenBitSet.java
lucene/dev/branches/branch_4x/lucene/core/src/test/org/apache/lucene/util/TestOpenBitSet.java
Modified: lucene/dev/branches/branch_4x/lucene/CHANGES.txt
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_4x/lucene/CHANGES.txt?rev=1532099&r1=1532098&r2=1532099&view=diff
==============================================================================
--- lucene/dev/branches/branch_4x/lucene/CHANGES.txt (original)
+++ lucene/dev/branches/branch_4x/lucene/CHANGES.txt Mon Oct 14 21:10:36 2013
@@ -83,6 +83,9 @@ Bug Fixes
* LUCENE-5269: Fix bug in NGramTokenFilter where it would sometimes count
unicode characters incorrectly. (Mike McCandless, Robert Muir)
+* LUCENE-5272: OpenBitSet.ensureCapacity did not modify numBits, causing
+ false assertion errors in fastSet. (Shai Erera)
+
API Changes:
* LUCENE-5222: Add SortField.needsScores(). Previously it was not possible
Modified: lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/util/OpenBitSet.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/util/OpenBitSet.java?rev=1532099&r1=1532098&r2=1532099&view=diff
==============================================================================
--- lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/util/OpenBitSet.java (original)
+++ lucene/dev/branches/branch_4x/lucene/core/src/java/org/apache/lucene/util/OpenBitSet.java Mon Oct 14 21:10:36 2013
@@ -81,32 +81,35 @@ public class OpenBitSet extends DocIdSet
// Used only for assert:
private long numBits;
- /** Constructs an OpenBitSet large enough to hold <code>numBits</code>.
- */
+ /** Constructs an OpenBitSet large enough to hold {@code numBits}. */
public OpenBitSet(long numBits) {
this.numBits = numBits;
bits = new long[bits2words(numBits)];
wlen = bits.length;
}
+ /** Constructor: allocates enough space for 64 bits. */
public OpenBitSet() {
this(64);
}
- /** Constructs an OpenBitSet from an existing long[].
- * <br/>
- * The first 64 bits are in long[0],
- * with bit index 0 at the least significant bit, and bit index 63 at the most significant.
- * Given a bit index,
- * the word containing it is long[index/64], and it is at bit number index%64 within that word.
+ /**
+ * Constructs an OpenBitSet from an existing long[].
* <p>
- * numWords are the number of elements in the array that contain
- * set bits (non-zero longs).
- * numWords should be <= bits.length, and
- * any existing words in the array at position >= numWords should be zero.
- *
+ * The first 64 bits are in long[0], with bit index 0 at the least significant
+ * bit, and bit index 63 at the most significant. Given a bit index, the word
+ * containing it is long[index/64], and it is at bit number index%64 within
+ * that word.
+ * <p>
+ * numWords are the number of elements in the array that contain set bits
+ * (non-zero longs). numWords should be <= bits.length, and any existing
+ * words in the array at position >= numWords should be zero.
+ *
*/
public OpenBitSet(long[] bits, int numWords) {
+ if (numWords > bits.length) {
+ throw new IllegalArgumentException("numWords cannot exceed bits.length");
+ }
this.bits = bits;
this.wlen = numWords;
this.numBits = wlen * 64;
@@ -150,17 +153,9 @@ public class OpenBitSet extends DocIdSet
/** Expert: returns the long[] storing the bits */
public long[] getBits() { return bits; }
- /** Expert: sets a new long[] to use as the bit storage */
- public void setBits(long[] bits) { this.bits = bits; }
-
/** Expert: gets the number of longs in the array that are in use */
public int getNumWords() { return wlen; }
- /** Expert: sets the number of longs in the array that are in use */
- public void setNumWords(int nWords) { this.wlen=nWords; }
-
-
-
/** Returns true or false for the specified bit index. */
@Override
public boolean get(int index) {
@@ -287,7 +282,7 @@ public class OpenBitSet extends DocIdSet
// since endIndex is one past the end, this is index of the last
// word to be changed.
- int endWord = expandingWordNum(endIndex-1);
+ int endWord = expandingWordNum(endIndex-1);
long startmask = -1L << startIndex;
long endmask = -1L >>> -endIndex; // 64-(endIndex&0x3f) is the same as -endIndex due to wrap
@@ -302,19 +297,14 @@ public class OpenBitSet extends DocIdSet
bits[endWord] |= endmask;
}
-
-
protected int expandingWordNum(long index) {
int wordNum = (int)(index >> 6);
- if (wordNum>=wlen) {
- ensureCapacity(index+1);
- wlen = wordNum+1;
+ if (wordNum >= wlen) {
+ ensureCapacity(index + 1);
}
- assert (numBits = Math.max(numBits, index+1)) >= 0;
return wordNum;
}
-
/** clears a bit.
* The index should be less than the OpenBitSet size.
*/
@@ -519,7 +509,7 @@ public class OpenBitSet extends DocIdSet
// since endIndex is one past the end, this is index of the last
// word to be changed.
- int endWord = expandingWordNum(endIndex-1);
+ int endWord = expandingWordNum(endIndex-1);
/*** Grrr, java shifting wraps around so -1L>>>64 == -1
* for that reason, make sure not to use endmask if the bits to flip will
@@ -833,22 +823,22 @@ public class OpenBitSet extends DocIdSet
return false;
}
-
-
- /** Expand the long[] with the size given as a number of words (64 bit longs).
- * getNumWords() is unchanged by this call.
- */
+ /** Expand the long[] with the size given as a number of words (64 bit longs). */
public void ensureCapacityWords(int numWords) {
- if (bits.length < numWords) {
- bits = ArrayUtil.grow(bits, numWords);
- }
+ bits = ArrayUtil.grow(bits, numWords);
+ wlen = numWords;
+ assert (this.numBits = Math.max(this.numBits, numWords << 6)) >= 0;
}
- /** Ensure that the long[] is big enough to hold numBits, expanding it if necessary.
- * getNumWords() is unchanged by this call.
+ /**
+ * Ensure that the long[] is big enough to hold numBits, expanding it if
+ * necessary.
*/
public void ensureCapacity(long numBits) {
ensureCapacityWords(bits2words(numBits));
+ // ensureCapacityWords sets numBits to a multiple of 64, but we want to set
+ // it to exactly what the app asked.
+ assert (this.numBits = Math.max(this.numBits, numBits)) >= 0;
}
/** Lowers numWords, the number of words in use,
@@ -862,10 +852,9 @@ public class OpenBitSet extends DocIdSet
/** returns the number of 64 bit words it would take to hold numBits */
public static int bits2words(long numBits) {
- return (int)(((numBits-1)>>>6)+1);
+ return (int)(((numBits-1)>>>6)+1);
}
-
/** returns true if both sets have the same bits set */
@Override
public boolean equals(Object o) {
Modified: lucene/dev/branches/branch_4x/lucene/core/src/test/org/apache/lucene/util/TestOpenBitSet.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_4x/lucene/core/src/test/org/apache/lucene/util/TestOpenBitSet.java?rev=1532099&r1=1532098&r2=1532099&view=diff
==============================================================================
--- lucene/dev/branches/branch_4x/lucene/core/src/test/org/apache/lucene/util/TestOpenBitSet.java (original)
+++ lucene/dev/branches/branch_4x/lucene/core/src/test/org/apache/lucene/util/TestOpenBitSet.java Mon Oct 14 21:10:36 2013
@@ -331,6 +331,38 @@ public class TestOpenBitSet extends Base
checkPrevSetBitArray(new int[] {0,2});
}
+ public void testEnsureCapacity() {
+ OpenBitSet bits = new OpenBitSet(1);
+ int bit = random().nextInt(100) + 10;
+ bits.ensureCapacity(bit); // make room for more bits
+ bits.fastSet(bit);
+ assertTrue(bits.fastGet(bit));
+ bits.ensureCapacity(bit + 1);
+ bits.fastSet(bit + 1);
+ assertTrue(bits.fastGet(bit + 1));
+ bits.ensureCapacity(3); // should not change numBits nor grow the array
+ bits.fastSet(3);
+ assertTrue(bits.fastGet(3));
+ bits.fastSet(bit-1);
+ assertTrue(bits.fastGet(bit-1));
+
+ // test ensureCapacityWords
+ int numWords = random().nextInt(10) + 2; // make sure we grow the array (at least 128 bits)
+ bits.ensureCapacityWords(numWords);
+ bit = _TestUtil.nextInt(random(), 128, numWords << 6); // pick a higher bit than 128, but still within range
+ bits.fastSet(bit);
+ assertTrue(bits.fastGet(bit));
+ bits.fastClear(bit);
+ assertFalse(bits.fastGet(bit));
+ bits.fastFlip(bit);
+ assertTrue(bits.fastGet(bit));
+ bits.ensureCapacityWords(2); // should not change numBits nor grow the array
+ bits.fastSet(3);
+ assertTrue(bits.fastGet(3));
+ bits.fastSet(bit-1);
+ assertTrue(bits.fastGet(bit-1));
+ }
+
}