| /* |
| * 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.io.sstable.metadata; |
| |
| import java.io.*; |
| import java.nio.ByteBuffer; |
| import java.util.*; |
| |
| import com.google.common.collect.Maps; |
| |
| import org.apache.cassandra.db.TypeSizes; |
| import org.apache.cassandra.db.commitlog.IntervalSet; |
| import org.apache.cassandra.db.commitlog.ReplayPosition; |
| import org.apache.cassandra.io.sstable.Component; |
| import org.apache.cassandra.io.sstable.Descriptor; |
| import org.apache.cassandra.io.sstable.format.Version; |
| import org.apache.cassandra.io.util.DataInputPlus.DataInputStreamPlus; |
| import org.apache.cassandra.io.util.DataOutputPlus; |
| import org.apache.cassandra.service.ActiveRepairService; |
| import org.apache.cassandra.utils.ByteBufferUtil; |
| import org.apache.cassandra.utils.EstimatedHistogram; |
| import org.apache.cassandra.utils.StreamingHistogram; |
| |
| import static org.apache.cassandra.io.sstable.metadata.StatsMetadata.replayPositionSetSerializer; |
| |
| /** |
| * Serializer for SSTable from legacy versions |
| */ |
| @Deprecated |
| public class LegacyMetadataSerializer extends MetadataSerializer |
| { |
| /** |
| * Legacy serialization is only used for SSTable level reset. |
| */ |
| @Override |
| public void serialize(Map<MetadataType, MetadataComponent> components, DataOutputPlus out, Version version) throws IOException |
| { |
| ValidationMetadata validation = (ValidationMetadata) components.get(MetadataType.VALIDATION); |
| StatsMetadata stats = (StatsMetadata) components.get(MetadataType.STATS); |
| CompactionMetadata compaction = (CompactionMetadata) components.get(MetadataType.COMPACTION); |
| |
| assert validation != null && stats != null && compaction != null && validation.partitioner != null; |
| |
| EstimatedHistogram.serializer.serialize(stats.estimatedPartitionSize, out); |
| EstimatedHistogram.serializer.serialize(stats.estimatedColumnCount, out); |
| ReplayPosition.serializer.serialize(stats.commitLogIntervals.upperBound().orElse(ReplayPosition.NONE), out); |
| out.writeLong(stats.minTimestamp); |
| out.writeLong(stats.maxTimestamp); |
| out.writeInt(stats.maxLocalDeletionTime); |
| out.writeDouble(validation.bloomFilterFPChance); |
| out.writeDouble(stats.compressionRatio); |
| out.writeUTF(validation.partitioner); |
| out.writeInt(0); // compaction ancestors |
| StreamingHistogram.serializer.serialize(stats.estimatedTombstoneDropTime, out); |
| out.writeInt(stats.sstableLevel); |
| out.writeInt(stats.minClusteringValues.size()); |
| for (ByteBuffer value : stats.minClusteringValues) |
| ByteBufferUtil.writeWithShortLength(value, out); |
| out.writeInt(stats.maxClusteringValues.size()); |
| for (ByteBuffer value : stats.maxClusteringValues) |
| ByteBufferUtil.writeWithShortLength(value, out); |
| if (version.hasCommitLogLowerBound()) |
| ReplayPosition.serializer.serialize(stats.commitLogIntervals.lowerBound().orElse(ReplayPosition.NONE), out); |
| if (version.hasCommitLogIntervals()) |
| replayPositionSetSerializer.serialize(stats.commitLogIntervals, out); |
| } |
| |
| /** |
| * Legacy serializer deserialize all components no matter what types are specified. |
| */ |
| @Override |
| public Map<MetadataType, MetadataComponent> deserialize(Descriptor descriptor, EnumSet<MetadataType> types) throws IOException |
| { |
| Map<MetadataType, MetadataComponent> components = Maps.newHashMap(); |
| |
| File statsFile = new File(descriptor.filenameFor(Component.STATS)); |
| if (!statsFile.exists() && types.contains(MetadataType.STATS)) |
| { |
| components.put(MetadataType.STATS, MetadataCollector.defaultStatsMetadata()); |
| } |
| else |
| { |
| try (DataInputStreamPlus in = new DataInputStreamPlus(new BufferedInputStream(new FileInputStream(statsFile)))) |
| { |
| EstimatedHistogram partitionSizes = EstimatedHistogram.serializer.deserialize(in); |
| EstimatedHistogram columnCounts = EstimatedHistogram.serializer.deserialize(in); |
| ReplayPosition commitLogLowerBound = ReplayPosition.NONE; |
| ReplayPosition commitLogUpperBound = ReplayPosition.serializer.deserialize(in); |
| long minTimestamp = in.readLong(); |
| long maxTimestamp = in.readLong(); |
| int maxLocalDeletionTime = in.readInt(); |
| double bloomFilterFPChance = in.readDouble(); |
| double compressionRatio = in.readDouble(); |
| String partitioner = in.readUTF(); |
| int nbAncestors = in.readInt(); //skip compaction ancestors |
| in.skipBytes(nbAncestors * TypeSizes.sizeof(nbAncestors)); |
| StreamingHistogram tombstoneHistogram = StreamingHistogram.serializer.deserialize(in); |
| int sstableLevel = 0; |
| if (in.available() > 0) |
| sstableLevel = in.readInt(); |
| |
| int colCount = in.readInt(); |
| List<ByteBuffer> minColumnNames = new ArrayList<>(colCount); |
| for (int i = 0; i < colCount; i++) |
| minColumnNames.add(ByteBufferUtil.readWithShortLength(in)); |
| |
| colCount = in.readInt(); |
| List<ByteBuffer> maxColumnNames = new ArrayList<>(colCount); |
| for (int i = 0; i < colCount; i++) |
| maxColumnNames.add(ByteBufferUtil.readWithShortLength(in)); |
| |
| if (descriptor.version.hasCommitLogLowerBound()) |
| commitLogLowerBound = ReplayPosition.serializer.deserialize(in); |
| IntervalSet<ReplayPosition> commitLogIntervals; |
| if (descriptor.version.hasCommitLogIntervals()) |
| commitLogIntervals = replayPositionSetSerializer.deserialize(in); |
| else |
| commitLogIntervals = new IntervalSet<>(commitLogLowerBound, commitLogUpperBound); |
| |
| if (types.contains(MetadataType.VALIDATION)) |
| components.put(MetadataType.VALIDATION, |
| new ValidationMetadata(partitioner, bloomFilterFPChance)); |
| if (types.contains(MetadataType.STATS)) |
| components.put(MetadataType.STATS, |
| new StatsMetadata(partitionSizes, |
| columnCounts, |
| commitLogIntervals, |
| minTimestamp, |
| maxTimestamp, |
| Integer.MAX_VALUE, |
| maxLocalDeletionTime, |
| 0, |
| Integer.MAX_VALUE, |
| compressionRatio, |
| tombstoneHistogram, |
| sstableLevel, |
| minColumnNames, |
| maxColumnNames, |
| true, |
| ActiveRepairService.UNREPAIRED_SSTABLE, |
| -1, |
| -1)); |
| if (types.contains(MetadataType.COMPACTION)) |
| components.put(MetadataType.COMPACTION, |
| new CompactionMetadata(null)); |
| } |
| } |
| return components; |
| } |
| } |