org.apache.cassandra.locator.Endpoints Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of cassandra-all Show documentation
Show all versions of cassandra-all Show documentation
The Apache Cassandra Project develops a highly scalable second-generation distributed database, bringing together Dynamo's fully distributed design and Bigtable's ColumnFamily-based data model.
/*
* 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.locator;
import org.apache.cassandra.locator.ReplicaCollection.Builder.Conflict;
import org.apache.cassandra.utils.FBUtilities;
import java.util.AbstractList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import com.google.common.collect.Lists;
/**
* A collection of Endpoints for a given ring position. This will typically reside in a ReplicaLayout,
* representing some subset of the endpoints for the Token or Range
* @param The concrete type of Endpoints, that will be returned by the modifying methods
*/
public abstract class Endpoints> extends AbstractReplicaCollection
{
static ReplicaMap endpointMap(ReplicaList list) { return new ReplicaMap<>(list, Replica::endpoint); }
static final ReplicaMap EMPTY_MAP = endpointMap(EMPTY_LIST);
// volatile not needed, as has only final members,
// besides (transitively) those that cache objects that themselves have only final members
ReplicaMap byEndpoint;
Endpoints(ReplicaList list, ReplicaMap byEndpoint)
{
super(list);
this.byEndpoint = byEndpoint;
}
@Override
public Set endpoints()
{
return byEndpoint().keySet();
}
public List endpointList()
{
return new AbstractList()
{
public InetAddressAndPort get(int index)
{
return list.get(index).endpoint();
}
public int size()
{
return list.size;
}
};
}
public Map byEndpoint()
{
ReplicaMap map = byEndpoint;
if (map == null)
byEndpoint = map = endpointMap(list);
return map;
}
@Override
public boolean contains(Replica replica)
{
return replica != null
&& Objects.equals(
byEndpoint().get(replica.endpoint()),
replica);
}
public E withoutSelf()
{
InetAddressAndPort self = FBUtilities.getBroadcastAddressAndPort();
return filter(r -> !self.equals(r.endpoint()));
}
public Replica selfIfPresent()
{
InetAddressAndPort self = FBUtilities.getBroadcastAddressAndPort();
return byEndpoint().get(self);
}
/**
* @return a collection without the provided endpoints, otherwise in the same order as this collection
*/
public E without(Set remove)
{
return filter(r -> !remove.contains(r.endpoint()));
}
/**
* @return a collection with only the provided endpoints (ignoring any not present), otherwise in the same order as this collection
*/
public E keep(Set keep)
{
return filter(r -> keep.contains(r.endpoint()));
}
/**
* @return a collection containing the Replica from this collection for the provided endpoints, in the order of the provided endpoints
*/
public E select(Iterable endpoints, boolean ignoreMissing)
{
Builder copy = newBuilder(
endpoints instanceof Collection>
? ((Collection) endpoints).size()
: size()
);
Map byEndpoint = byEndpoint();
for (InetAddressAndPort endpoint : endpoints)
{
Replica select = byEndpoint.get(endpoint);
if (select == null)
{
if (!ignoreMissing)
throw new IllegalArgumentException(endpoint + " is not present in " + this);
continue;
}
copy.add(select, Builder.Conflict.DUPLICATE);
}
return copy.build();
}
/**
* Care must be taken to ensure no conflicting ranges occur in pending and natural.
* Conflicts can occur for two reasons:
* 1) due to lack of isolation when reading pending/natural
* 2) because a movement that changes the type of replication from transient to full must be handled
* differently for reads and writes (with the reader treating it as transient, and writer as full)
*
* The method {@link ReplicaLayout#haveWriteConflicts} can be used to detect and resolve any issues
*/
public static > E concat(E natural, E pending)
{
return AbstractReplicaCollection.concat(natural, pending, Conflict.NONE);
}
public static > E append(E replicas, Replica extraReplica)
{
Builder builder = replicas.newBuilder(replicas.size() + 1);
builder.addAll(replicas);
builder.add(extraReplica, Conflict.NONE);
return builder.build();
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy