public void SeekWorks()
        {
            using (var pool = new MemoryPool2())
            {
                var block = pool.Lease(256);
                foreach (var ch in Enumerable.Range(0, 256).Select(x => (byte)x))
                {
                    block.Array[block.End++] = ch;
                }
                var iterator = block.GetIterator();
                foreach (var ch in Enumerable.Range(0, 256).Select(x => (char)x))
                {
                    var hit = iterator;
                    hit.Seek(ch);
                    Assert.Equal(ch, iterator.GetLength(hit));

                    hit = iterator;
                    hit.Seek(ch, byte.MaxValue);
                    Assert.Equal(ch, iterator.GetLength(hit));

                    hit = iterator;
                    hit.Seek(byte.MaxValue, ch);
                    Assert.Equal(ch, iterator.GetLength(hit));
                }
            }
        }
        public void CopyToCorrectlyTraversesBlocks()
        {
            using (var pool = new MemoryPool2())
            {
                var block1 = pool.Lease(128);
                var block2 = block1.Next = pool.Lease(128);

                for (int i = 0; i < 128; i++)
                {
                    block1.Array[block1.End++] = (byte)i;
                }
                for (int i = 128; i < 256; i++)
                {
                    block2.Array[block2.End++] = (byte)i;
                }

                var beginIterator = block1.GetIterator();

                var array = new byte[256];
                int actual;
                var endIterator = beginIterator.CopyTo(array, 0, 256, out actual);

                Assert.Equal(256, actual);

                for (int i = 0; i < 256; i++)
                {
                    Assert.Equal(i, array[i]);
                }

                endIterator.CopyTo(array, 0, 256, out actual);
                Assert.Equal(0, actual);
            }
        }
        public void GetLengthBetweenIteratorsWorks()
        {
            using (var pool = new MemoryPool2())
            {
                var block = pool.Lease(256);
                block.End += 256;
                TestAllLengths(block, 256);
                pool.Return(block);
                block = null;

                for (var fragment = 0; fragment < 256; fragment += 4)
                {
                    var next = block;
                    block      = pool.Lease(4);
                    block.Next = next;
                    block.End += 4;
                }

                TestAllLengths(block, 256);

                while (block != null)
                {
                    var next = block.Next;
                    pool.Return(block);
                    block = next;
                }
            }
        }
        public void CopyFromCorrectlyTraversesBlocks()
        {
            using (var pool = new MemoryPool2())
            {
                var block1     = pool.Lease(128);
                var start      = block1.GetIterator();
                var end        = start;
                var bufferSize = block1.Data.Count * 3;
                var buffer     = new byte[bufferSize];

                for (int i = 0; i < bufferSize; i++)
                {
                    buffer[i] = (byte)(i % 73);
                }

                Assert.Null(block1.Next);

                end.CopyFrom(new ArraySegment <byte>(buffer));

                Assert.NotNull(block1.Next);

                for (int i = 0; i < bufferSize; i++)
                {
                    Assert.Equal(i % 73, start.Take());
                }

                Assert.Equal(-1, start.Take());
                Assert.Equal(start.Block, end.Block);
                Assert.Equal(start.Index, end.Index);
            }
        }
        public void SeekWorksAcrossBlocks()
        {
            Console.WriteLine($"Vector.IsHardwareAccelerated == {Vector.IsHardwareAccelerated}");
            Console.WriteLine($"Vector<byte>.Count == {Vector<byte>.Count}");

            using (var pool = new MemoryPool2())
            {
                var block1 = pool.Lease(256);
                var block2 = block1.Next = pool.Lease(256);
                var block3 = block2.Next = pool.Lease(256);

                foreach (var ch in Enumerable.Range(0, 34).Select(x => (byte)x))
                {
                    block1.Array[block1.End++] = ch;
                }
                foreach (var ch in Enumerable.Range(34, 25).Select(x => (byte)x))
                {
                    block2.Array[block2.End++] = ch;
                }
                foreach (var ch in Enumerable.Range(59, 197).Select(x => (byte)x))
                {
                    block3.Array[block3.End++] = ch;
                }

                var vectorMaxValues = new Vector <byte>(byte.MaxValue);

                var iterator = block1.GetIterator();
                foreach (var ch in Enumerable.Range(0, 256).Select(x => (byte)x))
                {
                    var vectorCh = new Vector <byte>(ch);

                    var hit = iterator;
                    hit.Seek(ref vectorCh);
                    Assert.Equal(ch, iterator.GetLength(hit));

                    hit = iterator;
                    hit.Seek(ref vectorCh, ref vectorMaxValues);
                    Assert.Equal(ch, iterator.GetLength(hit));

                    hit = iterator;
                    hit.Seek(ref vectorMaxValues, ref vectorCh);
                    Assert.Equal(ch, iterator.GetLength(hit));

                    hit = iterator;
                    hit.Seek(ref vectorCh, ref vectorMaxValues, ref vectorMaxValues);
                    Assert.Equal(ch, iterator.GetLength(hit));

                    hit = iterator;
                    hit.Seek(ref vectorMaxValues, ref vectorCh, ref vectorMaxValues);
                    Assert.Equal(ch, iterator.GetLength(hit));

                    hit = iterator;
                    hit.Seek(ref vectorMaxValues, ref vectorMaxValues, ref vectorCh);
                    Assert.Equal(ch, iterator.GetLength(hit));
                }
            }
        }
Example #6
0
        public void WritesDontCompleteImmediatelyWhenTooManyBytesAreAlreadyPreCompleted()
        {
            // This should match _maxBytesPreCompleted in SocketOutput
            var maxBytesPreCompleted = 65536;
            var completeQueue        = new Queue <Action <int> >();

            // Arrange
            var mockLibuv = new MockLibuv
            {
                OnWrite = (socket, buffers, triggerCompleted) =>
                {
                    completeQueue.Enqueue(triggerCompleted);
                    return(0);
                }
            };

            using (var kestrelEngine = new KestrelEngine(mockLibuv, new TestServiceContext()))
                using (var memory = new MemoryPool2())
                {
                    kestrelEngine.Start(count: 1);

                    var kestrelThread = kestrelEngine.Threads[0];
                    var socket        = new MockSocket(kestrelThread.Loop.ThreadId, new TestKestrelTrace());
                    var trace         = new KestrelTrace(new TestKestrelTrace());
                    var ltp           = new LoggingThreadPool(trace);
                    var socketOutput  = new SocketOutput(kestrelThread, socket, memory, null, 0, trace, ltp, new Queue <UvWriteReq>());

                    var           bufferSize  = maxBytesPreCompleted;
                    var           buffer      = new ArraySegment <byte>(new byte[bufferSize], 0, bufferSize);
                    var           completedWh = new ManualResetEventSlim();
                    Action <Task> onCompleted = (Task t) =>
                    {
                        Assert.Null(t.Exception);
                        completedWh.Set();
                    };

                    // Act
                    socketOutput.WriteAsync(buffer).ContinueWith(onCompleted);
                    // Assert
                    // The first write should pre-complete since it is <= _maxBytesPreCompleted.
                    Assert.True(completedWh.Wait(1000));
                    // Arrange
                    completedWh.Reset();
                    // Act
                    socketOutput.WriteAsync(buffer).ContinueWith(onCompleted);
                    // Assert
                    // Too many bytes are already pre-completed for the second write to pre-complete.
                    Assert.False(completedWh.Wait(1000));
                    // Act
                    completeQueue.Dequeue()(0);
                    // Assert
                    // Finishing the first write should allow the second write to pre-complete.
                    Assert.True(completedWh.Wait(1000));
                }
        }
Example #7
0
        public TestInput()
        {
            var trace   = new KestrelTrace(new TestKestrelTrace());
            var ltp     = new LoggingThreadPool(trace);
            var memory2 = new MemoryPool2();

            FrameContext = new FrameContext
            {
                SocketInput       = new SocketInput(memory2, ltp),
                ConnectionControl = this,
                FrameControl      = this
            };
        }
Example #8
0
        public TestInput()
        {
            var memory  = new MemoryPool();
            var memory2 = new MemoryPool2();

            FrameContext = new FrameContext
            {
                SocketInput       = new SocketInput(memory2),
                Memory            = memory,
                ConnectionControl = this,
                FrameControl      = this
            };
        }
Example #9
0
        public void ProducingStartAndProducingCompleteCanBeUsedDirectly()
        {
            int nBuffers  = 0;
            var nBufferWh = new ManualResetEventSlim();

            var mockLibuv = new MockLibuv
            {
                OnWrite = (socket, buffers, triggerCompleted) =>
                {
                    nBuffers = buffers;
                    nBufferWh.Set();
                    triggerCompleted(0);
                    return(0);
                }
            };

            using (var kestrelEngine = new KestrelEngine(mockLibuv, new TestServiceContext()))
                using (var memory = new MemoryPool2())
                {
                    kestrelEngine.Start(count: 1);

                    var kestrelThread = kestrelEngine.Threads[0];
                    var socket        = new MockSocket(kestrelThread.Loop.ThreadId, new TestKestrelTrace());
                    var trace         = new KestrelTrace(new TestKestrelTrace());
                    var ltp           = new LoggingThreadPool(trace);
                    var socketOutput  = new SocketOutput(kestrelThread, socket, memory, null, 0, trace, ltp, new Queue <UvWriteReq>());

                    // block 1
                    var start = socketOutput.ProducingStart();
                    start.Block.End = start.Block.Data.Offset + start.Block.Data.Count;

                    // block 2
                    var block2 = memory.Lease();
                    block2.End       = block2.Data.Offset + block2.Data.Count;
                    start.Block.Next = block2;

                    var end = new MemoryPoolIterator2(block2, block2.End);

                    socketOutput.ProducingComplete(end);

                    // A call to Write is required to ensure a write is scheduled
                    socketOutput.WriteAsync(default(ArraySegment <byte>));

                    Assert.True(nBufferWh.Wait(1000));
                    Assert.Equal(2, nBuffers);
                }
        }
        public FilteredStreamAdapter(
            Stream filteredStream,
            MemoryPool2 memory,
            IKestrelTrace logger)
        {
            SocketInput  = new SocketInput(memory);
            SocketOutput = new StreamSocketOutput(filteredStream);

            _log               = logger;
            _filteredStream    = filteredStream;
            _socketInputStream = new SocketInputStream(SocketInput);

            _filteredStream.CopyToAsync(_socketInputStream).ContinueWith((task, state) =>
            {
                ((FilteredStreamAdapter)state).OnStreamClose(task);
            }, this);
        }
Example #11
0
        public void CanWrite1MB()
        {
            // This test was added because when initially implementing write-behind buffering in
            // SocketOutput, the write callback would never be invoked for writes larger than
            // _maxBytesPreCompleted even after the write actually completed.

            // Arrange
            var mockLibuv = new MockLibuv
            {
                OnWrite = (socket, buffers, triggerCompleted) =>
                {
                    triggerCompleted(0);
                    return(0);
                }
            };

            using (var kestrelEngine = new KestrelEngine(mockLibuv, new TestServiceContext()))
                using (var memory = new MemoryPool2())
                {
                    kestrelEngine.Start(count: 1);

                    var kestrelThread = kestrelEngine.Threads[0];
                    var socket        = new MockSocket(kestrelThread.Loop.ThreadId, new TestKestrelTrace());
                    var trace         = new KestrelTrace(new TestKestrelTrace());
                    var ltp           = new LoggingThreadPool(trace);
                    var socketOutput  = new SocketOutput(kestrelThread, socket, memory, null, 0, trace, ltp, new Queue <UvWriteReq>());

                    // I doubt _maxBytesPreCompleted will ever be over a MB. If it is, we should change this test.
                    var bufferSize  = 1048576;
                    var buffer      = new ArraySegment <byte>(new byte[bufferSize], 0, bufferSize);
                    var completedWh = new ManualResetEventSlim();

                    // Act
                    socketOutput.WriteAsync(buffer).ContinueWith(
                        (t) =>
                    {
                        Assert.Null(t.Exception);
                        completedWh.Set();
                    }
                        );

                    // Assert
                    Assert.True(completedWh.Wait(1000));
                }
        }
        public void IsEndCorrectlyTraversesBlocks()
        {
            using (var pool = new MemoryPool2())
            {
                var block1 = pool.Lease(128);
                var block2 = block1.Next = pool.Lease(128);
                var block3 = block2.Next = pool.Lease(128);
                var block4 = block3.Next = pool.Lease(128);

                // There is no data in block2 or block4, so IsEnd should be true after 256 bytes are read.
                block1.End += 128;
                block3.End += 128;

                var iterStart = block1.GetIterator();
                var iterMid   = iterStart.Add(128);
                var iterEnd   = iterMid.Add(128);

                Assert.False(iterStart.IsEnd);
                Assert.False(iterMid.IsEnd);
                Assert.True(iterEnd.IsEnd);
            }
        }
Example #13
0
        public SocketOutput(
            KestrelThread thread,
            UvStreamHandle socket,
            MemoryPool2 memory,
            Connection connection,
            long connectionId,
            IKestrelTrace log,
            IThreadPool threadPool,
            Queue <UvWriteReq> writeReqPool)
        {
            _thread           = thread;
            _socket           = socket;
            _connection       = connection;
            _connectionId     = connectionId;
            _log              = log;
            _threadPool       = threadPool;
            _tasksPending     = new Queue <TaskCompletionSource <object> >(_initialTaskQueues);
            _tasksCompleted   = new Queue <TaskCompletionSource <object> >(_initialTaskQueues);
            _writeContextPool = new Queue <WriteContext>(_maxPooledWriteContexts);
            _writeReqPool     = writeReqPool;

            _head = memory.Lease();
            _tail = _head;
        }
        public FilteredStreamAdapter(
            Stream filteredStream,
            MemoryPool2 memory,
            IKestrelTrace logger,
            IThreadPool threadPool)
        {
            SocketInput  = new SocketInput(memory, threadPool);
            SocketOutput = new StreamSocketOutput(filteredStream, memory);

            _log               = logger;
            _filteredStream    = filteredStream;
            _socketInputStream = new SocketInputStream(SocketInput);

            var block = memory.Lease();

            // Use pooled block for copy
            _filteredStream.CopyToAsync(_socketInputStream, block).ContinueWith((task, state) =>
            {
                var returnedBlock = task.Result;
                returnedBlock.Pool.Return(returnedBlock);

                ((FilteredStreamAdapter)state).OnStreamClose(task);
            }, this);
        }
        public void AddDoesNotAdvanceAtEndOfCurrentBlock()
        {
            using (var pool = new MemoryPool2())
            {
                var block1 = pool.Lease(256);
                var block2 = block1.Next = pool.Lease(256);

                block1.End += 100;
                block2.End += 200;

                var iter0   = block1.GetIterator();
                var iter100 = iter0.Add(100);

                var iter200a = iter0.Add(200);
                var iter200b = iter100.Add(100);

                var iter300a = iter0.Add(300);
                var iter300b = iter100.Add(200);
                var iter300c = iter200a.Add(100);

                var iter300a2 = iter300a.Add(1);
                var iter300b2 = iter300b.Add(1);
                var iter300c2 = iter300c.Add(1);

                AssertIterator(iter0, block1, block1.Start);
                AssertIterator(iter100, block1, block1.End);
                AssertIterator(iter200a, block2, block2.Start + 100);
                AssertIterator(iter200b, block2, block2.Start + 100);
                AssertIterator(iter300a, block2, block2.End);
                AssertIterator(iter300b, block2, block2.End);
                AssertIterator(iter300c, block2, block2.End);
                AssertIterator(iter300a2, block2, block2.End);
                AssertIterator(iter300b2, block2, block2.End);
                AssertIterator(iter300c2, block2, block2.End);
            }
        }
Example #16
0
 public SocketInput(MemoryPool2 memory)
 {
     _memory         = memory;
     _awaitableState = _awaitableIsNotCompleted;
 }
Example #17
0
        public void WritesDontGetCompletedTooQuickly()
        {
            // This should match _maxBytesPreCompleted in SocketOutput
            var maxBytesPreCompleted = 65536;
            var completeQueue        = new Queue <Action <int> >();
            var onWriteWh            = new ManualResetEventSlim();

            // Arrange
            var mockLibuv = new MockLibuv
            {
                OnWrite = (socket, buffers, triggerCompleted) =>
                {
                    completeQueue.Enqueue(triggerCompleted);
                    onWriteWh.Set();

                    return(0);
                }
            };

            using (var kestrelEngine = new KestrelEngine(mockLibuv, new TestServiceContext()))
                using (var memory = new MemoryPool2())
                {
                    kestrelEngine.Start(count: 1);

                    var kestrelThread = kestrelEngine.Threads[0];
                    var socket        = new MockSocket(kestrelThread.Loop.ThreadId, new TestKestrelTrace());
                    var trace         = new KestrelTrace(new TestKestrelTrace());
                    var ltp           = new LoggingThreadPool(trace);
                    var socketOutput  = new SocketOutput(kestrelThread, socket, memory, null, 0, trace, ltp, new Queue <UvWriteReq>());

                    var bufferSize = maxBytesPreCompleted;
                    var buffer     = new ArraySegment <byte>(new byte[bufferSize], 0, bufferSize);

                    var           completedWh = new ManualResetEventSlim();
                    Action <Task> onCompleted = (Task t) =>
                    {
                        Assert.Null(t.Exception);
                        completedWh.Set();
                    };

                    var           completedWh2 = new ManualResetEventSlim();
                    Action <Task> onCompleted2 = (Task t) =>
                    {
                        Assert.Null(t.Exception);
                        completedWh2.Set();
                    };

                    // Act (Pre-complete the maximum number of bytes in preparation for the rest of the test)
                    socketOutput.WriteAsync(buffer).ContinueWith(onCompleted);
                    // Assert
                    // The first write should pre-complete since it is <= _maxBytesPreCompleted.
                    Assert.True(completedWh.Wait(1000));
                    Assert.True(onWriteWh.Wait(1000));
                    // Arrange
                    completedWh.Reset();
                    onWriteWh.Reset();

                    // Act
                    socketOutput.WriteAsync(buffer).ContinueWith(onCompleted);
                    socketOutput.WriteAsync(buffer).ContinueWith(onCompleted2);

                    Assert.True(onWriteWh.Wait(1000));
                    completeQueue.Dequeue()(0);

                    // Assert
                    // Too many bytes are already pre-completed for the third but not the second write to pre-complete.
                    // https://github.com/aspnet/KestrelHttpServer/issues/356
                    Assert.True(completedWh.Wait(1000));
                    Assert.False(completedWh2.Wait(1000));

                    // Act
                    completeQueue.Dequeue()(0);

                    // Assert
                    // Finishing the first write should allow the second write to pre-complete.
                    Assert.True(completedWh2.Wait(1000));
                }
        }
Example #18
0
 public SocketInput(MemoryPool2 memory, IThreadPool threadPool)
 {
     _memory         = memory;
     _threadPool     = threadPool;
     _awaitableState = _awaitableIsNotCompleted;
 }
Example #19
0
 public MemoryPoolIterator2Tests()
 {
     _pool = new MemoryPool2();
 }
        public async Task ConcurrentReadsFailGracefully()
        {
            // Arrange
            var trace = new KestrelTrace(new TestKestrelTrace());
            var ltp   = new LoggingThreadPool(trace);

            using (var memory2 = new MemoryPool2())
            {
                var socketInput = new SocketInput(memory2, ltp);

                var task0Threw = false;
                var task1Threw = false;
                var task2Threw = false;


                var task0 = AwaitAsTaskAsync(socketInput);

                Assert.False(task0.IsFaulted);

                var task = task0.ContinueWith(
                    (t) =>
                {
                    TestConcurrentFaultedTask(t);
                    task0Threw = true;
                },
                    TaskContinuationOptions.OnlyOnFaulted);

                Assert.False(task0.IsFaulted);

                // Awaiting/continuing two tasks faults both

                var task1 = AwaitAsTaskAsync(socketInput);

                await task1.ContinueWith(
                    (t) =>
                {
                    TestConcurrentFaultedTask(t);
                    task1Threw = true;
                },
                    TaskContinuationOptions.OnlyOnFaulted);

                await task;

                Assert.True(task0.IsFaulted);
                Assert.True(task1.IsFaulted);

                Assert.True(task0Threw);
                Assert.True(task1Threw);

                // socket stays faulted

                var task2 = AwaitAsTaskAsync(socketInput);

                await task2.ContinueWith(
                    (t) =>
                {
                    TestConcurrentFaultedTask(t);
                    task2Threw = true;
                },
                    TaskContinuationOptions.OnlyOnFaulted);

                Assert.True(task2.IsFaulted);
                Assert.True(task2Threw);
            }
        }
Example #21
0
 public StreamSocketOutput(Stream outputStream, MemoryPool2 memory)
 {
     _outputStream = outputStream;
     _memory       = memory;
 }
Example #22
0
 public ListenerContext()
 {
     Memory2 = new MemoryPool2();
 }
Example #23
0
 public ListenerContext(ServiceContext serviceContext)
     : base(serviceContext)
 {
     Memory2 = new MemoryPool2();
 }
Example #24
0
 public ListenerContext(ServiceContext serviceContext)
     : base(serviceContext)
 {
     Memory2      = new MemoryPool2();
     WriteReqPool = new Queue <UvWriteReq>(SocketOutput.MaxPooledWriteReqs);
 }