Rename Prefix to UrlPrefix. Seperate IServerInformation to its own implementation.

This commit is contained in:
Chris Ross 2014-03-24 09:44:12 -07:00
parent eb27892470
commit 546af5ddee
10 changed files with 95 additions and 106 deletions

View File

@ -70,7 +70,7 @@ namespace Microsoft.AspNet.Server.WebListener
private object _internalLock;
private List<Prefix> _uriPrefixes = new List<Prefix>();
private List<UrlPrefix> _urlPrefixes = new List<UrlPrefix>();
// The native request queue
private long? _requestQueueLength;
@ -105,9 +105,9 @@ namespace Microsoft.AspNet.Server.WebListener
get { return _logger; }
}
public List<Prefix> UriPrefixes
public List<UrlPrefix> UrlPrefixes
{
get { return _uriPrefixes; }
get { return _urlPrefixes; }
}
internal SafeHandle RequestQueueHandle
@ -247,12 +247,12 @@ namespace Microsoft.AspNet.Server.WebListener
{
CheckDisposed();
// go through the uri list and unregister for each one of them
if (_uriPrefixes.Count > 0)
if (_urlPrefixes.Count > 0)
{
LogHelper.LogInfo(_logger, "RemoveAll");
if (_state == State.Started)
{
foreach (Prefix registeredPrefix in _uriPrefixes)
foreach (UrlPrefix registeredPrefix in _urlPrefixes)
{
// ignore possible failures
InternalRemovePrefix(registeredPrefix.Whole);
@ -261,7 +261,7 @@ namespace Microsoft.AspNet.Server.WebListener
if (clear)
{
_uriPrefixes.Clear();
_urlPrefixes.Clear();
}
}
}
@ -605,12 +605,12 @@ namespace Microsoft.AspNet.Server.WebListener
private void AddAllPrefixes()
{
// go through the uri list and register for each one of them
if (_uriPrefixes.Count > 0)
if (_urlPrefixes.Count > 0)
{
for (int i = 0; i < _uriPrefixes.Count; i++)
for (int i = 0; i < _urlPrefixes.Count; i++)
{
// We'll get this index back on each request and use it to look up the prefix to calculate PathBase.
Prefix registeredPrefix = _uriPrefixes[i];
UrlPrefix registeredPrefix = _urlPrefixes[i];
uint statusCode = InternalAddPrefix(registeredPrefix.Whole, i);
if (statusCode != UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS)
{

View File

@ -1,28 +0,0 @@
// <copyright file="PumpLimits.cs" company="Katana contributors">
// Copyright 2011-2012 Katana contributors
// </copyright>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
namespace Microsoft.AspNet.Server.WebListener
{
internal struct PumpLimits
{
internal PumpLimits(int maxAccepts)
{
MaxOutstandingAccepts = maxAccepts;
}
internal readonly int MaxOutstandingAccepts;
}
}

View File

@ -90,7 +90,7 @@ namespace Microsoft.AspNet.Server.WebListener
_cookedUrlQuery = Marshal.PtrToStringUni((IntPtr)cookedUrl.pQueryString, cookedUrl.QueryStringLength / 2);
}
Prefix prefix = httpContext.Server.UriPrefixes[(int)_contextId];
UrlPrefix prefix = httpContext.Server.UrlPrefixes[(int)_contextId];
string orriginalPath = RequestPath;
// These paths are both unescaped already.

View File

@ -51,7 +51,7 @@ namespace Microsoft.AspNet.Server.WebListener
{
OwinWebListener listener = new OwinWebListener();
ParseAddresses(configuration, listener);
return new WebListenerWrapper(listener, _loggerFactory);
return new ServerInformation(new WebListenerWrapper(listener, _loggerFactory));
}
/// <summary>
@ -70,16 +70,16 @@ namespace Microsoft.AspNet.Server.WebListener
throw new ArgumentNullException("app");
}
WebListenerWrapper wrapper = server as WebListenerWrapper;
if (wrapper == null)
var serverInfo = server as ServerInformation;
if (serverInfo == null)
{
throw new ArgumentException("server");
}
// TODO: var capabilities = new Dictionary<string, object>();
wrapper.Start(app);
return wrapper;
serverInfo.Wrapper.Start(app);
return serverInfo.Wrapper;
}
private void ParseAddresses(IConfiguration config, OwinWebListener listener)
@ -90,7 +90,7 @@ namespace Microsoft.AspNet.Server.WebListener
{
foreach (var value in urls.Split(';'))
{
listener.UriPrefixes.Add(Prefix.Create(value));
listener.UrlPrefixes.Add(UrlPrefix.Create(value));
}
}
// TODO: look for just a port option?

View File

@ -0,0 +1,37 @@
using System.Reflection;
using Microsoft.AspNet.Abstractions;
namespace Microsoft.AspNet.Server.WebListener
{
public class ServerInformation : IServerInformation
{
private WebListenerWrapper _webListenerWrapper;
internal ServerInformation(WebListenerWrapper webListenerWrapper)
{
_webListenerWrapper = webListenerWrapper;
}
internal WebListenerWrapper Wrapper
{
get { return _webListenerWrapper; }
}
// Microsoft.AspNet.Server.WebListener
public string Name
{
get { return GetType().GetTypeInfo().Assembly.GetName().Name; }
}
public OwinWebListener Listener
{
get { return _webListenerWrapper.Listener; }
}
public int MaxAccepts
{
get { return _webListenerWrapper.MaxAccepts; }
set { _webListenerWrapper.MaxAccepts = value; }
}
}
}

View File

@ -1,5 +1,5 @@
//------------------------------------------------------------------------------
// <copyright file="HttpListener.cs" company="Microsoft">
// <copyright file="UrlPrefix.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//------------------------------------------------------------------------------
@ -9,9 +9,9 @@ using System.Globalization;
namespace Microsoft.AspNet.Server.WebListener
{
public class Prefix
public class UrlPrefix
{
private Prefix(bool isHttps, string scheme, string host, string port, int portValue, string path)
private UrlPrefix(bool isHttps, string scheme, string host, string port, int portValue, string path)
{
IsHttps = isHttps;
Scheme = scheme;
@ -29,7 +29,7 @@ namespace Microsoft.AspNet.Server.WebListener
/// <param name="host">+, *, IPv4, [IPv6], or a dns name. Http.Sys does not permit punycode (xn--), use Unicode instead.</param>
/// <param name="port">If empty, the default port for the given scheme will be used (80 or 443).</param>
/// <param name="path">Should start and end with a '/', though a missing trailing slash will be added. This value must be un-escaped.</param>
public static Prefix Create(string scheme, string host, string port, string path)
public static UrlPrefix Create(string scheme, string host, string port, string path)
{
bool isHttps;
if (string.Equals(Constants.HttpScheme, scheme, StringComparison.OrdinalIgnoreCase))
@ -73,10 +73,10 @@ namespace Microsoft.AspNet.Server.WebListener
path += "/";
}
return new Prefix(isHttps, scheme, host, port, portValue, path);
return new UrlPrefix(isHttps, scheme, host, port, portValue, path);
}
public static Prefix Create(string prefix)
public static UrlPrefix Create(string prefix)
{
string scheme = null;
string host = null;
@ -118,7 +118,7 @@ namespace Microsoft.AspNet.Server.WebListener
}
path = whole.Substring(delimiterStart3);
return Prefix.Create(scheme, host, port, path);
return UrlPrefix.Create(scheme, host, port, path);
}
public bool IsHttps { get; private set; }

View File

@ -1,18 +1,14 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Diagnostics.Contracts;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNet.Abstractions;
using Microsoft.AspNet.Logging;
namespace Microsoft.AspNet.Server.WebListener
{
using AppFunc = Func<object, Task>;
public class WebListenerWrapper : IServerInformation, IDisposable
internal class WebListenerWrapper : IDisposable
{
private static readonly int DefaultMaxAccepts = 5 * Environment.ProcessorCount;
@ -21,7 +17,7 @@ namespace Microsoft.AspNet.Server.WebListener
private AppFunc _appFunc;
private PumpLimits _pumpLimits;
private int _maxAccepts;
private int _acceptorCounts;
private Action<object> _processRequest;
@ -34,18 +30,28 @@ namespace Microsoft.AspNet.Server.WebListener
_logger = LogHelper.CreateLogger(loggerFactory, typeof(WebListenerWrapper));
_processRequest = new Action<object>(ProcessRequestAsync);
_pumpLimits = new PumpLimits(DefaultMaxAccepts);
_maxAccepts = DefaultMaxAccepts;
}
public OwinWebListener Listener
internal OwinWebListener Listener
{
get { return _listener; }
}
// Microsoft.AspNet.Server.WebListener
public string Name
internal int MaxAccepts
{
get { return GetType().GetTypeInfo().Assembly.GetName().Name; }
get
{
return _maxAccepts;
}
set
{
_maxAccepts = value;
if (_listener.IsListening)
{
ActivateRequestProcessingLimits();
}
}
}
internal void Start(AppFunc app)
@ -57,7 +63,7 @@ namespace Microsoft.AspNet.Server.WebListener
_appFunc = app;
if (_listener.UriPrefixes.Count == 0)
if (_listener.UrlPrefixes.Count == 0)
{
throw new InvalidOperationException("No address prefixes were defined.");
}
@ -69,40 +75,14 @@ namespace Microsoft.AspNet.Server.WebListener
ActivateRequestProcessingLimits();
}
/// <summary>
/// These are merged as one operation because they should be swapped out atomically.
/// This controls how many requests the server attempts to process concurrently.
/// </summary>
/// <param name="maxAccepts">The maximum number of pending accepts.</param>
public void SetRequestProcessingLimits(int maxAccepts)
{
_pumpLimits = new PumpLimits(maxAccepts);
if (_listener.IsListening)
{
ActivateRequestProcessingLimits();
}
}
private void ActivateRequestProcessingLimits()
{
for (int i = _acceptorCounts; i < _pumpLimits.MaxOutstandingAccepts; i++)
for (int i = _acceptorCounts; i < MaxAccepts; i++)
{
ProcessRequestsWorker();
}
}
/// <summary>
/// Gets the request processing limits.
/// </summary>
/// <param name="maxAccepts">The maximum number of pending accepts.</param>
[SuppressMessage("Microsoft.Design", "CA1021:AvoidOutParameters", MessageId = "0#", Justification = "By design")]
public void GetRequestProcessingLimits(out int maxAccepts)
{
PumpLimits limits = _pumpLimits;
maxAccepts = limits.MaxOutstandingAccepts;
}
// The message pump.
// When we start listening for the next request on one thread, we may need to be sure that the
// completion continues on another thread as to not block the current request processing.
@ -110,7 +90,7 @@ namespace Microsoft.AspNet.Server.WebListener
private async void ProcessRequestsWorker()
{
int workerIndex = Interlocked.Increment(ref _acceptorCounts);
while (_listener.IsListening && workerIndex <= _pumpLimits.MaxOutstandingAccepts)
while (_listener.IsListening && workerIndex <= MaxAccepts)
{
// Receive a request
RequestContext requestContext;

View File

@ -150,15 +150,15 @@ namespace Microsoft.AspNet.Server.WebListener.Test
private IDisposable CreateServer(AppFunc app)
{
var factory = new ServerFactory(null);
var wrapper = (WebListenerWrapper)factory.Initialize(null);
var factory = new ServerFactory(loggerFactory: null);
var serverInfo = (ServerInformation)factory.Initialize(configuration: null);
foreach (string path in new[] { "/", "/11", "/2/3", "/2", "/11/2" })
{
wrapper.Listener.UriPrefixes.Add(Prefix.Create("http", "localhost", "8080", path));
serverInfo.Listener.UrlPrefixes.Add(UrlPrefix.Create("http", "localhost", "8080", path));
}
return factory.Start(wrapper, app);
return factory.Start(serverInfo, app);
}
private async Task<string> SendRequestAsync(string uri)

View File

@ -116,7 +116,7 @@ namespace Microsoft.AspNet.Server.WebListener.Test
requestTasks.Add(requestTask);
}
bool success = Task.WaitAll(requestTasks.ToArray(), TimeSpan.FromSeconds(5));
bool success = Task.WaitAll(requestTasks.ToArray(), TimeSpan.FromSeconds(10));
if (!success)
{
Console.WriteLine();
@ -191,13 +191,13 @@ namespace Microsoft.AspNet.Server.WebListener.Test
[Fact]
public async Task Server_SetQueueLimit_Success()
{
var factory = new ServerFactory(null);
var wrapper = (WebListenerWrapper)factory.Initialize(null);
wrapper.Listener.UriPrefixes.Add(Prefix.Create("http://localhost:8080"));
var factory = new ServerFactory(loggerFactory: null);
var serverInfo = (ServerInformation)factory.Initialize(configuration: null);
serverInfo.Listener.UrlPrefixes.Add(UrlPrefix.Create("http://localhost:8080"));
wrapper.Listener.SetRequestQueueLimit(1001);
serverInfo.Listener.SetRequestQueueLimit(1001);
using (factory.Start(wrapper, env => Task.FromResult(0)))
using (factory.Start(serverInfo, env => Task.FromResult(0)))
{
string response = await SendRequestAsync(Address);
Assert.Equal(string.Empty, response);

View File

@ -32,12 +32,12 @@ namespace Microsoft.AspNet.Server.WebListener.Test
internal static IDisposable CreateServer(string scheme, string host, string port, string path, AuthenticationType authType, AppFunc app)
{
ServerFactory factory = new ServerFactory(null);
WebListenerWrapper wrapper = (WebListenerWrapper)factory.Initialize(null);
wrapper.Listener.UriPrefixes.Add(Prefix.Create(scheme, host, port, path));
wrapper.Listener.AuthenticationManager.AuthenticationTypes = authType;
var factory = new ServerFactory(loggerFactory: null);
var serverInfo = (ServerInformation)factory.Initialize(configuration: null);
serverInfo.Listener.UrlPrefixes.Add(UrlPrefix.Create(scheme, host, port, path));
serverInfo.Listener.AuthenticationManager.AuthenticationTypes = authType;
return factory.Start(wrapper, app);
return factory.Start(serverInfo, app);
}
}
}