| /* |
| * 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.io.*; |
| import java.nio.ByteBuffer; |
| import java.util.List; |
| |
| import org.apache.cassandra.config.CFMetaData; |
| import org.apache.cassandra.db.marshal.CompositeType; |
| import org.apache.cassandra.io.ISerializer; |
| import org.apache.cassandra.io.util.DataInputPlus; |
| import org.apache.cassandra.io.util.DataOutputPlus; |
| import org.apache.cassandra.io.sstable.format.Version; |
| import org.apache.cassandra.utils.ByteBufferUtil; |
| |
| /** |
| * Holds references on serializers that depend on the table definition. |
| */ |
| public class Serializers |
| { |
| private final CFMetaData metadata; |
| |
| public Serializers(CFMetaData metadata) |
| { |
| this.metadata = metadata; |
| } |
| |
| // TODO: Once we drop support for old (pre-3.0) sstables, we can drop this method and inline the calls to |
| // ClusteringPrefix.serializer in IndexHelper directly. At which point this whole class probably becomes |
| // unecessary (since IndexInfo.Serializer won't depend on the metadata either). |
| public ISerializer<ClusteringPrefix> indexEntryClusteringPrefixSerializer(final Version version, final SerializationHeader header) |
| { |
| if (!version.storeRows() || header == null) //null header indicates streaming from pre-3.0 sstables |
| { |
| return oldFormatSerializer(version); |
| } |
| |
| return newFormatSerializer(version, header); |
| } |
| |
| private ISerializer<ClusteringPrefix> oldFormatSerializer(final Version version) |
| { |
| return new ISerializer<ClusteringPrefix>() |
| { |
| SerializationHeader newHeader = SerializationHeader.makeWithoutStats(metadata); |
| |
| public void serialize(ClusteringPrefix clustering, DataOutputPlus out) throws IOException |
| { |
| //we deserialize in the old format and serialize in the new format |
| ClusteringPrefix.serializer.serialize(clustering, out, |
| version.correspondingMessagingVersion(), |
| newHeader.clusteringTypes()); |
| } |
| |
| public ClusteringPrefix deserialize(DataInputPlus in) throws IOException |
| { |
| // We're reading the old cellname/composite |
| ByteBuffer bb = ByteBufferUtil.readWithShortLength(in); |
| assert bb.hasRemaining(); // empty cellnames were invalid |
| |
| int clusteringSize = metadata.clusteringColumns().size(); |
| // If the table has no clustering column, then the cellname will just be the "column" name, which we ignore here. |
| if (clusteringSize == 0) |
| return Clustering.EMPTY; |
| |
| if (!metadata.isCompound()) |
| return new Clustering(bb); |
| |
| List<ByteBuffer> components = CompositeType.splitName(bb); |
| byte eoc = CompositeType.lastEOC(bb); |
| |
| if (eoc == 0 || components.size() >= clusteringSize) |
| { |
| // That's a clustering. |
| if (components.size() > clusteringSize) |
| components = components.subList(0, clusteringSize); |
| |
| return new Clustering(components.toArray(new ByteBuffer[clusteringSize])); |
| } |
| else |
| { |
| // It's a range tombstone bound. It is a start since that's the only part we've ever included |
| // in the index entries. |
| Slice.Bound.Kind boundKind = eoc > 0 |
| ? Slice.Bound.Kind.EXCL_START_BOUND |
| : Slice.Bound.Kind.INCL_START_BOUND; |
| |
| return Slice.Bound.create(boundKind, components.toArray(new ByteBuffer[components.size()])); |
| } |
| } |
| |
| public long serializedSize(ClusteringPrefix clustering) |
| { |
| return ClusteringPrefix.serializer.serializedSize(clustering, version.correspondingMessagingVersion(), |
| newHeader.clusteringTypes()); |
| } |
| }; |
| } |
| |
| |
| private ISerializer<ClusteringPrefix> newFormatSerializer(final Version version, final SerializationHeader header) |
| { |
| return new ISerializer<ClusteringPrefix>() //Reading and writing from/to the new sstable format |
| { |
| public void serialize(ClusteringPrefix clustering, DataOutputPlus out) throws IOException |
| { |
| ClusteringPrefix.serializer.serialize(clustering, out, version.correspondingMessagingVersion(), header.clusteringTypes()); |
| } |
| |
| public ClusteringPrefix deserialize(DataInputPlus in) throws IOException |
| { |
| return ClusteringPrefix.serializer.deserialize(in, version.correspondingMessagingVersion(), header.clusteringTypes()); |
| } |
| |
| public long serializedSize(ClusteringPrefix clustering) |
| { |
| return ClusteringPrefix.serializer.serializedSize(clustering, version.correspondingMessagingVersion(), header.clusteringTypes()); |
| } |
| }; |
| } |
| |
| } |