/// <summary> /// Writes a raw BSON array. /// </summary> /// <param name="slice">The byte buffer containing the raw BSON array.</param> public virtual void WriteRawBsonArray(IByteBuffer slice) { // overridden in BsonBinaryWriter to write the raw bytes to the stream // for all other streams, deserialize the raw bytes and serialize the resulting array instead using (var chunkSource = new InputBufferChunkSource(BsonChunkPool.Default)) using (var buffer = new MultiChunkBuffer(chunkSource)) using (var stream = new ByteBufferStream(buffer)) { // wrap the array in a fake document so we can deserialize it var documentLength = slice.Length + 8; buffer.EnsureCapacity(documentLength); stream.WriteInt32(documentLength); stream.WriteBsonType(BsonType.Array); stream.WriteByte((byte)'x'); stream.WriteByte(0); stream.WriteSlice(slice); stream.WriteByte(0); buffer.MakeReadOnly(); stream.Position = 0; using (var reader = new BsonBinaryReader(stream, BsonBinaryReaderSettings.Defaults)) { var deserializationContext = BsonDeserializationContext.CreateRoot(reader); reader.ReadStartDocument(); reader.ReadName("x"); var array = BsonArraySerializer.Instance.Deserialize(deserializationContext); reader.ReadEndDocument(); var serializationContext = BsonSerializationContext.CreateRoot(this); BsonArraySerializer.Instance.Serialize(serializationContext, array); } } }
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 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; } }