use of org.apache.cassandra.locator.InetAddressAndPort in project cassandra by apache.
the class GossipDigestAck2Serializer method serialize.
public void serialize(GossipDigestAck2 ack2, DataOutputPlus out, int version) throws IOException {
out.writeInt(ack2.epStateMap.size());
for (Map.Entry<InetAddressAndPort, EndpointState> entry : ack2.epStateMap.entrySet()) {
InetAddressAndPort ep = entry.getKey();
inetAddressAndPortSerializer.serialize(ep, out, version);
EndpointState.serializer.serialize(entry.getValue(), out, version);
}
}
use of org.apache.cassandra.locator.InetAddressAndPort in project cassandra by apache.
the class StartupClusterConnectivityChecker method execute.
/**
* @param peers The currently known peers in the cluster; argument is not modified.
* @param getDatacenterSource A function for mapping peers to their datacenter.
* @return true if the requested percentage of peers are marked ALIVE in gossip and have their connections opened;
* else false.
*/
public boolean execute(Set<InetAddressAndPort> peers, Function<InetAddressAndPort, String> getDatacenterSource) {
if (peers == null || this.timeoutNanos < 0)
return true;
// make a copy of the set, to avoid mucking with the input (in case it's a sensitive collection)
peers = new HashSet<>(peers);
InetAddressAndPort localAddress = FBUtilities.getBroadcastAddressAndPort();
String localDc = getDatacenterSource.apply(localAddress);
peers.remove(localAddress);
if (peers.isEmpty())
return true;
// make a copy of the datacenter mapping (in case gossip updates happen during this method or some such)
Map<InetAddressAndPort, String> peerToDatacenter = new HashMap<>();
SetMultimap<String, InetAddressAndPort> datacenterToPeers = HashMultimap.create();
for (InetAddressAndPort peer : peers) {
String datacenter = getDatacenterSource.apply(peer);
peerToDatacenter.put(peer, datacenter);
datacenterToPeers.put(datacenter, peer);
}
// on the remaining local datacenter.
if (!blockForRemoteDcs) {
datacenterToPeers.keySet().retainAll(Collections.singleton(localDc));
logger.info("Blocking coordination until only a single peer is DOWN in the local datacenter, timeout={}s", TimeUnit.NANOSECONDS.toSeconds(timeoutNanos));
} else {
logger.info("Blocking coordination until only a single peer is DOWN in each datacenter, timeout={}s", TimeUnit.NANOSECONDS.toSeconds(timeoutNanos));
}
// The threshold is 3 because for each peer we want to have 3 acks,
// one for small message connection, one for large message connnection and one for alive event from gossip.
AckMap acks = new AckMap(3, peers);
Map<String, CountDownLatch> dcToRemainingPeers = new HashMap<>(datacenterToPeers.size());
for (String datacenter : datacenterToPeers.keys()) {
dcToRemainingPeers.put(datacenter, newCountDownLatch(Math.max(datacenterToPeers.get(datacenter).size() - 1, 0)));
}
long startNanos = nanoTime();
// set up a listener to react to new nodes becoming alive (in gossip), and account for all the nodes that are already alive
Set<InetAddressAndPort> alivePeers = Collections.newSetFromMap(new ConcurrentHashMap<>());
AliveListener listener = new AliveListener(alivePeers, dcToRemainingPeers, acks, peerToDatacenter::get);
Gossiper.instance.register(listener);
// send out a ping message to open up the non-gossip connections to all peers. Note that this sends the
// ping messages to _all_ peers, not just the ones we block for in dcToRemainingPeers.
sendPingMessages(peers, dcToRemainingPeers, acks, peerToDatacenter::get);
for (InetAddressAndPort peer : peers) {
if (Gossiper.instance.isAlive(peer) && alivePeers.add(peer) && acks.incrementAndCheck(peer)) {
String datacenter = peerToDatacenter.get(peer);
// We have to check because we might only have the local DC in the map
if (dcToRemainingPeers.containsKey(datacenter))
dcToRemainingPeers.get(datacenter).decrement();
}
}
boolean succeeded = true;
for (CountDownLatch countDownLatch : dcToRemainingPeers.values()) {
long remainingNanos = Math.max(1, timeoutNanos - (nanoTime() - startNanos));
// noinspection UnstableApiUsage
succeeded &= countDownLatch.awaitUninterruptibly(remainingNanos, TimeUnit.NANOSECONDS);
}
Gossiper.instance.unregister(listener);
if (succeeded) {
logger.info("Ensured sufficient healthy connections with {} after {} milliseconds", dcToRemainingPeers.keySet(), TimeUnit.NANOSECONDS.toMillis(nanoTime() - startNanos));
} else {
// dc -> missing peer host addresses
Map<String, List<String>> peersDown = acks.getMissingPeers().stream().collect(groupingBy(peer -> {
String dc = peerToDatacenter.get(peer);
if (dc != null)
return dc;
return StringUtils.defaultString(getDatacenterSource.apply(peer), "unknown");
}, mapping(InetAddressAndPort::getHostAddressAndPort, toList())));
logger.warn("Timed out after {} milliseconds, was waiting for remaining peers to connect: {}", TimeUnit.NANOSECONDS.toMillis(nanoTime() - startNanos), peersDown);
}
return succeeded;
}
use of org.apache.cassandra.locator.InetAddressAndPort in project cassandra by apache.
the class StartupClusterConnectivityChecker method sendPingMessages.
/**
* Sends a "connection warmup" message to each peer in the collection, on every {@link ConnectionType}
* used for internode messaging (that is not gossip).
*/
private void sendPingMessages(Set<InetAddressAndPort> peers, Map<String, CountDownLatch> dcToRemainingPeers, AckMap acks, Function<InetAddressAndPort, String> getDatacenter) {
RequestCallback responseHandler = msg -> {
if (acks.incrementAndCheck(msg.from())) {
String datacenter = getDatacenter.apply(msg.from());
// We have to check because we might only have the local DC in the map
if (dcToRemainingPeers.containsKey(datacenter))
dcToRemainingPeers.get(datacenter).decrement();
}
};
Message<PingRequest> small = Message.out(PING_REQ, PingRequest.forSmall);
Message<PingRequest> large = Message.out(PING_REQ, PingRequest.forLarge);
for (InetAddressAndPort peer : peers) {
MessagingService.instance().sendWithCallback(small, peer, responseHandler, SMALL_MESSAGES);
MessagingService.instance().sendWithCallback(large, peer, responseHandler, LARGE_MESSAGES);
}
}
use of org.apache.cassandra.locator.InetAddressAndPort in project cassandra by apache.
the class Message method outWithParam.
private static <T> Message<T> outWithParam(long id, Verb verb, long expiresAtNanos, T payload, int flags, ParamType paramType, Object paramValue) {
if (payload == null)
throw new IllegalArgumentException();
InetAddressAndPort from = FBUtilities.getBroadcastAddressAndPort();
long createdAtNanos = approxTime.now();
if (expiresAtNanos == 0)
expiresAtNanos = verb.expiresAtNanos(createdAtNanos);
return new Message<>(new Header(id, verb, from, createdAtNanos, expiresAtNanos, flags, buildParams(paramType, paramValue)), payload);
}
use of org.apache.cassandra.locator.InetAddressAndPort in project cassandra by apache.
the class InboundConnectionInitiator method bind.
/**
* Create a {@link Channel} that listens on the {@code localAddr}. This method will block while trying to bind to the address,
* but it does not make a remote call.
*/
private static ChannelFuture bind(Initializer initializer) throws ConfigurationException {
logger.info("Listening on {}", initializer.settings);
ServerBootstrap bootstrap = initializer.settings.socketFactory.newServerBootstrap().option(ChannelOption.SO_BACKLOG, 1 << 9).option(ChannelOption.ALLOCATOR, GlobalBufferPoolAllocator.instance).option(ChannelOption.SO_REUSEADDR, true).childHandler(initializer);
int socketReceiveBufferSizeInBytes = initializer.settings.socketReceiveBufferSizeInBytes;
if (socketReceiveBufferSizeInBytes > 0)
bootstrap.childOption(ChannelOption.SO_RCVBUF, socketReceiveBufferSizeInBytes);
InetAddressAndPort bind = initializer.settings.bindAddress;
ChannelFuture channelFuture = bootstrap.bind(new InetSocketAddress(bind.getAddress(), bind.getPort()));
if (!channelFuture.awaitUninterruptibly().isSuccess()) {
if (channelFuture.channel().isOpen())
channelFuture.channel().close();
Throwable failedChannelCause = channelFuture.cause();
String causeString = "";
if (failedChannelCause != null && failedChannelCause.getMessage() != null)
causeString = failedChannelCause.getMessage();
if (causeString.contains("in use")) {
throw new ConfigurationException(bind + " is in use by another process. Change listen_address:storage_port " + "in cassandra.yaml to values that do not conflict with other services");
} else if (causeString.contains("cannot assign requested address")) {
throw new ConfigurationException("Unable to bind to address " + bind + ". Set listen_address in cassandra.yaml to an interface you can bind to, e.g., your private IP address on EC2");
} else {
throw new ConfigurationException("failed to bind to: " + bind, failedChannelCause);
}
}
return channelFuture;
}
Aggregations