public void GetKillCursorsMessageEncoder_should_return_a_KillCursorsMessageBinaryEncoder() { using (var stream = new MemoryStream()) { var encoderFactory = new BinaryMessageEncoderFactory(stream, null); var encoder = encoderFactory.GetKillCursorsMessageEncoder(); encoder.Should().BeOfType<KillCursorsMessageBinaryEncoder>(); } }
public void GetInsertMessageEncoder_should_return_a_InsertMessageBinaryEncoder() { using (var stream = new MemoryStream()) { var encoderFactory = new BinaryMessageEncoderFactory(stream, null); var encoder = encoderFactory.GetInsertMessageEncoder<BsonDocument>(BsonDocumentSerializer.Instance); encoder.Should().BeOfType<InsertMessageBinaryEncoder<BsonDocument>>(); } }
public IByteBuffer EncodeMessages(CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); var serializationStopwatch = Stopwatch.StartNew(); var outputBufferChunkSource = new OutputBufferChunkSource(BsonChunkPool.Default); var buffer = new MultiChunkBuffer(outputBufferChunkSource); using (var stream = new ByteBufferStream(buffer, ownsBuffer: false)) { var encoderFactory = new BinaryMessageEncoderFactory(stream, _messageEncoderSettings); foreach (var message in _messages) { if (message.ShouldBeSent == null || message.ShouldBeSent()) { var encoder = message.GetEncoder(encoderFactory); encoder.WriteMessage(message); message.WasSent = true; } // Encoding messages includes serializing the // documents, so encoding message could be expensive // and worthy of us honoring cancellation here. cancellationToken.ThrowIfCancellationRequested(); } buffer.Length = (int)stream.Length; buffer.MakeReadOnly(); } serializationStopwatch.Stop(); _serializationDuration = serializationStopwatch.Elapsed; return buffer; }
public ResponseMessage DecodeMessage(IByteBuffer buffer, IMessageEncoderSelector encoderSelector, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); _stopwatch.Stop(); _networkDuration = _stopwatch.Elapsed; ResponseMessage message; _stopwatch.Restart(); using (var stream = new ByteBufferStream(buffer, ownsBuffer: false)) { var encoderFactory = new BinaryMessageEncoderFactory(stream, _messageEncoderSettings); var encoder = encoderSelector.GetEncoder(encoderFactory); message = (ResponseMessage)encoder.ReadMessage(); } _stopwatch.Stop(); _deserializationDuration = _stopwatch.Elapsed; return message; }
private void ProcessReplyMessage(CommandState state, ResponseMessage message, IByteBuffer buffer, ConnectionId connectionId, MessageEncoderSettings encoderSettings) { state.Stopwatch.Stop(); bool disposeOfDocuments = false; var replyMessage = message as ReplyMessage<RawBsonDocument>; if (replyMessage == null) { // ReplyMessage is generic, which means that we can't use it here, so, we need to use a different one... using (var stream = new ByteBufferStream(buffer, ownsBuffer: false)) { var encoderFactory = new BinaryMessageEncoderFactory(stream, encoderSettings); replyMessage = (ReplyMessage<RawBsonDocument>)encoderFactory .GetReplyMessageEncoder(RawBsonDocumentSerializer.Instance) .ReadMessage(); disposeOfDocuments = true; } } try { if (replyMessage.CursorNotFound || replyMessage.QueryFailure || (state.ExpectedResponseType != ExpectedResponseType.Query && replyMessage.Documents.Count == 0)) { var queryFailureDocument = replyMessage.QueryFailureDocument; if (__securitySensitiveCommands.Contains(state.CommandName)) { queryFailureDocument = new BsonDocument(); } if (_failedEvent != null) { _failedEvent(new CommandFailedEvent( state.CommandName, new MongoCommandException( connectionId, string.Format("{0} command failed", state.CommandName), null, queryFailureDocument), state.OperationId, replyMessage.ResponseTo, connectionId, state.Stopwatch.Elapsed)); } } else { switch (state.ExpectedResponseType) { case ExpectedResponseType.Command: ProcessCommandReplyMessage(state, replyMessage, connectionId); break; case ExpectedResponseType.GLE: ProcessGLEReplyMessage(state, replyMessage, connectionId); break; case ExpectedResponseType.Query: ProcessQueryReplyMessage(state, replyMessage, connectionId); break; } } } finally { if (disposeOfDocuments && replyMessage.Documents != null) { replyMessage.Documents.ForEach(d => d.Dispose()); } } }
public async Task SendMessagesAsync(IEnumerable<RequestMessage> messages, MessageEncoderSettings messageEncoderSettings, CancellationToken cancellationToken) { Ensure.IsNotNull(messages, nameof(messages)); ThrowIfDisposedOrNotOpen(); var messagesToSend = messages.ToList(); var requestIds = messagesToSend.Select(x => x.RequestId).ToList(); try { if (_sendingMessagesEventHandler != null) { _sendingMessagesEventHandler(new ConnectionSendingMessagesEvent(_connectionId, requestIds, EventContext.OperationId)); } cancellationToken.ThrowIfCancellationRequested(); var stopwatch = Stopwatch.StartNew(); var outputBufferChunkSource = new OutputBufferChunkSource(BsonChunkPool.Default); using (var buffer = new MultiChunkBuffer(outputBufferChunkSource)) { using (var stream = new ByteBufferStream(buffer, ownsBuffer: false)) { var encoderFactory = new BinaryMessageEncoderFactory(stream, messageEncoderSettings); foreach (var message in messagesToSend) { if (message.ShouldBeSent == null || message.ShouldBeSent()) { var encoder = message.GetEncoder(encoderFactory); encoder.WriteMessage(message); message.WasSent = true; } // Encoding messages includes serializing the // documents, so encoding message could be expensive // and worthy of us honoring cancellation here. cancellationToken.ThrowIfCancellationRequested(); } buffer.Length = (int)stream.Length; buffer.MakeReadOnly(); } var serializationDuration = stopwatch.Elapsed; if (_commandEventHelper.ShouldCallBeforeSending) { _commandEventHelper.BeforeSending( messages, _connectionId, buffer, messageEncoderSettings, stopwatch); } var stopwatchCheckPoint = stopwatch.Elapsed; await SendBufferAsync(buffer, cancellationToken).ConfigureAwait(false); var networkDuration = stopwatch.Elapsed - stopwatchCheckPoint; if (_commandEventHelper.ShouldCallAfterSending) { _commandEventHelper.AfterSending(messages, _connectionId); } if (_sentMessagesEventHandler != null) { _sentMessagesEventHandler(new ConnectionSentMessagesEvent(_connectionId, requestIds, buffer.Length, networkDuration, serializationDuration, EventContext.OperationId)); } } } catch (Exception ex) { if (_commandEventHelper.ShouldCallErrorSending) { _commandEventHelper.ErrorSending(messages, _connectionId, ex); } if (_failedSendingMessagesEvent != null) { _failedSendingMessagesEvent(new ConnectionSendingMessagesFailedEvent(_connectionId, requestIds, ex, EventContext.OperationId)); } throw; } }
public async Task<ResponseMessage> ReceiveMessageAsync( int responseTo, IMessageEncoderSelector encoderSelector, MessageEncoderSettings messageEncoderSettings, CancellationToken cancellationToken) { Ensure.IsNotNull(encoderSelector, nameof(encoderSelector)); ThrowIfDisposedOrNotOpen(); try { if (_receivingMessageEventHandler != null) { _receivingMessageEventHandler(new ConnectionReceivingMessageEvent(_connectionId, responseTo, EventContext.OperationId)); } ResponseMessage reply; var stopwatch = Stopwatch.StartNew(); using (var buffer = await ReceiveBufferAsync(responseTo, cancellationToken).ConfigureAwait(false)) { stopwatch.Stop(); var networkDuration = stopwatch.Elapsed; cancellationToken.ThrowIfCancellationRequested(); stopwatch.Restart(); using (var stream = new ByteBufferStream(buffer)) { var encoderFactory = new BinaryMessageEncoderFactory(stream, messageEncoderSettings); var encoder = encoderSelector.GetEncoder(encoderFactory); reply = (ResponseMessage)encoder.ReadMessage(); } stopwatch.Stop(); if (_commandEventHelper.ShouldCallAfterReceiving) { _commandEventHelper.AfterReceiving(reply, buffer, _connectionId, messageEncoderSettings); } if (_receivedMessageEventHandler != null) { _receivedMessageEventHandler(new ConnectionReceivedMessageEvent(_connectionId, responseTo, buffer.Length, networkDuration, stopwatch.Elapsed, EventContext.OperationId)); } } return reply; } catch (Exception ex) { if (_commandEventHelper.ShouldCallErrorReceiving) { _commandEventHelper.ErrorReceiving(responseTo, _connectionId, ex); } if (_failedReceivingMessageEventHandler != null) { _failedReceivingMessageEventHandler(new ConnectionReceivingMessageFailedEvent(_connectionId, responseTo, ex, EventContext.OperationId)); } throw; } }
private void ProcessReplyMessage(CommandState state, ResponseMessage message, IByteBuffer buffer, ConnectionId connectionId, MessageEncoderSettings encoderSettings) { state.Stopwatch.Stop(); bool disposeOfDocuments = false; var replyMessage = message as ReplyMessage <RawBsonDocument>; if (replyMessage == null) { // ReplyMessage is generic, which means that we can't use it here, so, we need to use a different one... using (var stream = new ByteBufferStream(buffer, ownsBuffer: false)) { var encoderFactory = new BinaryMessageEncoderFactory(stream, encoderSettings); replyMessage = (ReplyMessage <RawBsonDocument>)encoderFactory .GetReplyMessageEncoder(RawBsonDocumentSerializer.Instance) .ReadMessage(); disposeOfDocuments = true; } } try { if (replyMessage.CursorNotFound || replyMessage.QueryFailure || (state.ExpectedResponseType != ExpectedResponseType.Query && replyMessage.Documents.Count == 0)) { var queryFailureDocument = replyMessage.QueryFailureDocument; if (__securitySensitiveCommands.Contains(state.CommandName)) { queryFailureDocument = new BsonDocument(); } if (_failedEvent != null) { _failedEvent(new CommandFailedEvent( state.CommandName, new MongoCommandException( connectionId, string.Format("{0} command failed", state.CommandName), null, queryFailureDocument), state.OperationId, replyMessage.ResponseTo, connectionId, state.Stopwatch.Elapsed)); } } else { switch (state.ExpectedResponseType) { case ExpectedResponseType.Command: ProcessCommandReplyMessage(state, replyMessage, connectionId); break; case ExpectedResponseType.GLE: ProcessGLEReplyMessage(state, replyMessage, connectionId); break; case ExpectedResponseType.Query: ProcessQueryReplyMessage(state, replyMessage, connectionId); break; } } } finally { if (disposeOfDocuments && replyMessage.Documents != null) { replyMessage.Documents.ForEach(d => d.Dispose()); } } }
private TCommandResult ProcessReply(ConnectionId connectionId, ReplyMessage <RawBsonDocument> reply) { if (reply.NumberReturned == 0) { throw new MongoCommandException(connectionId, "Command returned no documents.", _command); } if (reply.NumberReturned > 1) { throw new MongoCommandException(connectionId, "Command returned multiple documents.", _command); } if (reply.QueryFailure) { var failureDocument = reply.QueryFailureDocument; throw ExceptionMapper.Map(connectionId, failureDocument) ?? new MongoCommandException(connectionId, "Command failed.", _command, failureDocument); } using (var rawDocument = reply.Documents[0]) { if (!rawDocument.GetValue("ok", false).ToBoolean()) { var materializedDocument = new BsonDocument(rawDocument); var commandName = _command.GetElement(0).Name; if (commandName == "$query") { commandName = _command["$query"].AsBsonDocument.GetElement(0).Name; } var notPrimaryOrNodeIsRecoveringException = ExceptionMapper.MapNotPrimaryOrNodeIsRecovering(connectionId, materializedDocument, "errmsg"); if (notPrimaryOrNodeIsRecoveringException != null) { throw notPrimaryOrNodeIsRecoveringException; } string message; BsonValue errmsgBsonValue; if (materializedDocument.TryGetValue("errmsg", out errmsgBsonValue) && errmsgBsonValue.IsString) { var errmsg = errmsgBsonValue.ToString(); message = string.Format("Command {0} failed: {1}.", commandName, errmsg); } else { message = string.Format("Command {0} failed.", commandName); } var mappedException = ExceptionMapper.Map(connectionId, materializedDocument); if (mappedException != null) { throw mappedException; } throw new MongoCommandException(connectionId, message, _command, materializedDocument); } using (var stream = new ByteBufferStream(rawDocument.Slice, ownsByteBuffer: false)) { var encoderFactory = new BinaryMessageEncoderFactory(stream, _messageEncoderSettings); var encoder = (ReplyMessageBinaryEncoder <TCommandResult>)encoderFactory.GetReplyMessageEncoder <TCommandResult>(_resultSerializer); using (var reader = encoder.CreateBinaryReader()) { var context = BsonDeserializationContext.CreateRoot(reader); return(_resultSerializer.Deserialize(context)); } } } }
private TCommandResult ProcessReply(ConnectionId connectionId, ReplyMessage <RawBsonDocument> reply) { if (reply.NumberReturned == 0) { throw new MongoCommandException(connectionId, "Command returned no documents.", _command); } if (reply.NumberReturned > 1) { throw new MongoCommandException(connectionId, "Command returned multiple documents.", _command); } if (reply.QueryFailure) { var failureDocument = reply.QueryFailureDocument; throw ExceptionMapper.Map(connectionId, failureDocument) ?? new MongoCommandException(connectionId, "Command failed.", _command, failureDocument); } using (var rawDocument = reply.Documents[0]) { var binaryReaderSettings = new BsonBinaryReaderSettings(); if (_messageEncoderSettings != null) { binaryReaderSettings.Encoding = _messageEncoderSettings.GetOrDefault <UTF8Encoding>(MessageEncoderSettingsName.ReadEncoding, Utf8Encodings.Strict); #pragma warning disable 618 if (BsonDefaults.GuidRepresentationMode == GuidRepresentationMode.V2) { binaryReaderSettings.GuidRepresentation = _messageEncoderSettings.GetOrDefault <GuidRepresentation>(MessageEncoderSettingsName.GuidRepresentation, GuidRepresentation.CSharpLegacy); } #pragma warning restore 618 } ; BsonValue clusterTime; if (rawDocument.TryGetValue("$clusterTime", out clusterTime)) { // note: we are assuming that _session is an instance of ClusterClockAdvancingClusterTime // and that calling _session.AdvanceClusterTime will have the side effect of advancing the cluster's ClusterTime also var materializedClusterTime = ((RawBsonDocument)clusterTime).Materialize(binaryReaderSettings); _session.AdvanceClusterTime(materializedClusterTime); } BsonValue operationTime; if (rawDocument.TryGetValue("operationTime", out operationTime)) { _session.AdvanceOperationTime(operationTime.AsBsonTimestamp); } if (!rawDocument.GetValue("ok", false).ToBoolean()) { var materializedDocument = rawDocument.Materialize(binaryReaderSettings); var commandName = _command.GetElement(0).Name; if (commandName == "$query") { commandName = _command["$query"].AsBsonDocument.GetElement(0).Name; } var notPrimaryOrNodeIsRecoveringException = ExceptionMapper.MapNotPrimaryOrNodeIsRecovering(connectionId, _command, materializedDocument, "errmsg"); if (notPrimaryOrNodeIsRecoveringException != null) { throw notPrimaryOrNodeIsRecoveringException; } string message; BsonValue errmsgBsonValue; if (materializedDocument.TryGetValue("errmsg", out errmsgBsonValue) && errmsgBsonValue.IsString) { var errmsg = errmsgBsonValue.ToString(); message = string.Format("Command {0} failed: {1}.", commandName, errmsg); } else { message = string.Format("Command {0} failed.", commandName); } var mappedException = ExceptionMapper.Map(connectionId, materializedDocument); if (mappedException != null) { throw mappedException; } throw new MongoCommandException(connectionId, message, _command, materializedDocument); } if (rawDocument.Contains("writeConcernError")) { var materializedDocument = rawDocument.Materialize(binaryReaderSettings); var writeConcernError = materializedDocument["writeConcernError"].AsBsonDocument; var message = writeConcernError.AsBsonDocument.GetValue("errmsg", null)?.AsString; var writeConcernResult = new WriteConcernResult(materializedDocument); throw new MongoWriteConcernException(connectionId, message, writeConcernResult); } using (var stream = new ByteBufferStream(rawDocument.Slice, ownsBuffer: false)) { var encoderFactory = new BinaryMessageEncoderFactory(stream, _messageEncoderSettings); var encoder = (ReplyMessageBinaryEncoder <TCommandResult>)encoderFactory.GetReplyMessageEncoder <TCommandResult>(_resultSerializer); using (var reader = encoder.CreateBinaryReader()) { var context = BsonDeserializationContext.CreateRoot(reader); return(_resultSerializer.Deserialize(context)); } } } }
public void GetDeleteMessageEncoder_should_return_a_DeleteMessageBinaryEncoder() { using (var stream = new MemoryStream()) using (var binaryWriter = new BsonBinaryWriter(stream)) { var encoderFactory = new BinaryMessageEncoderFactory(null, binaryWriter); var encoder = encoderFactory.GetDeleteMessageEncoder(); encoder.Should().BeOfType<DeleteMessageBinaryEncoder>(); } }
public void GetReplyMessageEncoder_should_return_a_ReplyMessageBinaryEncoder() { using (var stream = new MemoryStream()) using (var binaryWriter = new BsonBinaryWriter(stream)) { var encoderFactory = new BinaryMessageEncoderFactory(null, binaryWriter); var encoder = encoderFactory.GetReplyMessageEncoder<BsonDocument>(BsonDocumentSerializer.Instance); encoder.Should().BeOfType<ReplyMessageBinaryEncoder<BsonDocument>>(); } }
public async Task SendMessagesAsync(IEnumerable <RequestMessage> messages, MessageEncoderSettings messageEncoderSettings, CancellationToken cancellationToken) { Ensure.IsNotNull(messages, nameof(messages)); ThrowIfDisposedOrNotOpen(); var messagesToSend = messages.ToList(); var requestIds = messagesToSend.Select(x => x.RequestId).ToList(); try { if (_sendingMessagesEventHandler != null) { _sendingMessagesEventHandler(new ConnectionSendingMessagesEvent(_connectionId, requestIds, EventContext.OperationId)); } cancellationToken.ThrowIfCancellationRequested(); var stopwatch = Stopwatch.StartNew(); var outputBufferChunkSource = new OutputBufferChunkSource(BsonChunkPool.Default); using (var buffer = new MultiChunkBuffer(outputBufferChunkSource)) { using (var stream = new ByteBufferStream(buffer, ownsBuffer: false)) { var encoderFactory = new BinaryMessageEncoderFactory(stream, messageEncoderSettings); foreach (var message in messagesToSend) { if (message.ShouldBeSent == null || message.ShouldBeSent()) { var encoder = message.GetEncoder(encoderFactory); encoder.WriteMessage(message); message.WasSent = true; } // Encoding messages includes serializing the // documents, so encoding message could be expensive // and worthy of us honoring cancellation here. cancellationToken.ThrowIfCancellationRequested(); } buffer.Length = (int)stream.Length; buffer.MakeReadOnly(); } var serializationDuration = stopwatch.Elapsed; if (_commandEventHelper.ShouldCallBeforeSending) { _commandEventHelper.BeforeSending( messages, _connectionId, buffer, messageEncoderSettings, stopwatch); } var stopwatchCheckPoint = stopwatch.Elapsed; await SendBufferAsync(buffer, cancellationToken).ConfigureAwait(false); var networkDuration = stopwatch.Elapsed - stopwatchCheckPoint; if (_commandEventHelper.ShouldCallAfterSending) { _commandEventHelper.AfterSending(messages, _connectionId); } if (_sentMessagesEventHandler != null) { _sentMessagesEventHandler(new ConnectionSentMessagesEvent(_connectionId, requestIds, buffer.Length, networkDuration, serializationDuration, EventContext.OperationId)); } } } catch (Exception ex) { if (_commandEventHelper.ShouldCallErrorSending) { _commandEventHelper.ErrorSending(messages, _connectionId, ex); } if (_failedSendingMessagesEvent != null) { _failedSendingMessagesEvent(new ConnectionSendingMessagesFailedEvent(_connectionId, requestIds, ex, EventContext.OperationId)); } throw; } }
public async Task <ResponseMessage> ReceiveMessageAsync( int responseTo, IMessageEncoderSelector encoderSelector, MessageEncoderSettings messageEncoderSettings, CancellationToken cancellationToken) { Ensure.IsNotNull(encoderSelector, nameof(encoderSelector)); ThrowIfDisposedOrNotOpen(); try { if (_receivingMessageEventHandler != null) { _receivingMessageEventHandler(new ConnectionReceivingMessageEvent(_connectionId, responseTo, EventContext.OperationId)); } ResponseMessage reply; var stopwatch = Stopwatch.StartNew(); using (var buffer = await ReceiveBufferAsync(responseTo, cancellationToken).ConfigureAwait(false)) { stopwatch.Stop(); var networkDuration = stopwatch.Elapsed; cancellationToken.ThrowIfCancellationRequested(); stopwatch.Restart(); using (var stream = new ByteBufferStream(buffer)) { var encoderFactory = new BinaryMessageEncoderFactory(stream, messageEncoderSettings); var encoder = encoderSelector.GetEncoder(encoderFactory); reply = (ResponseMessage)encoder.ReadMessage(); } stopwatch.Stop(); if (_commandEventHelper.ShouldCallAfterReceiving) { _commandEventHelper.AfterReceiving(reply, buffer, _connectionId, messageEncoderSettings); } if (_receivedMessageEventHandler != null) { _receivedMessageEventHandler(new ConnectionReceivedMessageEvent(_connectionId, responseTo, buffer.Length, networkDuration, stopwatch.Elapsed, EventContext.OperationId)); } } return(reply); } catch (Exception ex) { if (_commandEventHelper.ShouldCallErrorReceiving) { _commandEventHelper.ErrorReceiving(responseTo, _connectionId, ex); } if (_failedReceivingMessageEventHandler != null) { _failedReceivingMessageEventHandler(new ConnectionReceivingMessageFailedEvent(_connectionId, responseTo, ex, EventContext.OperationId)); } throw; } }