mirror of https://github.com/apache/cassandra
[CASSANDRA-20736] Add CMS membership directly to ClusterMetadata
This commit is contained in:
parent
5282f81d0a
commit
1cfa689778
|
|
@ -0,0 +1,203 @@
|
|||
/*
|
||||
* 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.tcm;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Objects;
|
||||
import java.util.SortedSet;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
|
||||
import org.apache.cassandra.db.TypeSizes;
|
||||
import org.apache.cassandra.io.util.DataInputPlus;
|
||||
import org.apache.cassandra.io.util.DataOutputPlus;
|
||||
import org.apache.cassandra.tcm.membership.NodeId;
|
||||
import org.apache.cassandra.tcm.serialization.MetadataSerializer;
|
||||
import org.apache.cassandra.tcm.serialization.Version;
|
||||
import org.apache.cassandra.utils.btree.BTreeSet;
|
||||
|
||||
public class CMSMembership implements MetadataValue<CMSMembership>
|
||||
{
|
||||
public static final Serializer serializer = new Serializer();
|
||||
public static final CMSMembership EMPTY = new CMSMembership();
|
||||
|
||||
private final Epoch lastModified;
|
||||
private final BTreeSet<NodeId> fullMembers;
|
||||
private final BTreeSet<NodeId> joiningMembers;
|
||||
|
||||
private CMSMembership()
|
||||
{
|
||||
this(Epoch.EMPTY,
|
||||
BTreeSet.empty(NodeId::compareTo),
|
||||
BTreeSet.empty(NodeId::compareTo));
|
||||
}
|
||||
|
||||
private CMSMembership(Epoch lastModified, BTreeSet<NodeId> fullMembers, BTreeSet<NodeId> joiningMembers)
|
||||
{
|
||||
this.lastModified = lastModified;
|
||||
this.fullMembers = fullMembers;
|
||||
this.joiningMembers = joiningMembers;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public CMSMembership withLastModified(Epoch epoch)
|
||||
{
|
||||
return lastModified.is(epoch) ? this : new CMSMembership(epoch, fullMembers, joiningMembers);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Epoch lastModified()
|
||||
{
|
||||
return lastModified;
|
||||
}
|
||||
|
||||
public ImmutableSet<NodeId> joiningMembers()
|
||||
{
|
||||
return ImmutableSet.copyOf(joiningMembers);
|
||||
}
|
||||
|
||||
public ImmutableSet<NodeId> fullMembers()
|
||||
{
|
||||
return ImmutableSet.copyOf(fullMembers);
|
||||
}
|
||||
|
||||
public CMSMembership startJoining(NodeId id)
|
||||
{
|
||||
if (joiningMembers.contains(id))
|
||||
throw new IllegalStateException(id + " is already joining the CMS");
|
||||
if (fullMembers.contains(id))
|
||||
throw new IllegalStateException(id + " has already fully joined the CMS");
|
||||
|
||||
return new CMSMembership(lastModified, fullMembers, joiningMembers.with(id));
|
||||
}
|
||||
|
||||
public CMSMembership cancelJoining(NodeId id)
|
||||
{
|
||||
if (!joiningMembers.contains(id))
|
||||
throw new IllegalStateException(id + " is not currently joining the CMS");
|
||||
if (fullMembers.contains(id))
|
||||
throw new IllegalStateException(id + " has already fully joined the CMS");
|
||||
|
||||
return new CMSMembership(lastModified, fullMembers, joiningMembers.without(id));
|
||||
}
|
||||
|
||||
public CMSMembership finishJoining(NodeId id)
|
||||
{
|
||||
if (!joiningMembers.contains(id))
|
||||
throw new IllegalStateException(id + " is not currently joining the CMS");
|
||||
if (fullMembers.contains(id))
|
||||
throw new IllegalStateException(id + " has already fully joined the CMS");
|
||||
|
||||
return new CMSMembership(lastModified, fullMembers.with(id), joiningMembers.without(id));
|
||||
}
|
||||
|
||||
public CMSMembership leave(NodeId id)
|
||||
{
|
||||
if (joiningMembers.contains(id))
|
||||
throw new IllegalStateException(id + " is currently joining the CMS, ");
|
||||
if (!fullMembers.contains(id))
|
||||
throw new IllegalStateException(id + " is not a CMS member");
|
||||
|
||||
return new CMSMembership(lastModified, fullMembers.without(id), joiningMembers);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return "CMSMembership{" +
|
||||
"lastModified=" + lastModified +
|
||||
", fullMembers=" + fullMembers +
|
||||
", joiningMembers=" + joiningMembers +
|
||||
'}';
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean equals(Object o)
|
||||
{
|
||||
if (!(o instanceof CMSMembership)) return false;
|
||||
|
||||
CMSMembership that = (CMSMembership) o;
|
||||
return Objects.equals(lastModified, that.lastModified) &&
|
||||
Objects.equals(fullMembers, that.fullMembers) &&
|
||||
Objects.equals(joiningMembers, that.joiningMembers);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
int result = Objects.hashCode(lastModified);
|
||||
result = 31 * result + Objects.hashCode(fullMembers);
|
||||
result = 31 * result + Objects.hashCode(joiningMembers);
|
||||
return result;
|
||||
}
|
||||
|
||||
public static class Serializer implements MetadataSerializer<CMSMembership>
|
||||
{
|
||||
@Override
|
||||
public void serialize(CMSMembership t, DataOutputPlus out, Version version) throws IOException
|
||||
{
|
||||
Epoch.serializer.serialize(t.lastModified, out);
|
||||
|
||||
out.writeUnsignedVInt32(t.fullMembers.size());
|
||||
for (NodeId id : t.fullMembers)
|
||||
NodeId.serializer.serialize(id, out, version);
|
||||
|
||||
out.writeUnsignedVInt32(t.joiningMembers.size());
|
||||
for (NodeId id : t.joiningMembers)
|
||||
NodeId.serializer.serialize(id, out, version);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CMSMembership deserialize(DataInputPlus in, Version version) throws IOException
|
||||
{
|
||||
Epoch lastModified = Epoch.serializer.deserialize(in, version);
|
||||
|
||||
int fullMemberCount = in.readUnsignedVInt32();
|
||||
SortedSet<NodeId> fullMembers = new TreeSet<>();
|
||||
for (int i = 0; i < fullMemberCount; i++)
|
||||
fullMembers.add(NodeId.serializer.deserialize(in, version));
|
||||
|
||||
int joiningMemberCount = in.readUnsignedVInt32();
|
||||
SortedSet<NodeId> joiningMembers = new TreeSet<>();
|
||||
for (int i = 0; i < joiningMemberCount; i++)
|
||||
joiningMembers.add(NodeId.serializer.deserialize(in, version));
|
||||
|
||||
return new CMSMembership(lastModified, BTreeSet.of(fullMembers), BTreeSet.of(joiningMembers)) ;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long serializedSize(CMSMembership t, Version version)
|
||||
{
|
||||
long size = Epoch.serializer.serializedSize(t.lastModified);
|
||||
|
||||
size += TypeSizes.sizeofUnsignedVInt(t.fullMembers.size());
|
||||
for (NodeId id : t.fullMembers)
|
||||
size += NodeId.serializer.serializedSize(id, version);
|
||||
|
||||
size += TypeSizes.sizeofUnsignedVInt(t.joiningMembers.size());
|
||||
for (NodeId id : t.joiningMembers)
|
||||
size += NodeId.serializer.serializedSize(id, version);
|
||||
|
||||
return size;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -29,6 +29,7 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
|
|
@ -62,7 +63,6 @@ import org.apache.cassandra.schema.KeyspaceMetadata;
|
|||
import org.apache.cassandra.schema.KeyspaceParams;
|
||||
import org.apache.cassandra.schema.Keyspaces;
|
||||
import org.apache.cassandra.schema.ReplicationParams;
|
||||
import org.apache.cassandra.schema.SchemaConstants;
|
||||
import org.apache.cassandra.schema.TableId;
|
||||
import org.apache.cassandra.service.accord.topology.AccordFastPath;
|
||||
import org.apache.cassandra.service.accord.topology.AccordStaleReplicas;
|
||||
|
|
@ -89,7 +89,6 @@ import org.apache.cassandra.tcm.serialization.Version;
|
|||
import org.apache.cassandra.utils.FBUtilities;
|
||||
import org.apache.cassandra.utils.Pair;
|
||||
|
||||
import static com.google.common.collect.ImmutableSet.toImmutableSet;
|
||||
import static org.apache.cassandra.config.CassandraRelevantProperties.LINE_SEPARATOR;
|
||||
import static org.apache.cassandra.db.TypeSizes.sizeof;
|
||||
import static org.apache.cassandra.tcm.serialization.Version.MIN_ACCORD_VERSION;
|
||||
|
|
@ -114,6 +113,7 @@ public class ClusterMetadata
|
|||
public final ConsensusMigrationState consensusMigrationState;
|
||||
public final ImmutableMap<ExtensionKey<?,?>, ExtensionValue<?>> extensions;
|
||||
public final AccordStaleReplicas accordStaleReplicas;
|
||||
public final CMSMembership cmsMembership;
|
||||
|
||||
// This isn't serialized as part of ClusterMetadata it's really just a view over the Directory.
|
||||
public final Locator locator;
|
||||
|
|
@ -121,7 +121,6 @@ public class ClusterMetadata
|
|||
// These fields are lazy but only for the test purposes, since their computation requires initialization of the log ks
|
||||
private EndpointsForRange fullCMSReplicas;
|
||||
private Set<InetAddressAndPort> fullCMSEndpoints;
|
||||
private Set<NodeId> fullCMSIds;
|
||||
private volatile Map<ReplicationParams, RangesAtEndpoint> localRangesAllSettled = null;
|
||||
private static final RangesAtEndpoint EMPTY_LOCAL_RANGES = RangesAtEndpoint.empty(FBUtilities.getBroadcastAddressAndPort());
|
||||
|
||||
|
|
@ -151,7 +150,8 @@ public class ClusterMetadata
|
|||
InProgressSequences.EMPTY,
|
||||
ConsensusMigrationState.EMPTY,
|
||||
ImmutableMap.of(),
|
||||
AccordStaleReplicas.EMPTY);
|
||||
AccordStaleReplicas.EMPTY,
|
||||
CMSMembership.EMPTY);
|
||||
}
|
||||
|
||||
public ClusterMetadata(Epoch epoch,
|
||||
|
|
@ -165,7 +165,8 @@ public class ClusterMetadata
|
|||
InProgressSequences inProgressSequences,
|
||||
ConsensusMigrationState consensusMigrationState,
|
||||
Map<ExtensionKey<?, ?>, ExtensionValue<?>> extensions,
|
||||
AccordStaleReplicas accordStaleReplicas)
|
||||
AccordStaleReplicas accordStaleReplicas,
|
||||
CMSMembership cmsMembership)
|
||||
{
|
||||
this(EMPTY_METADATA_IDENTIFIER,
|
||||
epoch,
|
||||
|
|
@ -179,22 +180,25 @@ public class ClusterMetadata
|
|||
inProgressSequences,
|
||||
consensusMigrationState,
|
||||
extensions,
|
||||
accordStaleReplicas);
|
||||
accordStaleReplicas,
|
||||
cmsMembership);
|
||||
}
|
||||
|
||||
|
||||
private ClusterMetadata(int metadataIdentifier,
|
||||
Epoch epoch,
|
||||
IPartitioner partitioner,
|
||||
DistributedSchema schema,
|
||||
Directory directory,
|
||||
TokenMap tokenMap,
|
||||
DataPlacements placements,
|
||||
AccordFastPath accordFastPath,
|
||||
LockedRanges lockedRanges,
|
||||
InProgressSequences inProgressSequences,
|
||||
ConsensusMigrationState consensusMigrationState,
|
||||
Map<ExtensionKey<?, ?>, ExtensionValue<?>> extensions,
|
||||
AccordStaleReplicas accordStaleReplicas)
|
||||
Epoch epoch,
|
||||
IPartitioner partitioner,
|
||||
DistributedSchema schema,
|
||||
Directory directory,
|
||||
TokenMap tokenMap,
|
||||
DataPlacements placements,
|
||||
AccordFastPath accordFastPath,
|
||||
LockedRanges lockedRanges,
|
||||
InProgressSequences inProgressSequences,
|
||||
ConsensusMigrationState consensusMigrationState,
|
||||
Map<ExtensionKey<?, ?>, ExtensionValue<?>> extensions,
|
||||
AccordStaleReplicas accordStaleReplicas,
|
||||
CMSMembership cmsMembership)
|
||||
{
|
||||
// TODO: token map is a feature of the specific placement strategy, and so may not be a relevant component of
|
||||
// ClusterMetadata in the long term. We need to consider how the actual components of metadata can be evolved
|
||||
|
|
@ -214,6 +218,7 @@ public class ClusterMetadata
|
|||
this.extensions = ImmutableMap.copyOf(extensions);
|
||||
this.locator = Locator.usingDirectory(directory);
|
||||
this.accordStaleReplicas = accordStaleReplicas;
|
||||
this.cmsMembership = cmsMembership;
|
||||
}
|
||||
|
||||
public Set<InetAddressAndPort> fullCMSMembers()
|
||||
|
|
@ -223,9 +228,10 @@ public class ClusterMetadata
|
|||
|
||||
if (fullCMSEndpoints == null)
|
||||
{
|
||||
if (schema.maybeGetKeyspaceMetadata(SchemaConstants.METADATA_KEYSPACE_NAME).isEmpty())
|
||||
return Collections.emptySet();
|
||||
this.fullCMSEndpoints = ImmutableSet.copyOf(placements.get(ReplicationParams.meta(this)).reads.byEndpoint().keySet());
|
||||
fullCMSEndpoints = ImmutableSet.copyOf(cmsMembership.fullMembers()
|
||||
.stream()
|
||||
.map(directory::endpoint)
|
||||
.collect(Collectors.toSet()));
|
||||
}
|
||||
return fullCMSEndpoints;
|
||||
}
|
||||
|
|
@ -235,13 +241,7 @@ public class ClusterMetadata
|
|||
if (epoch.isBefore(Epoch.FIRST))
|
||||
return Collections.emptySet();
|
||||
|
||||
if (fullCMSIds == null)
|
||||
{
|
||||
if (schema.maybeGetKeyspaceMetadata(SchemaConstants.METADATA_KEYSPACE_NAME).isEmpty())
|
||||
return Collections.emptySet();
|
||||
this.fullCMSIds = placements.get(ReplicationParams.meta(this)).reads.byEndpoint().keySet().stream().map(directory::peerId).collect(toImmutableSet());
|
||||
}
|
||||
return fullCMSIds;
|
||||
return cmsMembership.fullMembers();
|
||||
}
|
||||
|
||||
public EndpointsForRange fullCMSMembersAsReplicas()
|
||||
|
|
@ -251,9 +251,10 @@ public class ClusterMetadata
|
|||
|
||||
if (fullCMSReplicas == null)
|
||||
{
|
||||
if (schema.maybeGetKeyspaceMetadata(SchemaConstants.METADATA_KEYSPACE_NAME).isEmpty())
|
||||
return EndpointsForRange.empty(MetaStrategy.entireRange);
|
||||
fullCMSReplicas = placements.get(ReplicationParams.meta(this)).reads.forRange(MetaStrategy.entireRange).get();
|
||||
EndpointsForRange.Builder builder = EndpointsForRange.builder(MetaStrategy.entireRange);
|
||||
for (NodeId nodeId : fullCMSMemberIds())
|
||||
builder.add(MetaStrategy.replica(directory.endpoint(nodeId)));
|
||||
fullCMSReplicas = builder.build();
|
||||
}
|
||||
return fullCMSReplicas;
|
||||
}
|
||||
|
|
@ -291,7 +292,8 @@ public class ClusterMetadata
|
|||
capLastModified(inProgressSequences, epoch),
|
||||
capLastModified(consensusMigrationState, epoch),
|
||||
capLastModified(extensions, epoch),
|
||||
capLastModified(accordStaleReplicas, epoch));
|
||||
capLastModified(accordStaleReplicas, epoch),
|
||||
capLastModified(cmsMembership, epoch));
|
||||
}
|
||||
|
||||
public ClusterMetadata initializeClusterIdentifier(int clusterIdentifier)
|
||||
|
|
@ -314,7 +316,8 @@ public class ClusterMetadata
|
|||
inProgressSequences,
|
||||
consensusMigrationState,
|
||||
extensions,
|
||||
accordStaleReplicas);
|
||||
accordStaleReplicas,
|
||||
cmsMembership);
|
||||
}
|
||||
|
||||
private static Map<ExtensionKey<?,?>, ExtensionValue<?>> capLastModified(Map<ExtensionKey<?,?>, ExtensionValue<?>> original, Epoch maxEpoch)
|
||||
|
|
@ -495,6 +498,7 @@ public class ClusterMetadata
|
|||
private final Map<ExtensionKey<?, ?>, ExtensionValue<?>> extensions;
|
||||
private final Set<MetadataKey> modifiedKeys;
|
||||
private AccordStaleReplicas accordStaleReplicas;
|
||||
private CMSMembership cmsMembership;
|
||||
|
||||
private Transformer(ClusterMetadata metadata, Epoch epoch)
|
||||
{
|
||||
|
|
@ -637,6 +641,30 @@ public class ClusterMetadata
|
|||
return this;
|
||||
}
|
||||
|
||||
public Transformer startJoiningCMS(NodeId id)
|
||||
{
|
||||
cmsMembership = cmsMembership.startJoining(id);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Transformer finishJoiningCMS(NodeId id)
|
||||
{
|
||||
cmsMembership = cmsMembership.finishJoining(id);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Transformer cancelJoiningCMS(NodeId id)
|
||||
{
|
||||
cmsMembership = cmsMembership.cancelJoining(id);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Transformer leaveCMS(NodeId id)
|
||||
{
|
||||
cmsMembership = cmsMembership.leave(id);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Transformer with(DataPlacements placements)
|
||||
{
|
||||
this.placements = placements;
|
||||
|
|
@ -834,7 +862,8 @@ public class ClusterMetadata
|
|||
inProgressSequences,
|
||||
consensusMigrationState,
|
||||
extensions,
|
||||
accordStaleReplicas),
|
||||
accordStaleReplicas,
|
||||
cmsMembership),
|
||||
ImmutableSet.copyOf(modifiedKeys));
|
||||
}
|
||||
|
||||
|
|
@ -852,7 +881,8 @@ public class ClusterMetadata
|
|||
inProgressSequences,
|
||||
consensusMigrationState,
|
||||
extensions,
|
||||
accordStaleReplicas);
|
||||
accordStaleReplicas,
|
||||
cmsMembership);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -871,6 +901,7 @@ public class ClusterMetadata
|
|||
", inProgressSequences=" + inProgressSequences +
|
||||
", consensusMigrationState=" + consensusMigrationState +
|
||||
", extensions=" + extensions +
|
||||
", cmsMembership=" + cmsMembership +
|
||||
", modifiedKeys=" + modifiedKeys +
|
||||
'}';
|
||||
}
|
||||
|
|
@ -966,6 +997,9 @@ public class ClusterMetadata
|
|||
", placements=" + placements +
|
||||
", lockedRanges=" + lockedRanges +
|
||||
", consensusMigrationState=" + lockedRanges +
|
||||
", inProgressSequences=" + inProgressSequences +
|
||||
", extensions=" + extensions +
|
||||
", cmsMembership=" + cmsMembership +
|
||||
'}';
|
||||
}
|
||||
|
||||
|
|
@ -994,7 +1028,8 @@ public class ClusterMetadata
|
|||
inProgressSequences.equals(that.inProgressSequences) &&
|
||||
consensusMigrationState.equals(that.consensusMigrationState) &&
|
||||
accordStaleReplicas.equals(that.accordStaleReplicas) &&
|
||||
extensions.equals(that.extensions);
|
||||
extensions.equals(that.extensions) &&
|
||||
cmsMembership.equals(that.cmsMembership);
|
||||
}
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(ClusterMetadata.class);
|
||||
|
|
@ -1037,12 +1072,16 @@ public class ClusterMetadata
|
|||
{
|
||||
logger.warn("Extensions differ: {} != {}", extensions, other.extensions);
|
||||
}
|
||||
if (!cmsMembership.equals(other.cmsMembership))
|
||||
{
|
||||
logger.warn("CMS Membership differ: {} != {}", cmsMembership, other.cmsMembership);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return Objects.hash(epoch, schema, directory, tokenMap, placements, accordFastPath, lockedRanges, inProgressSequences, consensusMigrationState, accordStaleReplicas, extensions);
|
||||
return Objects.hash(epoch, schema, directory, tokenMap, placements, accordFastPath, lockedRanges, inProgressSequences, consensusMigrationState, accordStaleReplicas, extensions, cmsMembership);
|
||||
}
|
||||
|
||||
public static ClusterMetadata current()
|
||||
|
|
@ -1132,6 +1171,8 @@ public class ClusterMetadata
|
|||
assert key.valueType.isInstance(value);
|
||||
value.serialize(out, version);
|
||||
}
|
||||
if (version.isAtLeast(Version.V9))
|
||||
CMSMembership.serializer.serialize(metadata.cmsMembership, out, version);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -1188,6 +1229,11 @@ public class ClusterMetadata
|
|||
value.deserialize(in, version);
|
||||
extensions.put(key, value);
|
||||
}
|
||||
|
||||
CMSMembership cmsMembership = CMSMembership.EMPTY;
|
||||
if (version.isAtLeast(Version.V9))
|
||||
cmsMembership = CMSMembership.serializer.deserialize(in, version);
|
||||
|
||||
return new ClusterMetadata(clusterIdentifier,
|
||||
epoch,
|
||||
partitioner,
|
||||
|
|
@ -1200,7 +1246,8 @@ public class ClusterMetadata
|
|||
ips,
|
||||
consensusMigrationState,
|
||||
extensions,
|
||||
staleReplicas);
|
||||
staleReplicas,
|
||||
cmsMembership);
|
||||
}
|
||||
|
||||
private DistributedSchema deduplicateReplicationParams(DistributedSchema schema, DataPlacements placements)
|
||||
|
|
@ -1248,6 +1295,9 @@ public class ClusterMetadata
|
|||
size += LockedRanges.serializer.serializedSize(metadata.lockedRanges, version) +
|
||||
InProgressSequences.serializer.serializedSize(metadata.inProgressSequences, version);
|
||||
|
||||
if (version.isAtLeast(Version.V9))
|
||||
size += CMSMembership.serializer.serializedSize(metadata.cmsMembership, version);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -327,14 +327,15 @@ public class ClusterMetadataService
|
|||
DatabaseDescriptor.getPartitioner(),
|
||||
new DistributedSchema(keyspaces),
|
||||
Directory.EMPTY,
|
||||
new TokenMap(DatabaseDescriptor.getPartitioner()),
|
||||
DataPlacements.empty(),
|
||||
AccordFastPath.EMPTY,
|
||||
LockedRanges.EMPTY,
|
||||
InProgressSequences.EMPTY,
|
||||
ConsensusMigrationState.EMPTY,
|
||||
Collections.emptyMap(),
|
||||
AccordStaleReplicas.EMPTY);
|
||||
new TokenMap(DatabaseDescriptor.getPartitioner()),
|
||||
DataPlacements.empty(),
|
||||
AccordFastPath.EMPTY,
|
||||
LockedRanges.EMPTY,
|
||||
InProgressSequences.EMPTY,
|
||||
ConsensusMigrationState.EMPTY,
|
||||
Collections.emptyMap(),
|
||||
AccordStaleReplicas.EMPTY,
|
||||
CMSMembership.EMPTY);
|
||||
|
||||
|
||||
LocalLog.LogSpec logSpec = LocalLog.logSpec()
|
||||
|
|
@ -360,6 +361,24 @@ public class ClusterMetadataService
|
|||
ClusterMetadataService.setInstance(cms);
|
||||
}
|
||||
|
||||
@SuppressWarnings("resource")
|
||||
public static void initializeForClients()
|
||||
{
|
||||
if (instance != null)
|
||||
return;
|
||||
|
||||
ClusterMetadataService.setInstance(StubClusterMetadataService.forClientTools());
|
||||
}
|
||||
|
||||
public static void initializeForClients(DistributedSchema initialSchema)
|
||||
{
|
||||
if (instance != null)
|
||||
return;
|
||||
|
||||
|
||||
ClusterMetadataService.setInstance(StubClusterMetadataService.forClientTools(initialSchema));
|
||||
}
|
||||
|
||||
/*
|
||||
* Hook to be executed when the LocalLog is bootstrapped with the PreInitialize transformation. This is done on
|
||||
* the first CMS member to set up the initial replication and data placements for the metadata keyspace.
|
||||
|
|
@ -391,25 +410,8 @@ public class ClusterMetadataService
|
|||
};
|
||||
}
|
||||
// otherwise, this is a noop.
|
||||
return preInit -> {};
|
||||
}
|
||||
|
||||
@SuppressWarnings("resource")
|
||||
public static void initializeForClients()
|
||||
{
|
||||
if (instance != null)
|
||||
return;
|
||||
|
||||
ClusterMetadataService.setInstance(StubClusterMetadataService.forClientTools());
|
||||
}
|
||||
|
||||
public static void initializeForClients(DistributedSchema initialSchema)
|
||||
{
|
||||
if (instance != null)
|
||||
return;
|
||||
|
||||
|
||||
ClusterMetadataService.setInstance(StubClusterMetadataService.forClientTools(initialSchema));
|
||||
return preInit -> {
|
||||
};
|
||||
}
|
||||
|
||||
public boolean isCurrentMember(InetAddressAndPort peer)
|
||||
|
|
|
|||
|
|
@ -184,7 +184,8 @@ public class StubClusterMetadataService extends ClusterMetadataService
|
|||
InProgressSequences.EMPTY,
|
||||
ConsensusMigrationState.EMPTY,
|
||||
ImmutableMap.of(),
|
||||
AccordStaleReplicas.EMPTY);
|
||||
AccordStaleReplicas.EMPTY,
|
||||
CMSMembership.EMPTY);
|
||||
}
|
||||
return new StubClusterMetadataService(new UniformRangePlacement(),
|
||||
snapshots != null ? snapshots : MetadataSnapshots.NO_OP,
|
||||
|
|
|
|||
|
|
@ -58,6 +58,7 @@ import org.apache.cassandra.service.StorageService;
|
|||
import org.apache.cassandra.service.accord.topology.AccordFastPath;
|
||||
import org.apache.cassandra.service.accord.topology.AccordStaleReplicas;
|
||||
import org.apache.cassandra.service.consensus.migration.ConsensusMigrationState;
|
||||
import org.apache.cassandra.tcm.CMSMembership;
|
||||
import org.apache.cassandra.tcm.ClusterMetadata;
|
||||
import org.apache.cassandra.tcm.Epoch;
|
||||
import org.apache.cassandra.tcm.MultiStepOperation;
|
||||
|
|
@ -306,7 +307,8 @@ public class GossipHelper
|
|||
InProgressSequences.EMPTY,
|
||||
ConsensusMigrationState.EMPTY,
|
||||
Collections.emptyMap(),
|
||||
AccordStaleReplicas.EMPTY);
|
||||
AccordStaleReplicas.EMPTY,
|
||||
CMSMembership.EMPTY);
|
||||
}
|
||||
|
||||
public static ClusterMetadata fromEndpointStates(DistributedSchema schema, Map<InetAddressAndPort, EndpointState> epStates)
|
||||
|
|
@ -396,7 +398,8 @@ public class GossipHelper
|
|||
InProgressSequences.EMPTY,
|
||||
ConsensusMigrationState.EMPTY,
|
||||
extensions,
|
||||
AccordStaleReplicas.EMPTY);
|
||||
AccordStaleReplicas.EMPTY,
|
||||
CMSMembership.EMPTY);
|
||||
DataPlacements placements = new UniformRangePlacement().calculatePlacements(Epoch.UPGRADE_GOSSIP,
|
||||
forPlacementCalculation,
|
||||
schema.getKeyspaces());
|
||||
|
|
@ -411,7 +414,8 @@ public class GossipHelper
|
|||
InProgressSequences.EMPTY,
|
||||
ConsensusMigrationState.EMPTY,
|
||||
extensions,
|
||||
AccordStaleReplicas.EMPTY);
|
||||
AccordStaleReplicas.EMPTY,
|
||||
CMSMembership.EMPTY);
|
||||
}
|
||||
|
||||
public static boolean isValidForClusterMetadata(Map<InetAddressAndPort, EndpointState> epstates)
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ import static org.apache.cassandra.db.TypeSizes.sizeofUnsignedVInt;
|
|||
public class NodeVersion implements Comparable<NodeVersion>
|
||||
{
|
||||
public static final Serializer serializer = new Serializer();
|
||||
public static final Version CURRENT_METADATA_VERSION = Version.V8;
|
||||
public static final Version CURRENT_METADATA_VERSION = Version.V9;
|
||||
public static final NodeVersion CURRENT = new NodeVersion(new CassandraVersion(FBUtilities.getReleaseVersionString()), CURRENT_METADATA_VERSION);
|
||||
private static final CassandraVersion SINCE_VERSION = CassandraVersion.CASSANDRA_5_1;
|
||||
|
||||
|
|
|
|||
|
|
@ -38,13 +38,13 @@ public enum Version
|
|||
*/
|
||||
V0(0),
|
||||
/**
|
||||
* - Moved Partitioner in ClusterMetadata serializer to be the first field
|
||||
* - Added a counter to Directory serializer to keep track of NodeIds
|
||||
* - Moved Partitioner in ClusterMetadata serializer to be the first field
|
||||
* - Added a counter to Directory serializer to keep track of NodeIds
|
||||
*/
|
||||
V1(1),
|
||||
/**
|
||||
* - Added version to PlacementForRange serializer
|
||||
* - Serialize MemtableParams when serializing TableParams
|
||||
* - Added version to PlacementForRange serializer
|
||||
* - Serialize MemtableParams when serializing TableParams
|
||||
*/
|
||||
V2(2),
|
||||
/**
|
||||
|
|
@ -78,6 +78,10 @@ public enum Version
|
|||
* - Comments and security labels for schema elements (keyspaces, tables, columns, UDTs, and UDT fields)
|
||||
*/
|
||||
V8(8),
|
||||
/**
|
||||
* - DataPlacements don't include MetaStrategy, replaced by ClusterMetadata.CMSMembership
|
||||
*/
|
||||
V9(9),
|
||||
|
||||
UNKNOWN(Integer.MAX_VALUE);
|
||||
|
||||
|
|
@ -95,6 +99,7 @@ public enum Version
|
|||
}
|
||||
|
||||
private final int version;
|
||||
|
||||
Version(int version)
|
||||
{
|
||||
this.version = version;
|
||||
|
|
|
|||
|
|
@ -64,6 +64,7 @@ import org.apache.cassandra.service.accord.topology.AccordFastPath;
|
|||
import org.apache.cassandra.service.accord.topology.AccordStaleReplicas;
|
||||
import org.apache.cassandra.service.consensus.migration.ConsensusMigrationState;
|
||||
import org.apache.cassandra.tcm.AtomicLongBackedProcessor;
|
||||
import org.apache.cassandra.tcm.CMSMembership;
|
||||
import org.apache.cassandra.tcm.ClusterMetadata;
|
||||
import org.apache.cassandra.tcm.ClusterMetadataService;
|
||||
import org.apache.cassandra.tcm.Commit;
|
||||
|
|
@ -169,7 +170,8 @@ public class ClusterMetadataTestHelper
|
|||
InProgressSequences.EMPTY,
|
||||
ConsensusMigrationState.EMPTY,
|
||||
ImmutableMap.of(),
|
||||
AccordStaleReplicas.EMPTY);
|
||||
AccordStaleReplicas.EMPTY,
|
||||
CMSMembership.EMPTY);
|
||||
}
|
||||
|
||||
public static ClusterMetadata minimalForTesting(IPartitioner partitioner)
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ import org.apache.cassandra.schema.DistributedSchema;
|
|||
import org.apache.cassandra.service.accord.topology.AccordFastPath;
|
||||
import org.apache.cassandra.service.accord.topology.AccordStaleReplicas;
|
||||
import org.apache.cassandra.service.consensus.migration.ConsensusMigrationState;
|
||||
import org.apache.cassandra.tcm.CMSMembership;
|
||||
import org.apache.cassandra.tcm.ClusterMetadata;
|
||||
import org.apache.cassandra.tcm.Epoch;
|
||||
import org.apache.cassandra.tcm.membership.Directory;
|
||||
|
|
@ -96,7 +97,8 @@ public class MetaStrategyTest
|
|||
InProgressSequences.EMPTY,
|
||||
ConsensusMigrationState.EMPTY,
|
||||
ImmutableMap.of(),
|
||||
AccordStaleReplicas.EMPTY);
|
||||
AccordStaleReplicas.EMPTY,
|
||||
CMSMembership.EMPTY);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@ import org.apache.cassandra.schema.SchemaConstants;
|
|||
import org.apache.cassandra.service.accord.topology.AccordFastPath;
|
||||
import org.apache.cassandra.service.accord.topology.AccordStaleReplicas;
|
||||
import org.apache.cassandra.service.consensus.migration.ConsensusMigrationState;
|
||||
import org.apache.cassandra.tcm.CMSMembership;
|
||||
import org.apache.cassandra.tcm.ClusterMetadata;
|
||||
import org.apache.cassandra.tcm.ClusterMetadataService;
|
||||
import org.apache.cassandra.tcm.Epoch;
|
||||
|
|
@ -110,7 +111,8 @@ public class CMSOfflineToolTest extends OfflineToolUtils
|
|||
InProgressSequences.EMPTY,
|
||||
ConsensusMigrationState.EMPTY,
|
||||
ImmutableMap.of(),
|
||||
AccordStaleReplicas.EMPTY);
|
||||
AccordStaleReplicas.EMPTY,
|
||||
CMSMembership.EMPTY);
|
||||
}
|
||||
|
||||
@Before
|
||||
|
|
|
|||
|
|
@ -140,6 +140,7 @@ import org.apache.cassandra.service.accord.topology.SimpleFastPathStrategy;
|
|||
import org.apache.cassandra.service.accord.topology.UpFastPathStrategy;
|
||||
import org.apache.cassandra.service.consensus.TransactionalMode;
|
||||
import org.apache.cassandra.service.consensus.migration.ConsensusMigrationState;
|
||||
import org.apache.cassandra.tcm.CMSMembership;
|
||||
import org.apache.cassandra.tcm.ClusterMetadata;
|
||||
import org.apache.cassandra.tcm.Epoch;
|
||||
import org.apache.cassandra.tcm.extensions.ExtensionKey;
|
||||
|
|
@ -1955,7 +1956,8 @@ public final class CassandraGenerators
|
|||
ConsensusMigrationState consensusMigrationState = ConsensusMigrationState.EMPTY;
|
||||
Map<ExtensionKey<?, ?>, ExtensionValue<?>> extensions = ImmutableMap.of();
|
||||
AccordStaleReplicas accordStaleReplicas = accordStaleReplicasGen.generate(rnd);
|
||||
return new ClusterMetadata(epoch, partitioner, schema, directory, tokenMap, placements, accordFastPath, lockedRanges, inProgressSequences, consensusMigrationState, extensions, accordStaleReplicas);
|
||||
CMSMembership cms = CMSMembership.EMPTY;
|
||||
return new ClusterMetadata(epoch, partitioner, schema, directory, tokenMap, placements, accordFastPath, lockedRanges, inProgressSequences, consensusMigrationState, extensions, accordStaleReplicas, cms);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue