stevenzwu commented on code in PR #18544:
URL: https://github.com/apache/iceberg/pull/18544#discussion_r4353425026
##########
core/src/main/java/org/apache/iceberg/mumbling/MumblingBitmap.java:
##########
@@ -138,6 +160,282 @@ private int offset(int containerIndex) {
return offsets[containerIndex];
}
+ public MutableBitmap asMutable() {
+ return new Mutable(this);
+ }
+
+ /**
+ * A copy-on-write {@link MutableBitmap} implementation for Mumbling.
+ *
+ * <p>When a new bit position is set, an overlay is created for the
position's container.
+ *
+ * <p>The initial buffer is not modified.
+ */
+ private static class Mutable implements MutableBitmap {
+ private final NavigableMap<Integer, Container> overlays =
Maps.newTreeMap();
+ private final MumblingBitmap base;
+ private final int baseContainerCount;
+ private int cardinality = 0;
+
+ public Mutable(MumblingBitmap base) {
+ this.base = base;
+ this.baseContainerCount = base.descriptors().length;
+ this.cardinality = base.cardinality();
+ }
+
+ @Override
+ public int cardinality() {
+ return cardinality;
+ }
+
+ @Override
+ public boolean isSet(int pos) {
+ Container overlay = overlays.get(containerIndex(pos));
+ if (overlay != null) {
+ return overlay.isSet(posInContainer(pos));
+ }
+
+ return base.isSet(pos);
+ }
+
+ @Override
+ public boolean set(int pos) {
+ Preconditions.checkArgument(pos >= 0, "Cannot set invalid bit position:
%s < 0", pos);
+ Preconditions.checkArgument(
+ pos < MAX_CARDINALITY, "Cannot set invalid bit position: %s (must be
< 2,097,152)", pos);
+
+ int containerIndex = containerIndex(pos);
+ Container overlay = overlays.get(containerIndex);
+ if (overlay == null) {
+ if (containerIndex < baseContainerCount) {
+ overlay =
+ new Container(
+ base.buffer(), base.offset(containerIndex),
base.descriptor(containerIndex));
+ } else {
+ overlay = new Container();
+ }
+ overlays.put(containerIndex, overlay);
+ }
+
+ if (overlay.set(posInContainer(pos))) {
+ this.cardinality += 1;
+ return true;
+ }
+
+ return false;
+ }
+
+ @Override
+ public ByteBuffer buffer() {
+ int[] descriptorArray = descriptorArray();
+ int containersSize = sizeOfContainers(descriptorArray, 0,
descriptorArray.length);
+ ByteBuffer descBuffer = PFOREncoding.encode(descriptorArray,
descriptorArray.length);
+ int descriptorsSize = descBuffer.remaining();
+
+ ByteBuffer buffer = ByteBuffer.allocate(HEADER_SIZE + descriptorsSize +
containersSize);
+ int currentPos = writeHeader(buffer, cardinality,
descriptorArray.length);
+
+ buffer.put(HEADER_SIZE, descBuffer, descBuffer.position(),
descriptorsSize);
+ currentPos += descriptorsSize;
+
+ int nextContainerIndex = 0;
+ for (Map.Entry<Integer, Container> entry : overlays.entrySet()) {
+ int containerIndex = entry.getKey();
+ currentPos +=
+ copyOriginalContainers(
+ descriptorArray, nextContainerIndex, containerIndex, buffer,
currentPos);
+ currentPos += entry.getValue().writeTo(buffer, currentPos);
+ nextContainerIndex = containerIndex + 1;
+ }
+
+ copyOriginalContainers(
+ descriptorArray, nextContainerIndex, descriptorArray.length, buffer,
currentPos);
+
+ return buffer;
+ }
+
+ private int[] descriptorArray() {
+ int[] baseDescriptors = base.descriptors();
+ int lastOverlayIndex = overlays.isEmpty() ? -1 : overlays.lastKey();
+ int numContainers = Math.max(lastOverlayIndex + 1,
baseDescriptors.length);
Review Comment:
I forgot overlays also contains updated containers.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]