コード例 #1
0
        public void GetChunk_should_return_expected_result_when_initialUnpooledChunkSize_is_not_zero(int numberOfCalls, int[] expectedRequestSizes)
        {
            var baseSource = Substitute.For <IBsonChunkSource>();

            baseSource.GetChunk(Arg.Any <int>()).Returns(x =>
            {
                var requestedSize = (int)x[0];
                return(new ByteArrayChunk(requestedSize));
            });
            var subject = new OutputBufferChunkSource(baseSource, initialUnpooledChunkSize: 2, minChunkSize: 4, maxChunkSize: 32);

            var result = subject.GetChunk(1);

            result.Bytes.Count.Should().Be(2);

            for (var n = 0; n < numberOfCalls - 1; n++)
            {
                result = subject.GetChunk(1);
                result.Bytes.Count.Should().Be(expectedRequestSizes[n]);
            }

            baseSource.Received(numberOfCalls - 1).GetChunk(Arg.Any <int>());
            foreach (var expectedRequestSize in expectedRequestSizes)
            {
                var requiredNumberOfCalls = expectedRequestSizes.Count(s => s == expectedRequestSize);
                baseSource.Received(requiredNumberOfCalls).GetChunk(expectedRequestSize);
            }
        }
コード例 #2
0
        private IByteBuffer CompressMessages(
            IEnumerable <RequestMessage> messages,
            IByteBuffer uncompressedBuffer,
            MessageEncoderSettings messageEncoderSettings)
        {
            var outputBufferChunkSource = new OutputBufferChunkSource(BsonChunkPool.Default);
            var compressedBuffer        = new MultiChunkBuffer(outputBufferChunkSource);

            using (var uncompressedStream = new ByteBufferStream(uncompressedBuffer, ownsBuffer: false))
                using (var compressedStream = new ByteBufferStream(compressedBuffer, ownsBuffer: false))
                {
                    foreach (var message in messages)
                    {
                        var uncompressedMessageLength = uncompressedStream.ReadInt32();
                        uncompressedStream.Position -= 4;

                        using (var uncompressedMessageSlice = uncompressedBuffer.GetSlice((int)uncompressedStream.Position, uncompressedMessageLength))
                            using (var uncompressedMessageStream = new ByteBufferStream(uncompressedMessageSlice, ownsBuffer: false))
                            {
                                if (message.MayBeCompressed)
                                {
                                    CompressMessage(message, uncompressedMessageStream, compressedStream, messageEncoderSettings);
                                }
                                else
                                {
                                    uncompressedMessageStream.EfficientCopyTo(compressedStream);
                                }
                            }
                    }
                    compressedBuffer.Length = (int)compressedStream.Length;
                }

            return(compressedBuffer);
        }
コード例 #3
0
            public IByteBuffer EncodeMessages(CancellationToken cancellationToken, out List <RequestMessage> sentMessages)
            {
                sentMessages = new List <RequestMessage>();
                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, compressorSource: null);
                    foreach (var message in _messages)
                    {
                        if (message.ShouldBeSent == null || message.ShouldBeSent())
                        {
                            var encoder = message.GetEncoder(encoderFactory);
                            encoder.WriteMessage(message);
                            message.WasSent = true;
                            sentMessages.Add(message);
                        }

                        // 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);
            }
コード例 #4
0
        public async Task SendMessagesAsync(IEnumerable <RequestMessage> messages, MessageEncoderSettings messageEncoderSettings, CancellationToken cancellationToken)
        {
            Ensure.IsNotNull(messages, "messages");
            ThrowIfDisposedOrNotOpen();

            var messagesToSend = messages.ToList();

            try
            {
                if (_listener != null)
                {
                    _listener.ConnectionBeforeSendingMessages(new ConnectionBeforeSendingMessagesEvent(_connectionId, messagesToSend));
                }

                cancellationToken.ThrowIfCancellationRequested();
                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;
                    }

                    var stopwatch = Stopwatch.StartNew();
                    await SendBufferAsync(buffer, cancellationToken).ConfigureAwait(false);

                    stopwatch.Stop();

                    if (_listener != null)
                    {
                        _listener.ConnectionAfterSendingMessages(new ConnectionAfterSendingMessagesEvent(_connectionId, messagesToSend, buffer.Length, stopwatch.Elapsed));
                    }
                }
            }
            catch (Exception ex)
            {
                if (_listener != null)
                {
                    _listener.ConnectionErrorSendingMessages(new ConnectionErrorSendingMessagesEvent(_connectionId, messagesToSend, ex));
                }

                throw;
            }
        }
コード例 #5
0
        public void Dispose_can_be_called_more_than_once()
        {
            var mockBaseSource = new Mock <IBsonChunkSource>();
            var subject        = new OutputBufferChunkSource(mockBaseSource.Object);

            subject.Dispose();
            subject.Dispose();
        }
コード例 #6
0
        public void Dispose_can_be_called_more_than_once()
        {
            var baseSource = Substitute.For <IBsonChunkSource>();
            var subject    = new OutputBufferChunkSource(baseSource);

            subject.Dispose();
            subject.Dispose();
        }
コード例 #7
0
        public void BaseSource_get_should_return_expected_result()
        {
            var mockBaseSource = new Mock <IBsonChunkSource>();
            var subject        = new OutputBufferChunkSource(mockBaseSource.Object);

            var result = subject.BaseSource;

            result.Should().BeSameAs(mockBaseSource.Object);
        }
コード例 #8
0
        public void BaseSource_get_should_return_expected_result()
        {
            var baseSource = Substitute.For <IBsonChunkSource>();
            var subject    = new OutputBufferChunkSource(baseSource);

            var result = subject.BaseSource;

            result.Should().BeSameAs(baseSource);
        }
コード例 #9
0
        public void MinChunkSize_get_should_return_expected_result()
        {
            var baseSource   = Substitute.For <IBsonChunkSource>();
            var minChunkSize = Reflector.DefaultMinChunkSize * 2;
            var subject      = new OutputBufferChunkSource(baseSource, minChunkSize: minChunkSize);

            var result = subject.MinChunkSize;

            result.Should().Be(minChunkSize);
        }
コード例 #10
0
        public void InitialUnpooledChunkSize_get_should_return_expected_result()
        {
            var baseSource = Substitute.For <IBsonChunkSource>();
            var initialUnpooledChunkSize = Reflector.DefaultInitialUnpooledChunkSize * 2;
            var subject = new OutputBufferChunkSource(baseSource, initialUnpooledChunkSize: initialUnpooledChunkSize);

            var result = subject.InitialUnpooledChunkSize;

            result.Should().Be(initialUnpooledChunkSize);
        }
コード例 #11
0
        public void MinChunkSize_get_should_return_expected_result()
        {
            var mockBaseSource = new Mock <IBsonChunkSource>();
            var minChunkSize   = Reflector.DefaultMinChunkSize * 2;
            var subject        = new OutputBufferChunkSource(mockBaseSource.Object, minChunkSize: minChunkSize);

            var result = subject.MinChunkSize;

            result.Should().Be(minChunkSize);
        }
コード例 #12
0
        public void InitialUnpooledChunkSize_get_should_return_expected_result()
        {
            var mockBaseSource           = new Mock <IBsonChunkSource>();
            var initialUnpooledChunkSize = Reflector.DefaultInitialUnpooledChunkSize * 2;
            var subject = new OutputBufferChunkSource(mockBaseSource.Object, initialUnpooledChunkSize: initialUnpooledChunkSize);

            var result = subject.InitialUnpooledChunkSize;

            result.Should().Be(initialUnpooledChunkSize);
        }
コード例 #13
0
        public void GetChunk_should_throw_when_requestedSize_is_less_than_or_equal_to_zero(
            [Values(-1, 0)]
            int requestedSize)
        {
            var baseSource = Substitute.For <IBsonChunkSource>();
            var subject    = new OutputBufferChunkSource(baseSource);

            Action action = () => subject.GetChunk(requestedSize);

            action.ShouldThrow <ArgumentOutOfRangeException>().And.ParamName.Should().Be("requestedSize");
        }
コード例 #14
0
        public void GetChunk_should_throw_when_subject_is_disposed()
        {
            var mockBaseSource = new Mock <IBsonChunkSource>();
            var subject        = new OutputBufferChunkSource(mockBaseSource.Object);

            subject.Dispose();

            Action action = () => subject.GetChunk(1);

            action.ShouldThrow <ObjectDisposedException>().And.ObjectName.Should().Be("OutputBufferChunkSource");
        }
コード例 #15
0
        public void Dispose_should_dispose_subject()
        {
            var mockBaseSource = new Mock <IBsonChunkSource>();
            var subject        = new OutputBufferChunkSource(mockBaseSource.Object);

            subject.Dispose();

            var reflector = new Reflector(subject);

            reflector._disposed.Should().BeTrue();
        }
コード例 #16
0
        public void Dispose_should_dispose_subject()
        {
            var baseSource = Substitute.For <IBsonChunkSource>();
            var subject    = new OutputBufferChunkSource(baseSource);

            subject.Dispose();

            var reflector = new Reflector(subject);

            reflector._disposed.Should().BeTrue();
        }
コード例 #17
0
        public void BaseSource_get_should_throw_when_subject_is_disposed()
        {
            var baseSource = Substitute.For <IBsonChunkSource>();
            var subject    = new OutputBufferChunkSource(baseSource);

            subject.Dispose();

            Action action = () => { var _ = subject.BaseSource; };

            action.ShouldThrow <ObjectDisposedException>().And.ObjectName.Should().Be("OutputBufferChunkSource");
        }
コード例 #18
0
        public void constructor_should_initialize_subject()
        {
            var baseSource = Substitute.For <IBsonChunkSource>();
            var initialUnpooledChunkSize = 2;
            var minChunkSize             = 4;
            var maxChunkSize             = 8;

            var subject = new OutputBufferChunkSource(baseSource, initialUnpooledChunkSize, minChunkSize, maxChunkSize);

            var reflector = new Reflector(subject);

            subject.BaseSource.Should().BeSameAs(baseSource);
            subject.InitialUnpooledChunkSize.Should().Be(initialUnpooledChunkSize);
            subject.MaxChunkSize.Should().Be(maxChunkSize);
            subject.MinChunkSize.Should().Be(minChunkSize);
            reflector._disposed.Should().BeFalse();
        }
コード例 #19
0
        public void GetChunk_should_return_expected_result_when_initialUnpooledChunkSize_is_zero(int numberOfCalls, int[] expectedRequestSizes)
        {
            var mockBaseSource = new Mock <IBsonChunkSource>();

            mockBaseSource.Setup(s => s.GetChunk(It.IsAny <int>())).Returns((int requestedSize) => new ByteArrayChunk(requestedSize));
            var subject = new OutputBufferChunkSource(mockBaseSource.Object, initialUnpooledChunkSize: 0, minChunkSize: 4, maxChunkSize: 32);

            for (var n = 0; n < numberOfCalls; n++)
            {
                var result = subject.GetChunk(1);
                result.Bytes.Count.Should().Be(expectedRequestSizes[n]);
            }

            mockBaseSource.Verify(s => s.GetChunk(It.IsAny <int>()), Times.Exactly(numberOfCalls));
            foreach (var expectedRequestSize in expectedRequestSizes)
            {
                var requiredNumberOfCalls = expectedRequestSizes.Count(s => s == expectedRequestSize);
                mockBaseSource.Verify(s => s.GetChunk(expectedRequestSize), Times.Exactly(requiredNumberOfCalls));
            }
        }
コード例 #20
0
        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;
            }
        }
コード例 #21
0
 public Reflector(OutputBufferChunkSource instance)
 {
     _instance = instance;
 }