com.datastax.oss.driver.internal.core.metadata.DefaultNode Maven / Gradle / Ivy
The newest version!
/*
* 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 com.datastax.oss.driver.internal.core.metadata;
import com.datastax.oss.driver.api.core.Version;
import com.datastax.oss.driver.api.core.loadbalancing.NodeDistance;
import com.datastax.oss.driver.api.core.metadata.EndPoint;
import com.datastax.oss.driver.api.core.metadata.Node;
import com.datastax.oss.driver.api.core.metadata.NodeState;
import com.datastax.oss.driver.internal.core.context.InternalDriverContext;
import com.datastax.oss.driver.internal.core.metrics.NodeMetricUpdater;
import com.datastax.oss.driver.internal.core.metrics.NoopNodeMetricUpdater;
import edu.umd.cs.findbugs.annotations.NonNull;
import edu.umd.cs.findbugs.annotations.Nullable;
import java.io.Serializable;
import java.net.InetSocketAddress;
import java.util.Collections;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.UUID;
import net.jcip.annotations.ThreadSafe;
/**
* Implementation note: all the mutable state in this class is read concurrently, but only mutated
* from {@link MetadataManager}'s admin thread.
*/
@ThreadSafe
public class DefaultNode implements Node, Serializable {
private static final long serialVersionUID = 1;
private volatile EndPoint endPoint;
// A deserialized node is not attached to a session anymore, so we don't need to retain this
private transient volatile NodeMetricUpdater metricUpdater;
volatile InetSocketAddress broadcastRpcAddress;
volatile InetSocketAddress broadcastAddress;
volatile InetSocketAddress listenAddress;
volatile String datacenter;
volatile String rack;
volatile Version cassandraVersion;
// Keep a copy of the raw tokens, to detect if they have changed when we refresh the node
volatile Set rawTokens;
volatile Map extras;
volatile UUID hostId;
volatile UUID schemaVersion;
// These 4 fields are read concurrently, but only mutated on NodeStateManager's admin thread
volatile NodeState state;
volatile int openConnections;
volatile int reconnections;
volatile long upSinceMillis;
volatile NodeDistance distance;
public DefaultNode(EndPoint endPoint, InternalDriverContext context) {
this.endPoint = endPoint;
this.state = NodeState.UNKNOWN;
this.distance = NodeDistance.IGNORED;
this.rawTokens = Collections.emptySet();
this.extras = Collections.emptyMap();
// We leak a reference to a partially constructed object (this), but in practice this won't be a
// problem because the node updater only needs the connect address to initialize.
this.metricUpdater = context.getMetricsFactory().newNodeUpdater(this);
this.upSinceMillis = -1;
}
@NonNull
@Override
public EndPoint getEndPoint() {
return endPoint;
}
public void setEndPoint(@NonNull EndPoint newEndPoint, @NonNull InternalDriverContext context) {
if (!newEndPoint.equals(endPoint)) {
endPoint = newEndPoint;
// The endpoint is also used to build metric names, so make sure they get updated
NodeMetricUpdater previousMetricUpdater = metricUpdater;
if (!(previousMetricUpdater instanceof NoopNodeMetricUpdater)) {
metricUpdater = context.getMetricsFactory().newNodeUpdater(this);
}
}
}
@NonNull
@Override
public Optional getBroadcastRpcAddress() {
return Optional.ofNullable(broadcastRpcAddress);
}
@NonNull
@Override
public Optional getBroadcastAddress() {
return Optional.ofNullable(broadcastAddress);
}
@NonNull
@Override
public Optional getListenAddress() {
return Optional.ofNullable(listenAddress);
}
@Nullable
@Override
public String getDatacenter() {
return datacenter;
}
@Nullable
@Override
public String getRack() {
return rack;
}
@Nullable
@Override
public Version getCassandraVersion() {
return cassandraVersion;
}
@Nullable
@Override
public UUID getHostId() {
return hostId;
}
@Nullable
@Override
public UUID getSchemaVersion() {
return schemaVersion;
}
@NonNull
@Override
public Map getExtras() {
return extras;
}
@NonNull
@Override
public NodeState getState() {
return state;
}
@Override
public long getUpSinceMillis() {
return upSinceMillis;
}
@Override
public int getOpenConnections() {
return openConnections;
}
@Override
public boolean isReconnecting() {
return reconnections > 0;
}
@NonNull
@Override
public NodeDistance getDistance() {
return distance;
}
public NodeMetricUpdater getMetricUpdater() {
return metricUpdater;
}
@Override
public String toString() {
// Include the hash code because this class uses reference equality
return String.format(
"Node(endPoint=%s, hostId=%s, hashCode=%x)", getEndPoint(), getHostId(), hashCode());
}
/** Note: deliberately not exposed by the public interface. */
public Set getRawTokens() {
return rawTokens;
}
}