Skip to content

Commit 8110bbd

Browse files
committed
CountedBitSet doesn't need to extend BitSet. (#28239)
1 parent 82d782b commit 8110bbd

File tree

5 files changed

+13
-49
lines changed

5 files changed

+13
-49
lines changed

server/src/main/java/org/elasticsearch/index/seqno/CountedBitSet.java

Lines changed: 4 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919

2020
package org.elasticsearch.index.seqno;
2121

22-
import org.apache.lucene.util.BitSet;
2322
import org.apache.lucene.util.FixedBitSet;
2423
import org.apache.lucene.util.RamUsageEstimator;
2524

@@ -28,7 +27,7 @@
2827
* when all bits are set to reduce memory usage. This structure can work well for sequence numbers as
2928
* these numbers are likely to form contiguous ranges (eg. filling all bits).
3029
*/
31-
public final class CountedBitSet extends BitSet {
30+
public final class CountedBitSet {
3231
static final long BASE_RAM_BYTES_USED = RamUsageEstimator.shallowSizeOfInstance(CountedBitSet.class);
3332
private short onBits; // Number of bits are set.
3433
private FixedBitSet bitset;
@@ -41,14 +40,12 @@ public CountedBitSet(short numBits) {
4140
this.bitset = new FixedBitSet(numBits);
4241
}
4342

44-
@Override
4543
public boolean get(int index) {
4644
assert 0 <= index && index < this.length();
4745
assert bitset == null || onBits < bitset.length() : "Bitset should be released when all bits are set";
4846
return bitset == null ? true : bitset.get(index);
4947
}
5048

51-
@Override
5249
public void set(int index) {
5350
assert 0 <= index && index < this.length();
5451
assert bitset == null || onBits < bitset.length() : "Bitset should be released when all bits are set";
@@ -67,41 +64,16 @@ public void set(int index) {
6764
}
6865
}
6966

70-
@Override
71-
public void clear(int startIndex, int endIndex) {
72-
throw new UnsupportedOperationException();
73-
}
74-
75-
@Override
76-
public void clear(int index) {
77-
throw new UnsupportedOperationException();
78-
}
67+
// Below methods are pkg-private for testing
7968

80-
@Override
81-
public int cardinality() {
69+
int cardinality() {
8270
return onBits;
8371
}
8472

85-
@Override
86-
public int length() {
73+
int length() {
8774
return bitset == null ? onBits : bitset.length();
8875
}
8976

90-
@Override
91-
public int prevSetBit(int index) {
92-
throw new UnsupportedOperationException();
93-
}
94-
95-
@Override
96-
public int nextSetBit(int index) {
97-
throw new UnsupportedOperationException();
98-
}
99-
100-
@Override
101-
public long ramBytesUsed() {
102-
return BASE_RAM_BYTES_USED + (bitset == null ? 0 : bitset.ramBytesUsed());
103-
}
104-
10577
boolean isInternalBitsetReleased() {
10678
return bitset == null;
10779
}

server/src/main/java/org/elasticsearch/index/seqno/LocalCheckpointTracker.java

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
package org.elasticsearch.index.seqno;
2121

2222
import com.carrotsearch.hppc.LongObjectHashMap;
23-
import org.apache.lucene.util.BitSet;
2423
import org.elasticsearch.common.SuppressForbidden;
2524

2625
/**
@@ -39,7 +38,7 @@ public class LocalCheckpointTracker {
3938
* A collection of bit sets representing pending sequence numbers. Each sequence number is mapped to a bit set by dividing by the
4039
* bit set size.
4140
*/
42-
final LongObjectHashMap<BitSet> processedSeqNo = new LongObjectHashMap<>();
41+
final LongObjectHashMap<CountedBitSet> processedSeqNo = new LongObjectHashMap<>();
4342

4443
/**
4544
* The current local checkpoint, i.e., all sequence numbers no more than this number have been completed.
@@ -96,7 +95,7 @@ public synchronized void markSeqNoAsCompleted(final long seqNo) {
9695
// this is possible during recovery where we might replay an operation that was also replicated
9796
return;
9897
}
99-
final BitSet bitSet = getBitSetForSeqNo(seqNo);
98+
final CountedBitSet bitSet = getBitSetForSeqNo(seqNo);
10099
final int offset = seqNoToBitSetOffset(seqNo);
101100
bitSet.set(offset);
102101
if (seqNo == checkpoint + 1) {
@@ -170,7 +169,7 @@ assert getBitSetForSeqNo(checkpoint + 1).get(seqNoToBitSetOffset(checkpoint + 1)
170169
try {
171170
// keep it simple for now, get the checkpoint one by one; in the future we can optimize and read words
172171
long bitSetKey = getBitSetKey(checkpoint);
173-
BitSet current = processedSeqNo.get(bitSetKey);
172+
CountedBitSet current = processedSeqNo.get(bitSetKey);
174173
if (current == null) {
175174
// the bit set corresponding to the checkpoint has already been removed, set ourselves up for the next bit set
176175
assert checkpoint % BIT_SET_SIZE == BIT_SET_SIZE - 1;
@@ -184,7 +183,7 @@ assert getBitSetForSeqNo(checkpoint + 1).get(seqNoToBitSetOffset(checkpoint + 1)
184183
*/
185184
if (checkpoint == lastSeqNoInBitSet(bitSetKey)) {
186185
assert current != null;
187-
final BitSet removed = processedSeqNo.remove(bitSetKey);
186+
final CountedBitSet removed = processedSeqNo.remove(bitSetKey);
188187
assert removed == current;
189188
current = processedSeqNo.get(++bitSetKey);
190189
}
@@ -210,11 +209,11 @@ private long getBitSetKey(final long seqNo) {
210209
return seqNo / BIT_SET_SIZE;
211210
}
212211

213-
private BitSet getBitSetForSeqNo(final long seqNo) {
212+
private CountedBitSet getBitSetForSeqNo(final long seqNo) {
214213
assert Thread.holdsLock(this);
215214
final long bitSetKey = getBitSetKey(seqNo);
216215
final int index = processedSeqNo.indexOf(bitSetKey);
217-
final BitSet bitSet;
216+
final CountedBitSet bitSet;
218217
if (processedSeqNo.indexExists(index)) {
219218
bitSet = processedSeqNo.indexGet(index);
220219
} else {

server/src/main/java/org/elasticsearch/index/translog/MultiSnapshot.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
package org.elasticsearch.index.translog;
2121

2222
import com.carrotsearch.hppc.LongObjectHashMap;
23-
import org.apache.lucene.util.BitSet;
2423
import org.elasticsearch.index.seqno.CountedBitSet;
2524
import org.elasticsearch.index.seqno.SequenceNumbers;
2625

@@ -85,15 +84,15 @@ public void close() throws IOException {
8584

8685
static final class SeqNoSet {
8786
static final short BIT_SET_SIZE = 1024;
88-
private final LongObjectHashMap<BitSet> bitSets = new LongObjectHashMap<>();
87+
private final LongObjectHashMap<CountedBitSet> bitSets = new LongObjectHashMap<>();
8988

9089
/**
9190
* Marks this sequence number and returns <tt>true</tt> if it is seen before.
9291
*/
9392
boolean getAndSet(long value) {
9493
assert value >= 0;
9594
final long key = value / BIT_SET_SIZE;
96-
BitSet bitset = bitSets.get(key);
95+
CountedBitSet bitset = bitSets.get(key);
9796
if (bitset == null) {
9897
bitset = new CountedBitSet(BIT_SET_SIZE);
9998
bitSets.put(key, bitset);

server/src/test/java/org/elasticsearch/index/seqno/CountedBitSetTests.java

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,7 @@
2626
import java.util.stream.Collectors;
2727
import java.util.stream.IntStream;
2828

29-
import static org.hamcrest.Matchers.allOf;
3029
import static org.hamcrest.Matchers.equalTo;
31-
import static org.hamcrest.Matchers.lessThan;
3230

3331
public class CountedBitSetTests extends ESTestCase {
3432

@@ -55,7 +53,6 @@ public void testReleaseInternalBitSet() {
5553
int numBits = (short) randomIntBetween(8, 4096);
5654
final CountedBitSet countedBitSet = new CountedBitSet((short) numBits);
5755
final List<Integer> values = IntStream.range(0, numBits).boxed().collect(Collectors.toList());
58-
final long ramBytesUsedWithBitSet = countedBitSet.ramBytesUsed();
5956

6057
for (int i = 1; i < numBits; i++) {
6158
final int value = values.get(i);
@@ -68,7 +65,6 @@ public void testReleaseInternalBitSet() {
6865
assertThat(countedBitSet.isInternalBitsetReleased(), equalTo(false));
6966
assertThat(countedBitSet.length(), equalTo(numBits));
7067
assertThat(countedBitSet.cardinality(), equalTo(i));
71-
assertThat(countedBitSet.ramBytesUsed(), equalTo(ramBytesUsedWithBitSet));
7268
}
7369

7470
// The missing piece to fill all bits.
@@ -83,7 +79,6 @@ public void testReleaseInternalBitSet() {
8379
assertThat(countedBitSet.isInternalBitsetReleased(), equalTo(true));
8480
assertThat(countedBitSet.length(), equalTo(numBits));
8581
assertThat(countedBitSet.cardinality(), equalTo(numBits));
86-
assertThat(countedBitSet.ramBytesUsed(), allOf(equalTo(CountedBitSet.BASE_RAM_BYTES_USED), lessThan(ramBytesUsedWithBitSet)));
8782
}
8883

8984
// Tests with released internal bitset.

server/src/test/java/org/elasticsearch/index/seqno/LocalCheckpointTrackerTests.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
package org.elasticsearch.index.seqno;
2121

2222
import com.carrotsearch.hppc.LongObjectHashMap;
23-
import org.apache.lucene.util.BitSet;
2423
import org.elasticsearch.ElasticsearchException;
2524
import org.elasticsearch.common.Randomness;
2625
import org.elasticsearch.common.util.concurrent.AbstractRunnable;
@@ -260,7 +259,7 @@ public void testResetCheckpoint() {
260259
tracker.resetCheckpoint(localCheckpoint);
261260
assertThat(tracker.getCheckpoint(), equalTo((long) localCheckpoint));
262261
assertThat(tracker.getMaxSeqNo(), equalTo((long) maxSeqNo));
263-
assertThat(tracker.processedSeqNo, new BaseMatcher<LongObjectHashMap<BitSet>>() {
262+
assertThat(tracker.processedSeqNo, new BaseMatcher<LongObjectHashMap<CountedBitSet>>() {
264263
@Override
265264
public boolean matches(Object item) {
266265
return (item instanceof LongObjectHashMap && ((LongObjectHashMap) item).isEmpty());

0 commit comments

Comments
 (0)