merge preamble-output, socket-output
This commit is contained in:
parent
a3173c487a
commit
feb40402de
|
|
@ -68,13 +68,29 @@ namespace Microsoft.AspNet.Server.Kestrel.Filter
|
|||
|
||||
public override void Write(byte[] buffer, int offset, int count)
|
||||
{
|
||||
var segment = new ArraySegment<byte>(buffer, offset, count);
|
||||
ArraySegment<byte> segment;
|
||||
if (buffer != null)
|
||||
{
|
||||
segment = new ArraySegment<byte>(buffer, offset, count);
|
||||
}
|
||||
else
|
||||
{
|
||||
segment = default(ArraySegment<byte>);
|
||||
}
|
||||
_output.Write(segment);
|
||||
}
|
||||
|
||||
public override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken token)
|
||||
{
|
||||
var segment = new ArraySegment<byte>(buffer, offset, count);
|
||||
ArraySegment<byte> segment;
|
||||
if (buffer != null)
|
||||
{
|
||||
segment = new ArraySegment<byte>(buffer, offset, count);
|
||||
}
|
||||
else
|
||||
{
|
||||
segment = default(ArraySegment<byte>);
|
||||
}
|
||||
return _output.WriteAsync(segment, cancellationToken: token);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ namespace Microsoft.AspNet.Server.Kestrel.Filter
|
|||
returnBlock.Pool?.Return(returnBlock);
|
||||
}
|
||||
|
||||
_outputStream.Write(end.Block.Array, end.Block.Data.Offset, end.Index);
|
||||
_outputStream.Write(end.Block.Array, end.Block.Data.Offset, end.Index - end.Block.Data.Offset);
|
||||
end.Block.Pool?.Return(end.Block);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -623,8 +623,8 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
|||
bool appCompleted,
|
||||
bool immediate)
|
||||
{
|
||||
var memoryBlock = Memory2.Lease();
|
||||
var begin = memoryBlock.GetIterator();
|
||||
var begin = SocketOutput.ProducingStart();
|
||||
var count = 0;
|
||||
var end = begin;
|
||||
if (_keepAlive)
|
||||
{
|
||||
|
|
@ -673,48 +673,20 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
|||
_responseHeaders.SetRawConnection("keep-alive", _bytesConnectionKeepAlive);
|
||||
}
|
||||
|
||||
end.CopyFrom(_httpVersion == HttpVersionType.Http1_1 ? _bytesHttpVersion1_1 : _bytesHttpVersion1_0);
|
||||
end.CopyFrom(statusBytes);
|
||||
_responseHeaders.CopyTo(ref end);
|
||||
end.CopyFrom(_bytesEndHeaders, 0, _bytesEndHeaders.Length);
|
||||
count += end.CopyFrom(_httpVersion == HttpVersionType.Http1_1 ? _bytesHttpVersion1_1 : _bytesHttpVersion1_0);
|
||||
count += end.CopyFrom(statusBytes);
|
||||
count += _responseHeaders.CopyTo(ref end);
|
||||
count += end.CopyFrom(_bytesEndHeaders, 0, _bytesEndHeaders.Length);
|
||||
|
||||
// TODO: change this to SocketOutput.ProduceStart/ProduceComplete once that change is made
|
||||
var scan = begin.Block;
|
||||
while (scan.Next != null)
|
||||
{
|
||||
if (scan.Start != scan.End)
|
||||
{
|
||||
SocketOutput.WriteAsync(
|
||||
new ArraySegment<byte>(scan.Array, scan.Start, scan.End - scan.Start),
|
||||
false);
|
||||
}
|
||||
var next = scan.Next;
|
||||
Memory2.Return(scan);
|
||||
scan = next;
|
||||
}
|
||||
var writeTask = SocketOutput.WriteAsync(
|
||||
new ArraySegment<byte>(scan.Array, scan.Start, scan.End - scan.Start),
|
||||
immediate);
|
||||
SocketOutput.ProducingComplete(end, count);
|
||||
|
||||
if (writeTask.IsCompleted)
|
||||
if (immediate)
|
||||
{
|
||||
Memory2.Return(scan);
|
||||
return TaskUtilities.CompletedTask;
|
||||
return SocketOutput.WriteAsync(default(ArraySegment<byte>), immediate: true);
|
||||
}
|
||||
else
|
||||
{
|
||||
return writeTask.ContinueWith(
|
||||
(t, o) =>
|
||||
{
|
||||
var mb = (MemoryPoolBlock2)o;
|
||||
mb.Pool.Return(mb);
|
||||
|
||||
if (t.IsFaulted)
|
||||
{
|
||||
throw t.Exception;
|
||||
}
|
||||
},
|
||||
scan);
|
||||
return TaskUtilities.CompletedTask;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7821,15 +7821,16 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
|||
((ICollection<KeyValuePair<string, StringValues>>)MaybeUnknown)?.CopyTo(array, arrayIndex);
|
||||
}
|
||||
|
||||
protected void CopyToFast(ref MemoryPoolIterator2 output)
|
||||
protected int CopyToFast(ref MemoryPoolIterator2 output)
|
||||
{
|
||||
var count = 0;
|
||||
|
||||
if (((_bits & 1L) != 0))
|
||||
{
|
||||
foreach(var value in _CacheControl)
|
||||
{
|
||||
output.CopyFrom(_headerBytes, 0, 17);
|
||||
output.CopyFromAscii(value);
|
||||
count += output.CopyFrom(_headerBytes, 0, 17);
|
||||
count += output.CopyFromAscii(value);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -7837,12 +7838,12 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
|||
{
|
||||
if (_rawConnection != null)
|
||||
{
|
||||
output.CopyFrom(_rawConnection, 0, _rawConnection.Length);
|
||||
count += output.CopyFrom(_rawConnection, 0, _rawConnection.Length);
|
||||
} else
|
||||
foreach(var value in _Connection)
|
||||
{
|
||||
output.CopyFrom(_headerBytes, 17, 14);
|
||||
output.CopyFromAscii(value);
|
||||
count += output.CopyFrom(_headerBytes, 17, 14);
|
||||
count += output.CopyFromAscii(value);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -7850,12 +7851,12 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
|||
{
|
||||
if (_rawDate != null)
|
||||
{
|
||||
output.CopyFrom(_rawDate, 0, _rawDate.Length);
|
||||
count += output.CopyFrom(_rawDate, 0, _rawDate.Length);
|
||||
} else
|
||||
foreach(var value in _Date)
|
||||
{
|
||||
output.CopyFrom(_headerBytes, 31, 8);
|
||||
output.CopyFromAscii(value);
|
||||
count += output.CopyFrom(_headerBytes, 31, 8);
|
||||
count += output.CopyFromAscii(value);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -7863,8 +7864,8 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
|||
{
|
||||
foreach(var value in _KeepAlive)
|
||||
{
|
||||
output.CopyFrom(_headerBytes, 39, 14);
|
||||
output.CopyFromAscii(value);
|
||||
count += output.CopyFrom(_headerBytes, 39, 14);
|
||||
count += output.CopyFromAscii(value);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -7872,8 +7873,8 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
|||
{
|
||||
foreach(var value in _Pragma)
|
||||
{
|
||||
output.CopyFrom(_headerBytes, 53, 10);
|
||||
output.CopyFromAscii(value);
|
||||
count += output.CopyFrom(_headerBytes, 53, 10);
|
||||
count += output.CopyFromAscii(value);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -7881,8 +7882,8 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
|||
{
|
||||
foreach(var value in _Trailer)
|
||||
{
|
||||
output.CopyFrom(_headerBytes, 63, 11);
|
||||
output.CopyFromAscii(value);
|
||||
count += output.CopyFrom(_headerBytes, 63, 11);
|
||||
count += output.CopyFromAscii(value);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -7890,12 +7891,12 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
|||
{
|
||||
if (_rawTransferEncoding != null)
|
||||
{
|
||||
output.CopyFrom(_rawTransferEncoding, 0, _rawTransferEncoding.Length);
|
||||
count += output.CopyFrom(_rawTransferEncoding, 0, _rawTransferEncoding.Length);
|
||||
} else
|
||||
foreach(var value in _TransferEncoding)
|
||||
{
|
||||
output.CopyFrom(_headerBytes, 74, 21);
|
||||
output.CopyFromAscii(value);
|
||||
count += output.CopyFrom(_headerBytes, 74, 21);
|
||||
count += output.CopyFromAscii(value);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -7903,8 +7904,8 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
|||
{
|
||||
foreach(var value in _Upgrade)
|
||||
{
|
||||
output.CopyFrom(_headerBytes, 95, 11);
|
||||
output.CopyFromAscii(value);
|
||||
count += output.CopyFrom(_headerBytes, 95, 11);
|
||||
count += output.CopyFromAscii(value);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -7912,8 +7913,8 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
|||
{
|
||||
foreach(var value in _Via)
|
||||
{
|
||||
output.CopyFrom(_headerBytes, 106, 7);
|
||||
output.CopyFromAscii(value);
|
||||
count += output.CopyFrom(_headerBytes, 106, 7);
|
||||
count += output.CopyFromAscii(value);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -7921,8 +7922,8 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
|||
{
|
||||
foreach(var value in _Warning)
|
||||
{
|
||||
output.CopyFrom(_headerBytes, 113, 11);
|
||||
output.CopyFromAscii(value);
|
||||
count += output.CopyFrom(_headerBytes, 113, 11);
|
||||
count += output.CopyFromAscii(value);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -7930,8 +7931,8 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
|||
{
|
||||
foreach(var value in _Allow)
|
||||
{
|
||||
output.CopyFrom(_headerBytes, 124, 9);
|
||||
output.CopyFromAscii(value);
|
||||
count += output.CopyFrom(_headerBytes, 124, 9);
|
||||
count += output.CopyFromAscii(value);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -7939,12 +7940,12 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
|||
{
|
||||
if (_rawContentLength != null)
|
||||
{
|
||||
output.CopyFrom(_rawContentLength, 0, _rawContentLength.Length);
|
||||
count += output.CopyFrom(_rawContentLength, 0, _rawContentLength.Length);
|
||||
} else
|
||||
foreach(var value in _ContentLength)
|
||||
{
|
||||
output.CopyFrom(_headerBytes, 133, 18);
|
||||
output.CopyFromAscii(value);
|
||||
count += output.CopyFrom(_headerBytes, 133, 18);
|
||||
count += output.CopyFromAscii(value);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -7952,8 +7953,8 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
|||
{
|
||||
foreach(var value in _ContentType)
|
||||
{
|
||||
output.CopyFrom(_headerBytes, 151, 16);
|
||||
output.CopyFromAscii(value);
|
||||
count += output.CopyFrom(_headerBytes, 151, 16);
|
||||
count += output.CopyFromAscii(value);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -7961,8 +7962,8 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
|||
{
|
||||
foreach(var value in _ContentEncoding)
|
||||
{
|
||||
output.CopyFrom(_headerBytes, 167, 20);
|
||||
output.CopyFromAscii(value);
|
||||
count += output.CopyFrom(_headerBytes, 167, 20);
|
||||
count += output.CopyFromAscii(value);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -7970,8 +7971,8 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
|||
{
|
||||
foreach(var value in _ContentLanguage)
|
||||
{
|
||||
output.CopyFrom(_headerBytes, 187, 20);
|
||||
output.CopyFromAscii(value);
|
||||
count += output.CopyFrom(_headerBytes, 187, 20);
|
||||
count += output.CopyFromAscii(value);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -7979,8 +7980,8 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
|||
{
|
||||
foreach(var value in _ContentLocation)
|
||||
{
|
||||
output.CopyFrom(_headerBytes, 207, 20);
|
||||
output.CopyFromAscii(value);
|
||||
count += output.CopyFrom(_headerBytes, 207, 20);
|
||||
count += output.CopyFromAscii(value);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -7988,8 +7989,8 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
|||
{
|
||||
foreach(var value in _ContentMD5)
|
||||
{
|
||||
output.CopyFrom(_headerBytes, 227, 15);
|
||||
output.CopyFromAscii(value);
|
||||
count += output.CopyFrom(_headerBytes, 227, 15);
|
||||
count += output.CopyFromAscii(value);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -7997,8 +7998,8 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
|||
{
|
||||
foreach(var value in _ContentRange)
|
||||
{
|
||||
output.CopyFrom(_headerBytes, 242, 17);
|
||||
output.CopyFromAscii(value);
|
||||
count += output.CopyFrom(_headerBytes, 242, 17);
|
||||
count += output.CopyFromAscii(value);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -8006,8 +8007,8 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
|||
{
|
||||
foreach(var value in _Expires)
|
||||
{
|
||||
output.CopyFrom(_headerBytes, 259, 11);
|
||||
output.CopyFromAscii(value);
|
||||
count += output.CopyFrom(_headerBytes, 259, 11);
|
||||
count += output.CopyFromAscii(value);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -8015,8 +8016,8 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
|||
{
|
||||
foreach(var value in _LastModified)
|
||||
{
|
||||
output.CopyFrom(_headerBytes, 270, 17);
|
||||
output.CopyFromAscii(value);
|
||||
count += output.CopyFrom(_headerBytes, 270, 17);
|
||||
count += output.CopyFromAscii(value);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -8024,8 +8025,8 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
|||
{
|
||||
foreach(var value in _AcceptRanges)
|
||||
{
|
||||
output.CopyFrom(_headerBytes, 287, 17);
|
||||
output.CopyFromAscii(value);
|
||||
count += output.CopyFrom(_headerBytes, 287, 17);
|
||||
count += output.CopyFromAscii(value);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -8033,8 +8034,8 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
|||
{
|
||||
foreach(var value in _Age)
|
||||
{
|
||||
output.CopyFrom(_headerBytes, 304, 7);
|
||||
output.CopyFromAscii(value);
|
||||
count += output.CopyFrom(_headerBytes, 304, 7);
|
||||
count += output.CopyFromAscii(value);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -8042,8 +8043,8 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
|||
{
|
||||
foreach(var value in _ETag)
|
||||
{
|
||||
output.CopyFrom(_headerBytes, 311, 8);
|
||||
output.CopyFromAscii(value);
|
||||
count += output.CopyFrom(_headerBytes, 311, 8);
|
||||
count += output.CopyFromAscii(value);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -8051,8 +8052,8 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
|||
{
|
||||
foreach(var value in _Location)
|
||||
{
|
||||
output.CopyFrom(_headerBytes, 319, 12);
|
||||
output.CopyFromAscii(value);
|
||||
count += output.CopyFrom(_headerBytes, 319, 12);
|
||||
count += output.CopyFromAscii(value);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -8060,8 +8061,8 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
|||
{
|
||||
foreach(var value in _ProxyAutheticate)
|
||||
{
|
||||
output.CopyFrom(_headerBytes, 331, 21);
|
||||
output.CopyFromAscii(value);
|
||||
count += output.CopyFrom(_headerBytes, 331, 21);
|
||||
count += output.CopyFromAscii(value);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -8069,8 +8070,8 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
|||
{
|
||||
foreach(var value in _RetryAfter)
|
||||
{
|
||||
output.CopyFrom(_headerBytes, 352, 15);
|
||||
output.CopyFromAscii(value);
|
||||
count += output.CopyFrom(_headerBytes, 352, 15);
|
||||
count += output.CopyFromAscii(value);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -8078,12 +8079,12 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
|||
{
|
||||
if (_rawServer != null)
|
||||
{
|
||||
output.CopyFrom(_rawServer, 0, _rawServer.Length);
|
||||
count += output.CopyFrom(_rawServer, 0, _rawServer.Length);
|
||||
} else
|
||||
foreach(var value in _Server)
|
||||
{
|
||||
output.CopyFrom(_headerBytes, 367, 10);
|
||||
output.CopyFromAscii(value);
|
||||
count += output.CopyFrom(_headerBytes, 367, 10);
|
||||
count += output.CopyFromAscii(value);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -8091,8 +8092,8 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
|||
{
|
||||
foreach(var value in _SetCookie)
|
||||
{
|
||||
output.CopyFrom(_headerBytes, 377, 14);
|
||||
output.CopyFromAscii(value);
|
||||
count += output.CopyFrom(_headerBytes, 377, 14);
|
||||
count += output.CopyFromAscii(value);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -8100,8 +8101,8 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
|||
{
|
||||
foreach(var value in _Vary)
|
||||
{
|
||||
output.CopyFrom(_headerBytes, 391, 8);
|
||||
output.CopyFromAscii(value);
|
||||
count += output.CopyFrom(_headerBytes, 391, 8);
|
||||
count += output.CopyFromAscii(value);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -8109,11 +8110,12 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
|||
{
|
||||
foreach(var value in _WWWAuthenticate)
|
||||
{
|
||||
output.CopyFrom(_headerBytes, 399, 20);
|
||||
output.CopyFromAscii(value);
|
||||
count += output.CopyFrom(_headerBytes, 399, 20);
|
||||
count += output.CopyFromAscii(value);
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
public unsafe void Append(byte[] keyBytes, int keyOffset, int keyLength, string value)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
|||
{
|
||||
public partial class FrameResponseHeaders : FrameHeaders
|
||||
{
|
||||
private static byte[] _CRLF = new[] { (byte)'\r', (byte)'\n' };
|
||||
private static byte[] _CrLf = new[] { (byte)'\r', (byte)'\n' };
|
||||
private static byte[] _colonSpace = new[] { (byte)':', (byte)' ' };
|
||||
|
||||
public bool HasConnection => HeaderConnection.Count != 0;
|
||||
|
|
@ -30,22 +30,23 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
|||
return GetEnumerator();
|
||||
}
|
||||
|
||||
public void CopyTo(ref MemoryPoolIterator2 output)
|
||||
public int CopyTo(ref MemoryPoolIterator2 output)
|
||||
{
|
||||
CopyToFast(ref output);
|
||||
var count = CopyToFast(ref output);
|
||||
if (MaybeUnknown != null)
|
||||
{
|
||||
foreach (var kv in MaybeUnknown)
|
||||
{
|
||||
foreach (var value in kv.Value)
|
||||
{
|
||||
output.CopyFrom(_CRLF, 0, 2);
|
||||
output.CopyFromAscii(kv.Key);
|
||||
output.CopyFrom(_colonSpace, 0, 2);
|
||||
output.CopyFromAscii(value);
|
||||
count += output.CopyFrom(_CrLf, 0, 2);
|
||||
count += output.CopyFromAscii(kv.Key);
|
||||
count += output.CopyFrom(_colonSpace, 0, 2);
|
||||
count += output.CopyFromAscii(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
public partial struct Enumerator : IEnumerator<KeyValuePair<string, StringValues>>
|
||||
|
|
|
|||
|
|
@ -70,11 +70,13 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
|||
bool socketShutdownSend = false,
|
||||
bool socketDisconnect = false)
|
||||
{
|
||||
var tail = ProducingStart();
|
||||
tail = tail.CopyFrom(buffer);
|
||||
// We do our own accounting below
|
||||
ProducingComplete(tail, count: 0);
|
||||
|
||||
if (buffer.Count > 0)
|
||||
{
|
||||
var tail = ProducingStart();
|
||||
tail.CopyFrom(buffer);
|
||||
// We do our own accounting below
|
||||
ProducingComplete(tail, count: 0);
|
||||
}
|
||||
TaskCompletionSource<object> tcs = null;
|
||||
|
||||
lock (_contextLock)
|
||||
|
|
|
|||
|
|
@ -532,7 +532,17 @@ namespace Microsoft.AspNet.Server.Kestrel.Infrastructure
|
|||
}
|
||||
}
|
||||
|
||||
public MemoryPoolIterator2 CopyFrom(ArraySegment<byte> buffer)
|
||||
public int CopyFrom(byte[] data)
|
||||
{
|
||||
return CopyFrom(new ArraySegment<byte>(data));
|
||||
}
|
||||
|
||||
public int CopyFrom(byte[] data, int offset, int count)
|
||||
{
|
||||
return CopyFrom(new ArraySegment<byte>(data, offset, count));
|
||||
}
|
||||
|
||||
public int CopyFrom(ArraySegment<byte> buffer)
|
||||
{
|
||||
Debug.Assert(_block != null);
|
||||
Debug.Assert(_block.Pool != null);
|
||||
|
|
@ -545,11 +555,10 @@ namespace Microsoft.AspNet.Server.Kestrel.Infrastructure
|
|||
|
||||
var bufferIndex = buffer.Offset;
|
||||
var remaining = buffer.Count;
|
||||
var bytesLeftInBlock = block.Data.Offset + block.Data.Count - blockIndex;
|
||||
|
||||
while (remaining > 0)
|
||||
{
|
||||
var bytesLeftInBlock = block.Data.Offset + block.Data.Count - blockIndex;
|
||||
|
||||
if (bytesLeftInBlock == 0)
|
||||
{
|
||||
var nextBlock = pool.Lease();
|
||||
|
|
@ -560,93 +569,55 @@ namespace Microsoft.AspNet.Server.Kestrel.Infrastructure
|
|||
bytesLeftInBlock = block.Data.Count;
|
||||
}
|
||||
|
||||
var bytesToCopy = Math.Min(remaining, bytesLeftInBlock);
|
||||
var bytesToCopy = remaining < bytesLeftInBlock ? remaining : bytesLeftInBlock;
|
||||
|
||||
Buffer.BlockCopy(buffer.Array, bufferIndex, block.Array, blockIndex, bytesToCopy);
|
||||
|
||||
blockIndex += bytesToCopy;
|
||||
bufferIndex += bytesToCopy;
|
||||
remaining -= bytesToCopy;
|
||||
bytesLeftInBlock -= bytesToCopy;
|
||||
block.End = blockIndex;
|
||||
}
|
||||
|
||||
return new MemoryPoolIterator2(block, blockIndex);
|
||||
_block = block;
|
||||
_index = blockIndex;
|
||||
|
||||
return buffer.Count;
|
||||
}
|
||||
|
||||
public void CopyFrom(byte[] data)
|
||||
{
|
||||
CopyFrom(data, 0, data.Length);
|
||||
}
|
||||
|
||||
public void CopyFrom(byte[] data, int offset, int count)
|
||||
public unsafe int CopyFromAscii(string data)
|
||||
{
|
||||
Debug.Assert(_block != null);
|
||||
Debug.Assert(_block.Pool != null);
|
||||
Debug.Assert(_block.Next == null);
|
||||
Debug.Assert(_block.End == _index);
|
||||
|
||||
var pool = _block.Pool;
|
||||
var block = _block;
|
||||
var blockIndex = _index;
|
||||
var length = data.Length;
|
||||
|
||||
var sourceData = data;
|
||||
var sourceStart = offset;
|
||||
var sourceEnd = offset + count;
|
||||
|
||||
var targetData = block.Array;
|
||||
var targetStart = block.End;
|
||||
var targetEnd = block.Data.Offset + block.Data.Count;
|
||||
|
||||
while (true)
|
||||
{
|
||||
// actual count to copy is remaining data, or unused trailing space in the current block, whichever is smaller
|
||||
var copyCount = Math.Min(sourceEnd - sourceStart, targetEnd - targetStart);
|
||||
|
||||
Buffer.BlockCopy(sourceData, sourceStart, targetData, targetStart, copyCount);
|
||||
sourceStart += copyCount;
|
||||
targetStart += copyCount;
|
||||
|
||||
// if this means all source data has been copied
|
||||
if (sourceStart == sourceEnd)
|
||||
{
|
||||
// increase occupied space in the block, and adjust iterator at start of unused trailing space
|
||||
block.End = targetStart;
|
||||
_block = block;
|
||||
_index = targetStart;
|
||||
return;
|
||||
}
|
||||
|
||||
// otherwise another block needs to be allocated to follow this one
|
||||
block.Next = block.Pool.Lease();
|
||||
block = block.Next;
|
||||
|
||||
targetData = block.Array;
|
||||
targetStart = block.End;
|
||||
targetEnd = block.Data.Offset + block.Data.Count;
|
||||
}
|
||||
}
|
||||
|
||||
public unsafe void CopyFromAscii(string data)
|
||||
{
|
||||
Debug.Assert(_block.Next == null);
|
||||
Debug.Assert(_block.End == _index);
|
||||
|
||||
var block = _block;
|
||||
|
||||
var inputLength = data.Length;
|
||||
var inputLengthMinusSpan = inputLength - 3;
|
||||
var bytesLeftInBlock = block.Data.Offset + block.Data.Count - blockIndex;
|
||||
var bytesLeftInBlockMinusSpan = bytesLeftInBlock - 3;
|
||||
|
||||
fixed (char* pData = data)
|
||||
{
|
||||
var input = pData;
|
||||
var inputEnd = pData + data.Length;
|
||||
var blockRemaining = block.Data.Offset + block.Data.Count - block.End;
|
||||
var blockRemainingMinusSpan = blockRemaining - 3;
|
||||
var inputEnd = pData + length;
|
||||
var inputEndMinusSpan = inputEnd - 3;
|
||||
|
||||
while (input < inputEnd)
|
||||
{
|
||||
if (blockRemaining == 0)
|
||||
if (bytesLeftInBlock == 0)
|
||||
{
|
||||
block.Next = block.Pool.Lease();
|
||||
block = block.Next;
|
||||
blockRemaining = block.Data.Count;
|
||||
blockRemainingMinusSpan = blockRemaining - 3;
|
||||
var nextBlock = pool.Lease();
|
||||
block.Next = nextBlock;
|
||||
block = nextBlock;
|
||||
|
||||
blockIndex = block.Data.Offset;
|
||||
bytesLeftInBlock = block.Data.Count;
|
||||
bytesLeftInBlockMinusSpan = bytesLeftInBlock - 3;
|
||||
}
|
||||
|
||||
fixed (byte* pOutput = block.Data.Array)
|
||||
|
|
@ -654,7 +625,7 @@ namespace Microsoft.AspNet.Server.Kestrel.Infrastructure
|
|||
var output = pOutput + block.End;
|
||||
|
||||
var copied = 0;
|
||||
for (; copied < inputLengthMinusSpan && copied < blockRemainingMinusSpan; copied += 4)
|
||||
for (; input < inputEndMinusSpan && copied < bytesLeftInBlockMinusSpan; copied += 4)
|
||||
{
|
||||
*(output) = (byte)*(input);
|
||||
*(output + 1) = (byte)*(input + 1);
|
||||
|
|
@ -662,19 +633,24 @@ namespace Microsoft.AspNet.Server.Kestrel.Infrastructure
|
|||
*(output + 3) = (byte)*(input + 3);
|
||||
output += 4;
|
||||
input += 4;
|
||||
blockRemainingMinusSpan -= 4;
|
||||
}
|
||||
for (; copied < inputLength && copied < blockRemaining; copied++)
|
||||
for (; input < inputEnd && copied < bytesLeftInBlock; copied++)
|
||||
{
|
||||
*(output++) = (byte)*(input++);
|
||||
blockRemaining--;
|
||||
}
|
||||
block.End += copied;
|
||||
_block = block;
|
||||
_index = block.End;
|
||||
|
||||
blockIndex += copied;
|
||||
bytesLeftInBlockMinusSpan -= copied;
|
||||
bytesLeftInBlock -= copied;
|
||||
}
|
||||
block.End = blockIndex;
|
||||
}
|
||||
}
|
||||
|
||||
_block = block;
|
||||
_index = blockIndex;
|
||||
|
||||
return length;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -159,7 +159,8 @@ namespace Microsoft.AspNet.Server.KestrelTests
|
|||
using (var pool = new MemoryPool2())
|
||||
{
|
||||
var block1 = pool.Lease(128);
|
||||
var iterator = block1.GetIterator();
|
||||
var start = block1.GetIterator();
|
||||
var end = start;
|
||||
var bufferSize = block1.Data.Count * 3;
|
||||
var buffer = new byte[bufferSize];
|
||||
|
||||
|
|
@ -170,18 +171,18 @@ namespace Microsoft.AspNet.Server.KestrelTests
|
|||
|
||||
Assert.Null(block1.Next);
|
||||
|
||||
var end = iterator.CopyFrom(new ArraySegment<byte>(buffer));
|
||||
end.CopyFrom(new ArraySegment<byte>(buffer));
|
||||
|
||||
Assert.NotNull(block1.Next);
|
||||
|
||||
for (int i = 0; i < bufferSize; i++)
|
||||
{
|
||||
Assert.Equal(i % 73, iterator.Take());
|
||||
Assert.Equal(i % 73, start.Take());
|
||||
}
|
||||
|
||||
Assert.Equal(-1, iterator.Take());
|
||||
Assert.Equal(iterator.Block, end.Block);
|
||||
Assert.Equal(iterator.Index, end.Index);
|
||||
Assert.Equal(-1, start.Take());
|
||||
Assert.Equal(start.Block, end.Block);
|
||||
Assert.Equal(start.Index, end.Index);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -380,22 +380,24 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
|||
((ICollection<KeyValuePair<string, StringValues>>)MaybeUnknown)?.CopyTo(array, arrayIndex);
|
||||
}}
|
||||
{(loop.ClassName == "FrameResponseHeaders" ? $@"
|
||||
protected void CopyToFast(ref MemoryPoolIterator2 output)
|
||||
protected int CopyToFast(ref MemoryPoolIterator2 output)
|
||||
{{
|
||||
var count = 0;
|
||||
{Each(loop.Headers, header => $@"
|
||||
if ({header.TestBit()})
|
||||
{{ {(header.EnhancedSetter == false ? "" : $@"
|
||||
if (_raw{header.Identifier} != null)
|
||||
{{
|
||||
output.CopyFromAscii(_raw{header.Identifier}, 0, _raw{header.Identifier}.Length);
|
||||
count += output.CopyFrom(_raw{header.Identifier}, 0, _raw{header.Identifier}.Length);
|
||||
}} else ")}
|
||||
foreach(var value in _{header.Identifier})
|
||||
{{
|
||||
output.CopyFromAscii(_headerBytes, {header.BytesOffset}, {header.BytesCount});
|
||||
output.CopyFromAscii(value);
|
||||
count += output.CopyFrom(_headerBytes, {header.BytesOffset}, {header.BytesCount});
|
||||
count += output.CopyFromAscii(value);
|
||||
}}
|
||||
}}
|
||||
")}
|
||||
return count;
|
||||
}}" : "")}
|
||||
public unsafe void Append(byte[] keyBytes, int keyOffset, int keyLength, string value)
|
||||
{{
|
||||
|
|
|
|||
Loading…
Reference in New Issue