/** * 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.gms; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.util.UUID; import org.apache.cassandra.dht.IPartitioner; import org.apache.cassandra.dht.Token; import org.apache.cassandra.io.ICompactSerializer; import org.apache.cassandra.utils.FBUtilities; /** * This abstraction represents the state associated with a particular node which an * application wants to make available to the rest of the nodes in the cluster. * Whenever a piece of state needs to be disseminated to the rest of cluster wrap * the state in an instance of <i>ApplicationState</i> and add it to the Gossiper. * * e.g. if we want to disseminate load information for node A do the following: * * ApplicationState loadState = new ApplicationState(<string representation of load>); * Gossiper.instance.addApplicationState("LOAD STATE", loadState); */ public class VersionedValue implements Comparable<VersionedValue> { public static final ICompactSerializer<VersionedValue> serializer = new VersionedValueSerializer(); // this must be a char that cannot be present in any token public final static char DELIMITER = ','; public final static String DELIMITER_STR = new String(new char[] { DELIMITER }); // values for State.STATUS public final static String STATUS_BOOTSTRAPPING = "BOOT"; public final static String STATUS_NORMAL = "NORMAL"; public final static String STATUS_LEAVING = "LEAVING"; public final static String STATUS_LEFT = "LEFT"; public final static String REMOVING_TOKEN = "removing"; public final static String REMOVED_TOKEN = "removed"; public final int version; public final String value; public int stype; private VersionedValue(String value, int version) { this.value = value; this.version = version; stype = 0; } public VersionedValue(String value, int version, int stype) { this.value = value; this.version = version; this.stype = stype; } private VersionedValue(String value) { this.value = value; version = VersionGenerator.getNextVersion(); stype = 0; } public int compareTo(VersionedValue value) { return this.version - value.version; } public int getStorageType() { return stype; } public void setStorageType(int storageType) { stype = storageType; } public static class VersionedValueFactory { IPartitioner partitioner; public VersionedValueFactory(IPartitioner partitioner) { this.partitioner = partitioner; } public VersionedValue bootstrapping(Token token) { return new VersionedValue(VersionedValue.STATUS_BOOTSTRAPPING + VersionedValue.DELIMITER + partitioner.getTokenFactory().toString(token)); } public VersionedValue normal(Token token) { return new VersionedValue(VersionedValue.STATUS_NORMAL + VersionedValue.DELIMITER + partitioner.getTokenFactory().toString(token)); } public VersionedValue load(double load) { return new VersionedValue(String.valueOf(load)); } public VersionedValue migration(UUID newVersion) { return new VersionedValue(newVersion.toString()); } public VersionedValue leaving(Token token) { return new VersionedValue(VersionedValue.STATUS_LEAVING + VersionedValue.DELIMITER + partitioner.getTokenFactory().toString(token)); } public VersionedValue left(Token token) { return new VersionedValue(VersionedValue.STATUS_LEFT + VersionedValue.DELIMITER + partitioner.getTokenFactory().toString(token)); } public VersionedValue removingNonlocal(Token localToken, Token token) { return new VersionedValue(VersionedValue.STATUS_NORMAL + VersionedValue.DELIMITER + partitioner.getTokenFactory().toString(localToken) + VersionedValue.DELIMITER + VersionedValue.REMOVING_TOKEN + VersionedValue.DELIMITER + partitioner.getTokenFactory().toString(token)); } public VersionedValue removedNonlocal(Token localToken, Token token) { return new VersionedValue(VersionedValue.STATUS_NORMAL + VersionedValue.DELIMITER + partitioner.getTokenFactory().toString(localToken) + VersionedValue.DELIMITER + VersionedValue.REMOVED_TOKEN + VersionedValue.DELIMITER + partitioner.getTokenFactory().toString(token)); } public VersionedValue datacenter(String dcId) { return new VersionedValue(dcId); } public VersionedValue rack(String rackId) { return new VersionedValue(rackId); } public VersionedValue releaseVersion() { return new VersionedValue(FBUtilities.getReleaseVersionString()); } } private static class VersionedValueSerializer implements ICompactSerializer<VersionedValue> { public void serialize(VersionedValue value, DataOutputStream dos) throws IOException { dos.writeUTF(value.value); dos.writeInt(value.version); dos.writeInt(value.stype); } public VersionedValue deserialize(DataInputStream dis) throws IOException { String value = dis.readUTF(); int version = dis.readInt(); int stype = dis.readInt(); return new VersionedValue(value, version, stype); } } }