/* * 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.DataInput; import java.io.IOException; import java.nio.ByteBuffer; import org.apache.cassandra.dht.*; import org.apache.cassandra.io.util.DataOutputPlus; import org.apache.cassandra.utils.ByteBufferUtil; public interface PartitionPosition extends RingPosition<PartitionPosition> { public static enum Kind { // Only add new values to the end of the enum, the ordinal is used // during serialization ROW_KEY, MIN_BOUND, MAX_BOUND; private static final Kind[] allKinds = Kind.values(); static Kind fromOrdinal(int ordinal) { return allKinds[ordinal]; } } public static final class ForKey { public static PartitionPosition get(ByteBuffer key, IPartitioner p) { return key == null || key.remaining() == 0 ? p.getMinimumToken().minKeyBound() : p.decorateKey(key); } } public static final RowPositionSerializer serializer = new RowPositionSerializer(); public Kind kind(); public boolean isMinimum(); public static class RowPositionSerializer implements IPartitionerDependentSerializer<PartitionPosition> { /* * We need to be able to serialize both Token.KeyBound and * DecoratedKey. To make this compact, we first write a byte whose * meaning is: * - 0: DecoratedKey * - 1: a 'minimum' Token.KeyBound * - 2: a 'maximum' Token.KeyBound * In the case of the DecoratedKey, we then serialize the key (the * token is recreated on the other side). In the other cases, we then * serialize the token. */ public void serialize(PartitionPosition pos, DataOutputPlus out, int version) throws IOException { Kind kind = pos.kind(); out.writeByte(kind.ordinal()); if (kind == Kind.ROW_KEY) ByteBufferUtil.writeWithShortLength(((DecoratedKey)pos).getKey(), out); else Token.serializer.serialize(pos.getToken(), out, version); } public PartitionPosition deserialize(DataInput in, IPartitioner p, int version) throws IOException { Kind kind = Kind.fromOrdinal(in.readByte()); if (kind == Kind.ROW_KEY) { ByteBuffer k = ByteBufferUtil.readWithShortLength(in); return p.decorateKey(k); } else { Token t = Token.serializer.deserialize(in, p, version); return kind == Kind.MIN_BOUND ? t.minKeyBound() : t.maxKeyBound(); } } public long serializedSize(PartitionPosition pos, int version) { Kind kind = pos.kind(); int size = 1; // 1 byte for enum if (kind == Kind.ROW_KEY) { int keySize = ((DecoratedKey)pos).getKey().remaining(); size += TypeSizes.sizeof((short) keySize) + keySize; } else { size += Token.serializer.serializedSize(pos.getToken(), version); } return size; } } }