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