/*
 * Copyright DataStax, Inc.
 *
 * Licensed 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 MetadataManager's admin thread.
/** * 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<String> rawTokens; volatile Map<String, Object> 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<InetSocketAddress> getBroadcastRpcAddress() { return Optional.ofNullable(broadcastRpcAddress); } @NonNull @Override public Optional<InetSocketAddress> getBroadcastAddress() { return Optional.ofNullable(broadcastAddress); } @NonNull @Override public Optional<InetSocketAddress> 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<String, Object> 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.
/** Note: deliberately not exposed by the public interface. */
public Set<String> getRawTokens() { return rawTokens; } }