com.mongodb.connection.ServerDescription Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of mongo-java-driver Show documentation
Show all versions of mongo-java-driver Show documentation
The MongoDB Java Driver uber-artifact, containing mongodb-driver, mongodb-driver-core, and bson
The newest version!
/*
* Copyright (c) 2008-2014 MongoDB, 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.mongodb.connection;
import com.mongodb.ServerAddress;
import com.mongodb.TagSet;
import com.mongodb.annotations.Immutable;
import com.mongodb.annotations.NotThreadSafe;
import org.bson.types.ObjectId;
import java.text.DecimalFormat;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import static com.mongodb.assertions.Assertions.notNull;
import static com.mongodb.connection.ServerConnectionState.CONNECTED;
import static com.mongodb.connection.ServerType.REPLICA_SET_PRIMARY;
import static com.mongodb.connection.ServerType.REPLICA_SET_SECONDARY;
import static com.mongodb.connection.ServerType.SHARD_ROUTER;
import static com.mongodb.connection.ServerType.STANDALONE;
import static com.mongodb.connection.ServerType.UNKNOWN;
/**
* Immutable snapshot state of a server.
*
* @since 3.0
*/
@Immutable
public class ServerDescription {
static final int MIN_DRIVER_WIRE_VERSION = 0;
static final int MAX_DRIVER_WIRE_VERSION = 3;
private static final int DEFAULT_MAX_DOCUMENT_SIZE = 0x1000000; // 16MB
private final ServerAddress address;
private final ServerType type;
private final String canonicalAddress;
private final Set hosts;
private final Set passives;
private final Set arbiters;
private final String primary;
private final int maxDocumentSize;
private final TagSet tagSet;
private final String setName;
private final long roundTripTimeNanos;
private final boolean ok;
private final ServerConnectionState state;
private final ServerVersion version;
private final int minWireVersion;
private final int maxWireVersion;
private final ObjectId electionId;
private final Throwable exception;
/**
* Gets a Builder for creating a new ServerDescription instance.
*
* @return a new Builder for ServerDescription.
*/
public static Builder builder() {
return new Builder();
}
/**
* Gets the string representing the host name and port that this member of a replica set was configured with,
* e.g. {@code "somehost:27019"}. This is typically derived from the "me" field from the "isMaster" command response.
*
* @return the host name and port that this replica set member is configured with.
*/
public String getCanonicalAddress() {
return canonicalAddress;
}
/**
* A builder for creating ServerDescription.
*/
@NotThreadSafe
public static class Builder {
private ServerAddress address;
private ServerType type = UNKNOWN;
private String canonicalAddress;
private Set hosts = Collections.emptySet();
private Set passives = Collections.emptySet();
private Set arbiters = Collections.emptySet();
private String primary;
private int maxDocumentSize = DEFAULT_MAX_DOCUMENT_SIZE;
private TagSet tagSet = new TagSet();
private String setName;
private long roundTripTimeNanos;
private boolean ok;
private ServerConnectionState state;
private ServerVersion version = new ServerVersion();
private int minWireVersion = 0;
private int maxWireVersion = 0;
private ObjectId electionId;
private Throwable exception;
/**
* Sets the address of the server.
*
* @param address the address of the server
* @return this
*/
public Builder address(final ServerAddress address) {
this.address = address;
return this;
}
/**
* Sets the canonical host name and port of this server. This is typically derived from the "me" field contained in the "isMaster"
* command. response.
*
* @param canonicalAddress the host name and port as a string
*
* @return this
*/
public Builder canonicalAddress(final String canonicalAddress) {
this.canonicalAddress = canonicalAddress;
return this;
}
/**
* Sets the type of the server, for example whether it's a standalone or in a replica set.
*
* @param type the Server type
* @return this
*/
public Builder type(final ServerType type) {
this.type = notNull("type", type);
return this;
}
/**
* Sets all members of the replica set that are neither hidden, passive, nor arbiters.
*
* @param hosts A Set of strings in the format of "[hostname]:[port]" that contains all members of the replica set that are neither
* hidden, passive, nor arbiters.
* @return this
*/
public Builder hosts(final Set hosts) {
this.hosts = hosts == null ? Collections.emptySet() : Collections.unmodifiableSet(new HashSet(hosts));
return this;
}
/**
* Sets the passive members of the replica set.
*
* @param passives A Set of strings in the format of "[hostname]:[port]" listing all members of the replica set which have a
* priority of 0.
* @return this
*/
public Builder passives(final Set passives) {
this.passives = passives == null ? Collections.emptySet() : Collections.unmodifiableSet(new HashSet(passives));
return this;
}
/**
* Sets the arbiters in the replica set
*
* @param arbiters A Set of strings in the format of "[hostname]:[port]" containing all members of the replica set that are
* arbiters.
* @return this
*/
public Builder arbiters(final Set arbiters) {
this.arbiters = arbiters == null ? Collections.emptySet() : Collections.unmodifiableSet(new HashSet(arbiters));
return this;
}
/**
* Sets the address of the current primary in the replica set
*
* @param primary A string in the format of "[hostname]:[port]" listing the current primary member of the replica set.
* @return this
*/
public Builder primary(final String primary) {
this.primary = primary;
return this;
}
/**
* The maximum permitted size of a BSON object in bytes for this mongod process. Defaults to 16MB.
*
* @param maxDocumentSize the maximum size a document can be
* @return this
*/
public Builder maxDocumentSize(final int maxDocumentSize) {
this.maxDocumentSize = maxDocumentSize;
return this;
}
/**
* A set of any tags assigned to this member.
*
* @param tagSet a TagSet with all the tags for this server.
* @return this
*/
public Builder tagSet(final TagSet tagSet) {
this.tagSet = tagSet == null ? new TagSet() : tagSet;
return this;
}
/**
* Set the time it took to make the round trip for requesting this information from the server
*
* @param roundTripTime the time taken
* @param timeUnit the units of the time taken
* @return this
*/
public Builder roundTripTime(final long roundTripTime, final TimeUnit timeUnit) {
this.roundTripTimeNanos = timeUnit.toNanos(roundTripTime);
return this;
}
/**
* Sets the name of the replica set
*
* @param setName the name of the replica set
* @return this
*/
public Builder setName(final String setName) {
this.setName = setName;
return this;
}
/**
* The isOK() result from requesting this information from MongoDB
*
* @param ok true if the request executed correctly
* @return this
*/
public Builder ok(final boolean ok) {
this.ok = ok;
return this;
}
/**
* The current state of the connection to the server.
*
* @param state ServerConnectionState representing whether the server has been successfully connected to
* @return this
*/
public Builder state(final ServerConnectionState state) {
this.state = state;
return this;
}
/**
* Sets the server version
*
* @param version a ServerVersion representing which version of MongoDB is running on this server
* @return this
*/
public Builder version(final ServerVersion version) {
notNull("version", version);
this.version = version;
return this;
}
/**
* The earliest version of the wire protocol that this MongoDB server is capable of using to communicate with clients.
*
* @param minWireVersion the minimum protocol version supported by this server
* @return this
* @mongodb.server.release 2.6
*/
public Builder minWireVersion(final int minWireVersion) {
this.minWireVersion = minWireVersion;
return this;
}
/**
* The latest version of the wire protocol that this MongoDB server is capable of using to communicate with clients.
*
* @param maxWireVersion the maximum protocol version supported by this server
* @return this
* @mongodb.server.release 2.6
*/
public Builder maxWireVersion(final int maxWireVersion) {
this.maxWireVersion = maxWireVersion;
return this;
}
/**
* Sets the electionId reported by this server.
*
* @param electionId the electionId
* @return this
*/
public Builder electionId(final ObjectId electionId) {
this.electionId = electionId;
return this;
}
/**
* Sets the exception thrown while attempting to determine the server description.
*
* @param exception the exception
* @return this
*/
public Builder exception(final Throwable exception) {
this.exception = exception;
return this;
}
/**
* Create a new ServerDescription from the settings in this builder.
*
* @return a new server description
*/
public ServerDescription build() {
return new ServerDescription(this);
}
}
/**
* Return whether the server is compatible with the driver. An incompatible server is one that has a min wire version greater that the
* driver's max wire version or a max wire version less than the driver's min wire version.
*
* @return true if the server is compatible with the driver.
*/
public boolean isCompatibleWithDriver() {
if (!ok) {
return true;
}
if (minWireVersion > MAX_DRIVER_WIRE_VERSION) {
return false;
}
if (maxWireVersion < MIN_DRIVER_WIRE_VERSION) {
return false;
}
return true;
}
/**
* Get the default maximum document size.
*
* @return the default maximum document size
*/
public static int getDefaultMaxDocumentSize() {
return DEFAULT_MAX_DOCUMENT_SIZE;
}
/**
* Get the default minimum wire version
*
* @return the default minimum wire version
*/
public static int getDefaultMinWireVersion() {
return 0;
}
/**
* Get the default maximum wire version
*
* @return the default maximum wire version
*/
public static int getDefaultMaxWireVersion() {
return 0;
}
/**
* Gets the address of this server
*
* @return a ServerAddress containing the details of the address of this server.
*/
public ServerAddress getAddress() {
return address;
}
/**
* Gets whether this server is a replica set member.
*
* @return true if this server is part of a replica set
*/
public boolean isReplicaSetMember() {
return type.getClusterType() == ClusterType.REPLICA_SET;
}
/**
* Gets whether this is a server that is the entry point to a sharded instance of MongoDB.
*
* @return true if this server is a mongos instance
*/
public boolean isShardRouter() {
return type == SHARD_ROUTER;
}
/**
* Gets whether this is part of a replica set/sharded system, or is a single server.
*
* @return true if this is a single server
*/
public boolean isStandAlone() {
return type == STANDALONE;
}
/**
* Returns whether this can be treated as a primary server.
*
* @return true if this server is the primary in a replica set, is a mongos, or is a single standalone server
*/
public boolean isPrimary() {
return ok && (type == REPLICA_SET_PRIMARY || type == SHARD_ROUTER || type == STANDALONE);
}
/**
* Returns whether this can be treated as a secondary server.
*
* @return true if this server is a secondary in a replica set, is a mongos, or is a single standalone server
*/
public boolean isSecondary() {
return ok && (type == REPLICA_SET_SECONDARY || type == SHARD_ROUTER || type == STANDALONE);
}
/**
* Get a Set of strings in the format of "[hostname]:[port]" that contains all members of the replica set that are neither hidden,
* passive, nor arbiters.
*
* @return all members of the replica set that are neither hidden, passive, nor arbiters.
*/
public Set getHosts() {
return hosts;
}
/**
* Gets the passive members of the replica set.
*
* @return A set of strings in the format of "[hostname]:[port]" listing all members of the replica set which have a priority of 0.
*/
public Set getPassives() {
return passives;
}
/**
* Gets the arbiters in the replica set
*
* @return A Set of strings in the format of "[hostname]:[port]" containing all members of the replica set that are arbiters.
*/
public Set getArbiters() {
return arbiters;
}
/**
* Gets the address of the current primary in the replica set
*
* @return A string in the format of "[hostname]:[port]" listing the current primary member of the replica set.
*/
public String getPrimary() {
return primary;
}
/**
* The maximum permitted size of a BSON object in bytes for this mongod process. Defaults to 16MB.
*
* @return the maximum size a document can be
*/
public int getMaxDocumentSize() {
return maxDocumentSize;
}
/**
* A set of all tags assigned to this member.
*
* @return a TagSet with all the tags for this server.
*/
public TagSet getTagSet() {
return tagSet;
}
/**
* The earliest version of the wire protocol that this MongoDB server is capable of using to communicate with clients.
*
* @return the minimum protocol version supported by this server
* @mongodb.server.release 2.6
*/
public int getMinWireVersion() {
return minWireVersion;
}
/**
* The latest version of the wire protocol that this MongoDB server is capable of using to communicate with clients.
*
* @return the maximum protocol version supported by this server
* @mongodb.server.release 2.6
*/
public int getMaxWireVersion() {
return maxWireVersion;
}
/**
* The replica set electionid reported by this MongoDB server.
*
* @return the electionId, which may be null
*/
public ObjectId getElectionId() {
return electionId;
}
/**
* Returns true if the server has the given tags. A server of either type {@code ServerType.STANDALONE} or {@code
* ServerType.SHARD_ROUTER} is considered to have all tags, so this method will always return true for instances of either of those
* types.
*
* @param desiredTags the tags
* @return true if this server has the given tags
*/
public boolean hasTags(final TagSet desiredTags) {
if (!ok) {
return false;
}
if (type == STANDALONE || type == SHARD_ROUTER) {
return true;
}
return tagSet.containsAll(desiredTags);
}
/**
* Gets the name of the replica set
*
* @return the name of the replica set
*/
public String getSetName() {
return setName;
}
/**
* The isOK() result from requesting this information from the server
*
* @return true if the request executed correctly
*/
public boolean isOk() {
return ok;
}
/**
* Gets the current state of the connection to the server.
*
* @return ServerConnectionState representing whether the server has been successfully connected to
*/
public ServerConnectionState getState() {
return state;
}
/**
* Gets the type of the server, for example whether it's a standalone or in a replica set.
*
* @return the server type
*/
public ServerType getType() {
return type;
}
/**
* Gets the type of the cluster this server is in (for example, replica set).
*
* @return a ClusterType representing the type of the cluster this server is in
*/
public ClusterType getClusterType() {
return type.getClusterType();
}
/**
* Gets the server version
*
* @return a ServerVersion representing which version of MongoDB is running on this server
*/
public ServerVersion getVersion() {
return version;
}
/**
* Get the time it took to make the round trip for requesting this information from the server in nanoseconds.
*
* @return the time taken to request the information, in nano seconds
*/
public long getRoundTripTimeNanos() {
return roundTripTimeNanos;
}
/**
* Gets the exception thrown while attempting to determine the server description. This is useful for diagnostic purposed when
* determining the root cause of a connectivity failure.
*
* @return the exception, which may be null
*/
public Throwable getException() {
return exception;
}
/**
* Returns true if this instance is equals to @code{o}. Note that equality is defined to NOT include the round trip time.
*
* @param o the object to compare to
* @return true if this instance is equals to @code{o}
*/
@Override
public boolean equals(final Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
ServerDescription that = (ServerDescription) o;
if (maxDocumentSize != that.maxDocumentSize) {
return false;
}
if (ok != that.ok) {
return false;
}
if (!address.equals(that.address)) {
return false;
}
if (!arbiters.equals(that.arbiters)) {
return false;
}
if (canonicalAddress != null ? !canonicalAddress.equals(that.canonicalAddress) : that.canonicalAddress != null) {
return false;
}
if (!hosts.equals(that.hosts)) {
return false;
}
if (!passives.equals(that.passives)) {
return false;
}
if (primary != null ? !primary.equals(that.primary) : that.primary != null) {
return false;
}
if (setName != null ? !setName.equals(that.setName) : that.setName != null) {
return false;
}
if (state != that.state) {
return false;
}
if (!tagSet.equals(that.tagSet)) {
return false;
}
if (type != that.type) {
return false;
}
if (!version.equals(that.version)) {
return false;
}
if (minWireVersion != that.minWireVersion) {
return false;
}
if (maxWireVersion != that.maxWireVersion) {
return false;
}
if (electionId != null ? !electionId.equals(that.electionId) : that.electionId != null) {
return false;
}
// Compare class equality and message as exceptions rarely override equals
Class> thisExceptionClass = exception != null ? exception.getClass() : null;
Class> thatExceptionClass = that.exception != null ? that.exception.getClass() : null;
if (thisExceptionClass != null ? !thisExceptionClass.equals(thatExceptionClass) : thatExceptionClass != null) {
return false;
}
String thisExceptionMessage = exception != null ? exception.getMessage() : null;
String thatExceptionMessage = that.exception != null ? that.exception.getMessage() : null;
if (thisExceptionMessage != null ? !thisExceptionMessage.equals(thatExceptionMessage) : thatExceptionMessage != null) {
return false;
}
return true;
}
@Override
public int hashCode() {
int result = address.hashCode();
result = 31 * result + type.hashCode();
result = 31 * result + (canonicalAddress != null ? canonicalAddress.hashCode() : 0);
result = 31 * result + hosts.hashCode();
result = 31 * result + passives.hashCode();
result = 31 * result + arbiters.hashCode();
result = 31 * result + (primary != null ? primary.hashCode() : 0);
result = 31 * result + maxDocumentSize;
result = 31 * result + tagSet.hashCode();
result = 31 * result + (setName != null ? setName.hashCode() : 0);
result = 31 * result + (electionId != null ? electionId.hashCode() : 0);
result = 31 * result + (ok ? 1 : 0);
result = 31 * result + state.hashCode();
result = 31 * result + version.hashCode();
result = 31 * result + minWireVersion;
result = 31 * result + maxWireVersion;
result = 31 * result + (exception == null ? 0 : exception.getClass().hashCode());
result = 31 * result + (exception == null ? 0 : exception.getMessage().hashCode());
return result;
}
@Override
public String toString() {
return "ServerDescription{"
+ "address=" + address
+ ", type=" + type
+ ", state=" + state
+ (state == CONNECTED
?
", ok=" + ok
+ ", version=" + version
+ ", minWireVersion=" + minWireVersion
+ ", maxWireVersion=" + maxWireVersion
+ ", electionId=" + electionId
+ ", maxDocumentSize=" + maxDocumentSize
+ ", roundTripTimeNanos=" + roundTripTimeNanos
: "")
+ (isReplicaSetMember()
?
", setName='" + setName + '\''
+ ", canonicalAddress=" + canonicalAddress
+ ", hosts=" + hosts
+ ", passives=" + passives
+ ", arbiters=" + arbiters
+ ", primary='" + primary + '\''
+ ", tagSet=" + tagSet
: "")
+ (exception == null ? "" : ", exception=" + translateExceptionToString())
+ '}';
}
/**
* Returns a short, pretty description for this ServerDescription.
*
* @return a String containing the most pertinent information about this ServerDescription
*/
public String getShortDescription() {
return "{"
+ "address=" + address
+ ", type=" + type
+ (!tagSet.iterator().hasNext() ? "" : ", " + tagSet)
+ (state == CONNECTED ? (", roundTripTime=" + getRoundTripFormattedInMilliseconds() + " ms") : "")
+ ", state=" + state
+ (exception == null ? "" : ", exception=" + translateExceptionToString())
+ '}';
}
private String translateExceptionToString() {
StringBuilder builder = new StringBuilder();
builder.append("{");
builder.append(exception);
builder.append("}");
Throwable cur = exception.getCause();
while (cur != null) {
builder.append(", caused by ");
builder.append("{");
builder.append(cur);
builder.append("}");
cur = cur.getCause();
}
return builder.toString();
}
private String getRoundTripFormattedInMilliseconds() {
return new DecimalFormat("#0.0").format(roundTripTimeNanos / 1000.0 / 1000.0);
}
ServerDescription(final Builder builder) {
address = notNull("address", builder.address);
type = notNull("type", builder.type);
state = notNull("state", builder.state);
version = notNull("version", builder.version);
canonicalAddress = builder.canonicalAddress;
hosts = builder.hosts;
passives = builder.passives;
arbiters = builder.arbiters;
primary = builder.primary;
maxDocumentSize = builder.maxDocumentSize;
tagSet = builder.tagSet;
setName = builder.setName;
roundTripTimeNanos = builder.roundTripTimeNanos;
ok = builder.ok;
minWireVersion = builder.minWireVersion;
maxWireVersion = builder.maxWireVersion;
electionId = builder.electionId;
exception = builder.exception;
}
}