com.mongodb.connection.ProtocolHelper Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of mongodb-driver-core Show documentation
Show all versions of mongodb-driver-core Show documentation
The Java operations layer for the MongoDB Java Driver.
Third parties can wrap this layer to provide custom higher-level APIs
/*
* Copyright (c) 2008-2015 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.DuplicateKeyException;
import com.mongodb.ErrorCategory;
import com.mongodb.MongoCommandException;
import com.mongodb.MongoException;
import com.mongodb.MongoExecutionTimeoutException;
import com.mongodb.MongoNodeIsRecoveringException;
import com.mongodb.MongoNotPrimaryException;
import com.mongodb.MongoQueryException;
import com.mongodb.ServerAddress;
import com.mongodb.WriteConcernException;
import com.mongodb.WriteConcernResult;
import com.mongodb.diagnostics.logging.Logger;
import com.mongodb.diagnostics.logging.Loggers;
import com.mongodb.event.CommandFailedEvent;
import com.mongodb.event.CommandListener;
import com.mongodb.event.CommandStartedEvent;
import com.mongodb.event.CommandSucceededEvent;
import org.bson.BsonBoolean;
import org.bson.BsonDocument;
import org.bson.BsonInt32;
import org.bson.BsonReader;
import org.bson.BsonString;
import org.bson.BsonType;
import org.bson.BsonValue;
import org.bson.codecs.BsonValueCodecProvider;
import org.bson.codecs.DecoderContext;
import org.bson.codecs.configuration.CodecRegistry;
import org.bson.io.BsonOutput;
import static java.lang.String.format;
import static org.bson.codecs.BsonValueCodecProvider.getClassForBsonType;
import static org.bson.codecs.configuration.CodecRegistries.fromProviders;
final class ProtocolHelper {
private static final Logger PROTOCOL_EVENT_LOGGER = Loggers.getLogger("protocol.event");
private static final CodecRegistry REGISTRY = fromProviders(new BsonValueCodecProvider());
static WriteConcernResult getWriteResult(final BsonDocument result, final ServerAddress serverAddress) {
if (!isCommandOk(result)) {
throw getCommandFailureException(result, serverAddress);
}
if (hasWriteError(result)) {
throwWriteException(result, serverAddress);
}
return createWriteResult(result);
}
private static WriteConcernResult createWriteResult(final BsonDocument result) {
BsonBoolean updatedExisting = result.getBoolean("updatedExisting", BsonBoolean.FALSE);
return WriteConcernResult.acknowledged(result.getNumber("n", new BsonInt32(0)).intValue(),
updatedExisting.getValue(), result.get("upserted"));
}
static boolean isCommandOk(final BsonDocument response) {
BsonValue okValue = response.get("ok");
return isCommandOk(okValue);
}
static boolean isCommandOk(final BsonReader bsonReader) {
return isCommandOk(getField(bsonReader, "ok"));
}
private static BsonValue getField(final BsonReader bsonReader, final String fieldName) {
bsonReader.readStartDocument();
while (bsonReader.readBsonType() != BsonType.END_OF_DOCUMENT) {
if (bsonReader.readName().equals(fieldName)) {
return REGISTRY.get(getClassForBsonType(bsonReader.getCurrentBsonType())).decode(bsonReader,
DecoderContext.builder().build());
}
bsonReader.skipValue();
}
bsonReader.readEndDocument();
return null;
}
private static boolean isCommandOk(final BsonValue okValue) {
if (okValue == null) {
return false;
} else if (okValue.isBoolean()) {
return okValue.asBoolean().getValue();
} else if (okValue.isNumber()) {
return okValue.asNumber().intValue() == 1;
} else {
return false;
}
}
static MongoException getCommandFailureException(final BsonDocument response, final ServerAddress serverAddress) {
MongoException specialException = createSpecialException(response, serverAddress, "errmsg");
if (specialException != null) {
return specialException;
}
return new MongoCommandException(response, serverAddress);
}
static int getErrorCode(final BsonDocument response) {
return (response.getNumber("code", new BsonInt32(-1)).intValue());
}
static String getErrorMessage(final BsonDocument response, final String errorMessageFieldName) {
return response.getString(errorMessageFieldName, new BsonString("")).getValue();
}
static MongoException getQueryFailureException(final BsonDocument errorDocument, final ServerAddress serverAddress) {
MongoException specialException = createSpecialException(errorDocument, serverAddress, "$err");
if (specialException != null) {
return specialException;
}
return new MongoQueryException(serverAddress, getErrorCode(errorDocument), getErrorMessage(errorDocument, "$err"));
}
static MessageSettings getMessageSettings(final ConnectionDescription connectionDescription) {
return MessageSettings.builder()
.maxDocumentSize(connectionDescription.getMaxDocumentSize())
.maxMessageSize(connectionDescription.getMaxMessageSize())
.maxBatchCount(connectionDescription.getMaxBatchCount())
.build();
}
static RequestMessage encodeMessage(final RequestMessage message, final BsonOutput bsonOutput) {
try {
return message.encode(bsonOutput);
} catch (RuntimeException e) {
bsonOutput.close();
throw e;
} catch (Error e) {
bsonOutput.close();
throw e;
}
}
private static MongoException createSpecialException(final BsonDocument response, final ServerAddress serverAddress,
final String errorMessageFieldName) {
if (ErrorCategory.fromErrorCode(getErrorCode(response)) == ErrorCategory.EXECUTION_TIMEOUT) {
return new MongoExecutionTimeoutException(getErrorCode(response), getErrorMessage(response, errorMessageFieldName));
} else if (getErrorMessage(response, errorMessageFieldName).startsWith("not master")) {
return new MongoNotPrimaryException(serverAddress);
} else if (getErrorMessage(response, errorMessageFieldName).startsWith("node is recovering")) {
return new MongoNodeIsRecoveringException(serverAddress);
} else {
return null;
}
}
private static boolean hasWriteError(final BsonDocument response) {
String err = WriteConcernException.extractErrorMessage(response);
return err != null && err.length() > 0;
}
@SuppressWarnings("deprecation")
private static void throwWriteException(final BsonDocument result, final ServerAddress serverAddress) {
MongoException specialException = createSpecialException(result, serverAddress, "err");
if (specialException != null) {
throw specialException;
}
int code = WriteConcernException.extractErrorCode(result);
if (ErrorCategory.fromErrorCode(code) == ErrorCategory.DUPLICATE_KEY) {
throw new DuplicateKeyException(result, serverAddress, createWriteResult(result));
} else {
throw new WriteConcernException(result, serverAddress, createWriteResult(result));
}
}
static void sendCommandStartedEvent(final RequestMessage message, final String databaseName, final String commandName,
final BsonDocument command, final ConnectionDescription connectionDescription,
final CommandListener commandListener) {
try {
commandListener.commandStarted(new CommandStartedEvent(message.getId(), connectionDescription,
databaseName, commandName, command));
} catch (Exception e) {
if (PROTOCOL_EVENT_LOGGER.isWarnEnabled()) {
PROTOCOL_EVENT_LOGGER.warn(format("Exception thrown raising command started event to listener %s", commandListener), e);
}
}
}
static void sendCommandSucceededEvent(final RequestMessage message, final String commandName, final BsonDocument response,
final ConnectionDescription connectionDescription, final long startTimeNanos,
final CommandListener commandListener) {
try {
commandListener.commandSucceeded(new CommandSucceededEvent(message.getId(), connectionDescription,
commandName,
response, System.nanoTime() - startTimeNanos));
} catch (Exception e) {
if (PROTOCOL_EVENT_LOGGER.isWarnEnabled()) {
PROTOCOL_EVENT_LOGGER.warn(format("Exception thrown raising command succeeded event to listener %s", commandListener), e);
}
}
}
static void sendCommandFailedEvent(final RequestMessage message, final String commandName,
final ConnectionDescription connectionDescription, final long startTimeNanos,
final Throwable throwable, final CommandListener commandListener) {
try {
commandListener.commandFailed(new CommandFailedEvent(message.getId(), connectionDescription, commandName,
System.nanoTime() - startTimeNanos, throwable));
} catch (Exception e) {
if (PROTOCOL_EVENT_LOGGER.isWarnEnabled()) {
PROTOCOL_EVENT_LOGGER.warn(format("Exception thrown raising command failed event to listener %s", commandListener), e);
}
}
}
private ProtocolHelper() {
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy