This is an automated email from the ASF dual-hosted git repository.

bdeggleston pushed a commit to branch cassandra-3.11
in repository https://gitbox.apache.org/repos/asf/cassandra.git

commit 1cc941361a2613dce600695f844b84f2dd3670a8
Merge: 0d5ccb9 9382186
Author: Blake Eggleston <bdeggles...@gmail.com>
AuthorDate: Mon Nov 11 15:25:22 2019 -0800

    Merge branch 'cassandra-3.0' into cassandra-3.11

 CHANGES.txt                                        |  1 +
 .../org/apache/cassandra/db/BufferClustering.java  |  8 +++++
 .../org/apache/cassandra/db/ClusteringBound.java   |  8 +++++
 .../apache/cassandra/db/ClusteringBoundary.java    |  8 +++++
 .../org/apache/cassandra/db/ClusteringPrefix.java  |  6 ++++
 .../org/apache/cassandra/db/NativeClustering.java  |  5 ++++
 .../org/apache/cassandra/db/RangeTombstone.java    |  1 -
 src/java/org/apache/cassandra/db/Slice.java        |  1 +
 .../io/sstable/metadata/MetadataCollector.java     | 35 ++--------------------
 .../org/apache/cassandra/utils/ByteBufferUtil.java | 23 ++++++++++++++
 .../cassandra/io/sstable/SSTableMetadataTest.java  |  6 ++++
 11 files changed, 68 insertions(+), 34 deletions(-)

diff --cc CHANGES.txt
index 6781c4e,6dd6d0a..c1480a4
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@@ -1,5 -1,5 +1,6 @@@
 -3.0.20
 +3.11.6
 +Merged from 3.0:
+  * Minimize clustering values in metadata collector (CASSANDRA-15400)
   * Avoid over-trimming of results in mixed mode clusters (CASSANDRA-15405)
   * validate value sizes in LegacyLayout (CASSANDRA-15373)
   * Ensure that tracing doesn't break connections in 3.x/4.0 mixed mode by 
default (CASSANDRA-15385)
diff --cc src/java/org/apache/cassandra/db/BufferClustering.java
index df6a473,0000000..7ca9132
mode 100644,000000..100644
--- a/src/java/org/apache/cassandra/db/BufferClustering.java
+++ b/src/java/org/apache/cassandra/db/BufferClustering.java
@@@ -1,40 -1,0 +1,48 @@@
 +/*
 + * Licensed to the Apache Software Foundation (ASF) under one
 + * or more contributor license agreements.  See the NOTICE file
 + * distributed with this work for additional information
 + * regarding copyright ownership.  The ASF licenses this file
 + * to you 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 org.apache.cassandra.db;
 +
 +import java.nio.ByteBuffer;
 +
++import org.apache.cassandra.utils.ByteBufferUtil;
++
 +/**
 + * The clustering column values for a row.
 + * <p>
 + * A {@code Clustering} is a {@code ClusteringPrefix} that must always be 
"complete", i.e. have
 + * as many values as there is clustering columns in the table it is part of. 
It is the clustering
 + * prefix used by rows.
 + * <p>
 + * Note however that while it's size must be equal to the table clustering 
size, a clustering can have
 + * {@code null} values, and this mostly for thrift backward compatibility (in 
practice, if a value is null,
 + * all of the following ones will be too because that's what thrift allows, 
but it's never assumed by the
 + * code so we could start generally allowing nulls for clustering columns if 
we wanted to).
 + */
 +public class BufferClustering extends AbstractBufferClusteringPrefix 
implements Clustering
 +{
 +    BufferClustering(ByteBuffer... values)
 +    {
 +        super(Kind.CLUSTERING, values);
 +    }
++
++    public ClusteringPrefix minimize()
++    {
++        if (!ByteBufferUtil.canMinimize(values))
++            return this;
++        return new BufferClustering(ByteBufferUtil.minimizeBuffers(values));  
  }
 +}
diff --cc src/java/org/apache/cassandra/db/ClusteringBound.java
index c45f7ba,0000000..8bfeb32
mode 100644,000000..100644
--- a/src/java/org/apache/cassandra/db/ClusteringBound.java
+++ b/src/java/org/apache/cassandra/db/ClusteringBound.java
@@@ -1,171 -1,0 +1,179 @@@
 +/*
 + *
 + * Licensed to the Apache Software Foundation (ASF) under one
 + * or more contributor license agreements.  See the NOTICE file
 + * distributed with this work for additional information
 + * regarding copyright ownership.  The ASF licenses this file
 + * to you 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 org.apache.cassandra.db;
 +
 +import java.nio.ByteBuffer;
 +import java.util.List;
 +
++import org.apache.cassandra.utils.ByteBufferUtil;
 +import org.apache.cassandra.utils.memory.AbstractAllocator;
 +
 +/**
 + * The start or end of a range of clusterings, either inclusive or exclusive.
 + */
 +public class ClusteringBound extends ClusteringBoundOrBoundary
 +{
 +    /** The smallest start bound, i.e. the one that starts before any row. */
 +    public static final ClusteringBound BOTTOM = new 
ClusteringBound(Kind.INCL_START_BOUND, EMPTY_VALUES_ARRAY);
 +    /** The biggest end bound, i.e. the one that ends after any row. */
 +    public static final ClusteringBound TOP = new 
ClusteringBound(Kind.INCL_END_BOUND, EMPTY_VALUES_ARRAY);
 +
 +    protected ClusteringBound(Kind kind, ByteBuffer[] values)
 +    {
 +        super(kind, values);
 +    }
 +
 +    public static ClusteringBound create(Kind kind, ByteBuffer[] values)
 +    {
 +        assert !kind.isBoundary();
 +        return new ClusteringBound(kind, values);
 +    }
 +
 +    public static Kind boundKind(boolean isStart, boolean isInclusive)
 +    {
 +        return isStart
 +             ? (isInclusive ? Kind.INCL_START_BOUND : Kind.EXCL_START_BOUND)
 +             : (isInclusive ? Kind.INCL_END_BOUND : Kind.EXCL_END_BOUND);
 +    }
 +
 +    public static ClusteringBound inclusiveStartOf(ByteBuffer... values)
 +    {
 +        return create(Kind.INCL_START_BOUND, values);
 +    }
 +
 +    public static ClusteringBound inclusiveEndOf(ByteBuffer... values)
 +    {
 +        return create(Kind.INCL_END_BOUND, values);
 +    }
 +
 +    public static ClusteringBound exclusiveStartOf(ByteBuffer... values)
 +    {
 +        return create(Kind.EXCL_START_BOUND, values);
 +    }
 +
 +    public static ClusteringBound exclusiveEndOf(ByteBuffer... values)
 +    {
 +        return create(Kind.EXCL_END_BOUND, values);
 +    }
 +
 +    public static ClusteringBound inclusiveStartOf(ClusteringPrefix prefix)
 +    {
 +        ByteBuffer[] values = new ByteBuffer[prefix.size()];
 +        for (int i = 0; i < prefix.size(); i++)
 +            values[i] = prefix.get(i);
 +        return inclusiveStartOf(values);
 +    }
 +
 +    public static ClusteringBound exclusiveStartOf(ClusteringPrefix prefix)
 +    {
 +        ByteBuffer[] values = new ByteBuffer[prefix.size()];
 +        for (int i = 0; i < prefix.size(); i++)
 +            values[i] = prefix.get(i);
 +        return exclusiveStartOf(values);
 +    }
 +
 +    public static ClusteringBound inclusiveEndOf(ClusteringPrefix prefix)
 +    {
 +        ByteBuffer[] values = new ByteBuffer[prefix.size()];
 +        for (int i = 0; i < prefix.size(); i++)
 +            values[i] = prefix.get(i);
 +        return inclusiveEndOf(values);
 +    }
 +
 +    public static ClusteringBound create(ClusteringComparator comparator, 
boolean isStart, boolean isInclusive, Object... values)
 +    {
 +        CBuilder builder = CBuilder.create(comparator);
 +        for (Object val : values)
 +        {
 +            if (val instanceof ByteBuffer)
 +                builder.add((ByteBuffer) val);
 +            else
 +                builder.add(val);
 +        }
 +        return builder.buildBound(isStart, isInclusive);
 +    }
 +
 +    @Override
 +    public ClusteringBound invert()
 +    {
 +        return create(kind().invert(), values);
 +    }
 +
 +    public ClusteringBound copy(AbstractAllocator allocator)
 +    {
 +        return (ClusteringBound) super.copy(allocator);
 +    }
 +
++    public ClusteringPrefix minimize()
++    {
++        if (!ByteBufferUtil.canMinimize(values))
++            return this;
++        return new ClusteringBound(kind, 
ByteBufferUtil.minimizeBuffers(values));
++    }
++
 +    public boolean isStart()
 +    {
 +        return kind().isStart();
 +    }
 +
 +    public boolean isEnd()
 +    {
 +        return !isStart();
 +    }
 +
 +    public boolean isInclusive()
 +    {
 +        return kind == Kind.INCL_START_BOUND || kind == Kind.INCL_END_BOUND;
 +    }
 +
 +    public boolean isExclusive()
 +    {
 +        return kind == Kind.EXCL_START_BOUND || kind == Kind.EXCL_END_BOUND;
 +    }
 +
 +    // For use by intersects, it's called with the sstable bound opposite to 
the slice bound
 +    // (so if the slice bound is a start, it's call with the max sstable 
bound)
 +    int compareTo(ClusteringComparator comparator, List<ByteBuffer> 
sstableBound)
 +    {
 +        for (int i = 0; i < sstableBound.size(); i++)
 +        {
 +            // Say the slice bound is a start. It means we're in the case 
where the max
 +            // sstable bound is say (1:5) while the slice start is (1). So 
the start
 +            // does start before the sstable end bound (and intersect it). 
It's the exact
 +            // inverse with a end slice bound.
 +            if (i >= size())
 +                return isStart() ? -1 : 1;
 +
 +            int cmp = comparator.compareComponent(i, get(i), 
sstableBound.get(i));
 +            if (cmp != 0)
 +                return cmp;
 +        }
 +
 +        // Say the slice bound is a start. I means we're in the case where 
the max
 +        // sstable bound is say (1), while the slice start is (1:5). This 
again means
 +        // that the slice start before the end bound.
 +        if (size() > sstableBound.size())
 +            return isStart() ? -1 : 1;
 +
 +        // The slice bound is equal to the sstable bound. Results depends on 
whether the slice is inclusive or not
 +        return isInclusive() ? 0 : (isStart() ? 1 : -1);
 +    }
 +}
diff --cc src/java/org/apache/cassandra/db/ClusteringBoundary.java
index 37b3210,0000000..7a6842b
mode 100644,000000..100644
--- a/src/java/org/apache/cassandra/db/ClusteringBoundary.java
+++ b/src/java/org/apache/cassandra/db/ClusteringBoundary.java
@@@ -1,65 -1,0 +1,73 @@@
 +/*
 + *
 + * Licensed to the Apache Software Foundation (ASF) under one
 + * or more contributor license agreements.  See the NOTICE file
 + * distributed with this work for additional information
 + * regarding copyright ownership.  The ASF licenses this file
 + * to you 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 org.apache.cassandra.db;
 +
 +import java.nio.ByteBuffer;
 +
++import org.apache.cassandra.utils.ByteBufferUtil;
 +import org.apache.cassandra.utils.memory.AbstractAllocator;
 +
 +/**
 + * The threshold between two different ranges, i.e. a shortcut for the 
combination of two ClusteringBounds -- one
 + * specifying the end of one of the ranges, and its (implicit) complement 
specifying the beginning of the other.
 + */
 +public class ClusteringBoundary extends ClusteringBoundOrBoundary
 +{
 +    protected ClusteringBoundary(Kind kind, ByteBuffer[] values)
 +    {
 +        super(kind, values);
 +    }
 +
 +    public static ClusteringBoundary create(Kind kind, ByteBuffer[] values)
 +    {
 +        assert kind.isBoundary();
 +        return new ClusteringBoundary(kind, values);
 +    }
 +
 +    @Override
 +    public ClusteringBoundary invert()
 +    {
 +        return create(kind().invert(), values);
 +    }
 +
 +    @Override
 +    public ClusteringBoundary copy(AbstractAllocator allocator)
 +    {
 +        return (ClusteringBoundary) super.copy(allocator);
 +    }
 +
++    public ClusteringPrefix minimize()
++    {
++        if (!ByteBufferUtil.canMinimize(values))
++            return this;
++        return new ClusteringBoundary(kind, 
ByteBufferUtil.minimizeBuffers(values));
++    }
++
 +    public ClusteringBound openBound(boolean reversed)
 +    {
 +        return ClusteringBound.create(kind.openBoundOfBoundary(reversed), 
values);
 +    }
 +
 +    public ClusteringBound closeBound(boolean reversed)
 +    {
 +        return ClusteringBound.create(kind.closeBoundOfBoundary(reversed), 
values);
 +    }
 +}
diff --cc src/java/org/apache/cassandra/db/NativeClustering.java
index 1943b71,0000000..e96435b
mode 100644,000000..100644
--- a/src/java/org/apache/cassandra/db/NativeClustering.java
+++ b/src/java/org/apache/cassandra/db/NativeClustering.java
@@@ -1,125 -1,0 +1,130 @@@
 +/*
 +* Licensed to the Apache Software Foundation (ASF) under one
 +* or more contributor license agreements.  See the NOTICE file
 +* distributed with this work for additional information
 +* regarding copyright ownership.  The ASF licenses this file
 +* to you 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 org.apache.cassandra.db;
 +
 +import java.nio.ByteBuffer;
 +import java.nio.ByteOrder;
 +
 +import org.apache.cassandra.utils.ObjectSizes;
 +import org.apache.cassandra.utils.concurrent.OpOrder;
 +import org.apache.cassandra.utils.memory.MemoryUtil;
 +import org.apache.cassandra.utils.memory.NativeAllocator;
 +
 +public class NativeClustering extends AbstractClusteringPrefix implements 
Clustering
 +{
 +    private static final long EMPTY_SIZE = ObjectSizes.measure(new 
NativeClustering());
 +
 +    private final long peer;
 +
 +    private NativeClustering() { peer = 0; }
 +
 +    public NativeClustering(NativeAllocator allocator, OpOrder.Group writeOp, 
Clustering clustering)
 +    {
 +        int count = clustering.size();
 +        int metadataSize = (count * 2) + 4;
 +        int dataSize = clustering.dataSize();
 +        int bitmapSize = ((count + 7) >>> 3);
 +
 +        assert count < 64 << 10;
 +        assert dataSize < 64 << 10;
 +
 +        peer = allocator.allocate(metadataSize + dataSize + bitmapSize, 
writeOp);
 +        long bitmapStart = peer + metadataSize;
 +        MemoryUtil.setShort(peer, (short) count);
 +        MemoryUtil.setShort(peer + (metadataSize - 2), (short) dataSize); // 
goes at the end of the other offsets
 +
 +        MemoryUtil.setByte(bitmapStart, bitmapSize, (byte) 0);
 +        long dataStart = peer + metadataSize + bitmapSize;
 +        int dataOffset = 0;
 +        for (int i = 0 ; i < count ; i++)
 +        {
 +            MemoryUtil.setShort(peer + 2 + i * 2, (short) dataOffset);
 +
 +            ByteBuffer value = clustering.get(i);
 +            if (value == null)
 +            {
 +                long boffset = bitmapStart + (i >>> 3);
 +                int b = MemoryUtil.getByte(boffset);
 +                b |= 1 << (i & 7);
 +                MemoryUtil.setByte(boffset, (byte) b);
 +                continue;
 +            }
 +
 +            assert value.order() == ByteOrder.BIG_ENDIAN;
 +
 +            int size = value.remaining();
 +            MemoryUtil.setBytes(dataStart + dataOffset, value);
 +            dataOffset += size;
 +        }
 +    }
 +
 +    public Kind kind()
 +    {
 +        return Kind.CLUSTERING;
 +    }
 +
 +    public int size()
 +    {
 +        return MemoryUtil.getShort(peer);
 +    }
 +
 +    public ByteBuffer get(int i)
 +    {
 +        // offset at which we store the dataOffset
 +        int size = size();
 +        if (i >= size)
 +            throw new IndexOutOfBoundsException();
 +
 +        int metadataSize = (size * 2) + 4;
 +        int bitmapSize = ((size + 7) >>> 3);
 +        long bitmapStart = peer + metadataSize;
 +        int b = MemoryUtil.getByte(bitmapStart + (i >>> 3));
 +        if ((b & (1 << (i & 7))) != 0)
 +            return null;
 +
 +        int startOffset = MemoryUtil.getShort(peer + 2 + i * 2);
 +        int endOffset = MemoryUtil.getShort(peer + 4 + i * 2);
 +        return MemoryUtil.getByteBuffer(bitmapStart + bitmapSize + 
startOffset,
 +                                        endOffset - startOffset,
 +                                        ByteOrder.BIG_ENDIAN);
 +    }
 +
 +    public ByteBuffer[] getRawValues()
 +    {
 +        ByteBuffer[] values = new ByteBuffer[size()];
 +        for (int i = 0 ; i < values.length ; i++)
 +            values[i] = get(i);
 +        return values;
 +    }
 +
 +    public long unsharedHeapSize()
 +    {
 +        return EMPTY_SIZE;
 +    }
 +
 +    public long unsharedHeapSizeExcludingData()
 +    {
 +        return EMPTY_SIZE;
 +    }
++
++    public ClusteringPrefix minimize()
++    {
++        return this;
++    }
 +}
diff --cc src/java/org/apache/cassandra/db/RangeTombstone.java
index 8e01b8e,4a26581..eb9725a
--- a/src/java/org/apache/cassandra/db/RangeTombstone.java
+++ b/src/java/org/apache/cassandra/db/RangeTombstone.java
@@@ -17,11 -17,19 +17,10 @@@
   */
  package org.apache.cassandra.db;
  
 -import java.io.IOException;
 -import java.nio.ByteBuffer;
 -import java.util.List;
  import java.util.Objects;
  
 -import org.apache.cassandra.db.marshal.AbstractType;
  import org.apache.cassandra.db.rows.RangeTombstoneMarker;
 -import org.apache.cassandra.io.util.DataInputPlus;
 -import org.apache.cassandra.io.util.DataOutputPlus;
 -import org.apache.cassandra.utils.ByteBufferUtil;
 -import org.apache.cassandra.utils.memory.AbstractAllocator;
 -
  
- 
  /**
   * A range tombstone is a tombstone that covers a slice/range of rows.
   * <p>


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscr...@cassandra.apache.org
For additional commands, e-mail: commits-h...@cassandra.apache.org

Reply via email to