//------------------------------------------------------------------------------ // // Copyright (c) Microsoft Corporation. All rights reserved. // //------------------------------------------------------------------------------ namespace System.Web.Configuration { using System; using System.Xml; using System.Configuration; using System.Collections.Specialized; using System.Collections; using System.Globalization; using System.IO; using System.Text; using System.ComponentModel; using System.Web.Util; using System.Security.Permissions; /* */ public sealed class ProcessModelSection : ConfigurationSection { private const int DefaultMaxThreadsPerCPU = 100; private static readonly ConfigurationElementProperty s_elemProperty = new ConfigurationElementProperty(new CallbackValidator(typeof(ProcessModelSection), Validate)); internal static TimeSpan DefaultClientConnectedCheck = new TimeSpan(0, 0, 5); private static ConfigurationPropertyCollection _properties; private static readonly ConfigurationProperty _propEnable = new ConfigurationProperty("enable", typeof(bool), true, ConfigurationPropertyOptions.None); private static readonly ConfigurationProperty _propTimeout = new ConfigurationProperty("timeout", typeof(TimeSpan), TimeSpan.MaxValue, StdValidatorsAndConverters.InfiniteTimeSpanConverter, null, ConfigurationPropertyOptions.None); private static readonly ConfigurationProperty _propIdleTimeout = new ConfigurationProperty("idleTimeout", typeof(TimeSpan), TimeSpan.MaxValue, StdValidatorsAndConverters.InfiniteTimeSpanConverter, null, ConfigurationPropertyOptions.None); private static readonly ConfigurationProperty _propShutdownTimeout = new ConfigurationProperty("shutdownTimeout", typeof(TimeSpan), TimeSpan.FromSeconds(5), StdValidatorsAndConverters.InfiniteTimeSpanConverter, StdValidatorsAndConverters.PositiveTimeSpanValidator, ConfigurationPropertyOptions.None); private static readonly ConfigurationProperty _propRequestLimit = new ConfigurationProperty("requestLimit", typeof(int), int.MaxValue, new InfiniteIntConverter(), StdValidatorsAndConverters.PositiveIntegerValidator, ConfigurationPropertyOptions.None); private static readonly ConfigurationProperty _propRequestQueueLimit = new ConfigurationProperty("requestQueueLimit", typeof(int), 5000, new InfiniteIntConverter(), StdValidatorsAndConverters.PositiveIntegerValidator, ConfigurationPropertyOptions.None); private static readonly ConfigurationProperty _propRestartQueueLimit = new ConfigurationProperty("restartQueueLimit", typeof(int), 10, new InfiniteIntConverter(), StdValidatorsAndConverters.PositiveIntegerValidator, ConfigurationPropertyOptions.None); private static readonly ConfigurationProperty _propMemoryLimit = new ConfigurationProperty("memoryLimit", typeof(int), 60, ConfigurationPropertyOptions.None); private static readonly ConfigurationProperty _propWebGarden = new ConfigurationProperty("webGarden", typeof(bool), false, ConfigurationPropertyOptions.None); private static readonly ConfigurationProperty _propCpuMask = new ConfigurationProperty("cpuMask", typeof(string), "0xffffffff", ConfigurationPropertyOptions.None); private static readonly ConfigurationProperty _propUserName = new ConfigurationProperty("userName", typeof(string), "machine", ConfigurationPropertyOptions.None); private static readonly ConfigurationProperty _propPassword = new ConfigurationProperty("password", typeof(string), "AutoGenerate", ConfigurationPropertyOptions.None); private static readonly ConfigurationProperty _propLogLevel = new ConfigurationProperty("logLevel", typeof(ProcessModelLogLevel), ProcessModelLogLevel.Errors, ConfigurationPropertyOptions.None); private static readonly ConfigurationProperty _propClientConnectedCheck = new ConfigurationProperty("clientConnectedCheck", typeof(TimeSpan), DefaultClientConnectedCheck, StdValidatorsAndConverters.InfiniteTimeSpanConverter, null, ConfigurationPropertyOptions.None); private static readonly ConfigurationProperty _propComAuthenticationLevel = new ConfigurationProperty("comAuthenticationLevel", typeof(ProcessModelComAuthenticationLevel), ProcessModelComAuthenticationLevel.Connect, ConfigurationPropertyOptions.None); private static readonly ConfigurationProperty _propComImpersonationLevel = new ConfigurationProperty("comImpersonationLevel", typeof(ProcessModelComImpersonationLevel), ProcessModelComImpersonationLevel.Impersonate, ConfigurationPropertyOptions.None); private static readonly ConfigurationProperty _propResponseDeadlockInterval = new ConfigurationProperty("responseDeadlockInterval", typeof(TimeSpan), TimeSpan.FromMinutes(3), StdValidatorsAndConverters.InfiniteTimeSpanConverter, StdValidatorsAndConverters.PositiveTimeSpanValidator, ConfigurationPropertyOptions.None); private static readonly ConfigurationProperty _propResponseRestartDeadlockInterval = new ConfigurationProperty("responseRestartDeadlockInterval", typeof(TimeSpan), TimeSpan.FromMinutes(3), StdValidatorsAndConverters.InfiniteTimeSpanConverter, null, ConfigurationPropertyOptions.None); // NOTE the AutoConfig default value is different then the value shipped in Machine.config // This is because the Whidbey value is supposed to be true, but if the user removes the value // it should act like pre whidbey behavior which did not have autoconfig. private static readonly ConfigurationProperty _propAutoConfig = new ConfigurationProperty("autoConfig", typeof(bool), false, ConfigurationPropertyOptions.None); private static readonly ConfigurationProperty _propMaxWorkerThreads = new ConfigurationProperty("maxWorkerThreads", typeof(int), DefaultMaxThreadsPerCPU, null, new IntegerValidator(1, int.MaxValue - 1), ConfigurationPropertyOptions.None); private static readonly ConfigurationProperty _propMaxIOThreads = new ConfigurationProperty("maxIoThreads", typeof(int), DefaultMaxThreadsPerCPU, null, new IntegerValidator(1, int.MaxValue - 1), ConfigurationPropertyOptions.None); private static readonly ConfigurationProperty _propMinWorkerThreads = new ConfigurationProperty("minWorkerThreads", typeof(int), 1, null, new IntegerValidator(1, int.MaxValue - 1), ConfigurationPropertyOptions.None); private static readonly ConfigurationProperty _propMinIOThreads = new ConfigurationProperty("minIoThreads", typeof(int), 1, null, new IntegerValidator(1, int.MaxValue - 1), ConfigurationPropertyOptions.None); private static readonly ConfigurationProperty _propServerErrorMessageFile = new ConfigurationProperty("serverErrorMessageFile", typeof(string), String.Empty, ConfigurationPropertyOptions.None); private static readonly ConfigurationProperty _propPingFrequency = new ConfigurationProperty("pingFrequency", typeof(TimeSpan), TimeSpan.MaxValue, StdValidatorsAndConverters.InfiniteTimeSpanConverter, null, ConfigurationPropertyOptions.None); private static readonly ConfigurationProperty _propPingTimeout = new ConfigurationProperty("pingTimeout", typeof(TimeSpan), TimeSpan.MaxValue, StdValidatorsAndConverters.InfiniteTimeSpanConverter, null, ConfigurationPropertyOptions.None); private static readonly ConfigurationProperty _propMaxAppDomains = new ConfigurationProperty("maxAppDomains", typeof(int), 2000, null, new IntegerValidator(1, int.MaxValue - 1), ConfigurationPropertyOptions.None); private static int cpuCount; internal const string sectionName = "system.web/processModel"; static ProcessModelSection() { // Property initialization _properties = new ConfigurationPropertyCollection(); _properties.Add(_propEnable); _properties.Add(_propTimeout); _properties.Add(_propIdleTimeout); _properties.Add(_propShutdownTimeout); _properties.Add(_propRequestLimit); _properties.Add(_propRequestQueueLimit); _properties.Add(_propRestartQueueLimit); _properties.Add(_propMemoryLimit); _properties.Add(_propWebGarden); _properties.Add(_propCpuMask); _properties.Add(_propUserName); _properties.Add(_propPassword); _properties.Add(_propLogLevel); _properties.Add(_propClientConnectedCheck); _properties.Add(_propComAuthenticationLevel); _properties.Add(_propComImpersonationLevel); _properties.Add(_propResponseDeadlockInterval); _properties.Add(_propResponseRestartDeadlockInterval); _properties.Add(_propAutoConfig); _properties.Add(_propMaxWorkerThreads); _properties.Add(_propMaxIOThreads); _properties.Add(_propMinWorkerThreads); _properties.Add(_propMinIOThreads); _properties.Add(_propServerErrorMessageFile); _properties.Add(_propPingFrequency); _properties.Add(_propPingTimeout); _properties.Add(_propMaxAppDomains); cpuCount = SystemInfo.GetNumProcessCPUs(); } public ProcessModelSection() { } protected override ConfigurationPropertyCollection Properties { get { return _properties; } } [ConfigurationProperty("enable", DefaultValue = true)] public bool Enable { get { return (bool)base[_propEnable]; } set { base[_propEnable] = value; } } [ConfigurationProperty("timeout", DefaultValue = TimeSpanValidatorAttribute.TimeSpanMaxValue)] [TypeConverter(typeof(InfiniteTimeSpanConverter))] public TimeSpan Timeout { get { return (TimeSpan)base[_propTimeout]; } set { base[_propTimeout] = value; } } [ConfigurationProperty("idleTimeout", DefaultValue = TimeSpanValidatorAttribute.TimeSpanMaxValue)] [TypeConverter(typeof(InfiniteTimeSpanConverter))] public TimeSpan IdleTimeout { get { return (TimeSpan)base[_propIdleTimeout]; } set { base[_propIdleTimeout] = value; } } [ConfigurationProperty("shutdownTimeout", DefaultValue = "00:00:05")] [TypeConverter(typeof(InfiniteTimeSpanConverter))] [TimeSpanValidator(MinValueString="00:00:00", MaxValueString=TimeSpanValidatorAttribute.TimeSpanMaxValue)] public TimeSpan ShutdownTimeout { get { return (TimeSpan)base[_propShutdownTimeout]; } set { base[_propShutdownTimeout] = value; } } [ConfigurationProperty("requestLimit", DefaultValue = int.MaxValue)] [TypeConverter(typeof(InfiniteIntConverter))] [IntegerValidator(MinValue = 0)] public int RequestLimit { get { return (int)base[_propRequestLimit]; } set { base[_propRequestLimit] = value; } } [ConfigurationProperty("requestQueueLimit", DefaultValue = 5000)] [TypeConverter(typeof(InfiniteIntConverter))] [IntegerValidator(MinValue = 0)] public int RequestQueueLimit { get { return (int)base[_propRequestQueueLimit]; } set { base[_propRequestQueueLimit] = value; } } [ConfigurationProperty("restartQueueLimit", DefaultValue = 10)] [TypeConverter(typeof(InfiniteIntConverter))] [IntegerValidator(MinValue = 0)] public int RestartQueueLimit { get { return (int)base[_propRestartQueueLimit]; } set { base[_propRestartQueueLimit] = value; } } [ConfigurationProperty("memoryLimit", DefaultValue = 60)] public int MemoryLimit { get { return (int)base[_propMemoryLimit]; } set { base[_propMemoryLimit] = value; } } [ConfigurationProperty("webGarden", DefaultValue = false)] public bool WebGarden { get { return (bool)base[_propWebGarden]; } set { base[_propWebGarden] = value; } } [ConfigurationProperty("cpuMask", DefaultValue = "0xffffffff")] public int CpuMask { get { return (int)Convert.ToInt32((string)base[_propCpuMask], 16); } set { base[_propCpuMask] = "0x" + Convert.ToString(value, 16); } } [ConfigurationProperty("userName", DefaultValue = "machine")] public string UserName { get { return (string)base[_propUserName]; } set { base[_propUserName] = value; } } [ConfigurationProperty("password", DefaultValue = "AutoGenerate")] public string Password { get { return (string)base[_propPassword]; } set { base[_propPassword] = value; } } [ConfigurationProperty("logLevel", DefaultValue = ProcessModelLogLevel.Errors)] public ProcessModelLogLevel LogLevel { get { return (ProcessModelLogLevel)base[_propLogLevel]; } set { base[_propLogLevel] = value; } } [ConfigurationProperty("clientConnectedCheck", DefaultValue = "00:00:05")] [TypeConverter(typeof(InfiniteTimeSpanConverter))] public TimeSpan ClientConnectedCheck { get { return (TimeSpan)base[_propClientConnectedCheck]; } set { base[_propClientConnectedCheck] = value; } } [ConfigurationProperty("comAuthenticationLevel", DefaultValue = ProcessModelComAuthenticationLevel.Connect)] public ProcessModelComAuthenticationLevel ComAuthenticationLevel { get { return (ProcessModelComAuthenticationLevel)base[_propComAuthenticationLevel]; } set { base[_propComAuthenticationLevel] = value; } } [ConfigurationProperty("comImpersonationLevel", DefaultValue = ProcessModelComImpersonationLevel.Impersonate)] public ProcessModelComImpersonationLevel ComImpersonationLevel { get { return (ProcessModelComImpersonationLevel)base[_propComImpersonationLevel]; } set { base[_propComImpersonationLevel] = value; } } [ConfigurationProperty("responseDeadlockInterval", DefaultValue = "00:03:00")] [TypeConverter(typeof(InfiniteTimeSpanConverter))] [TimeSpanValidator(MinValueString="00:00:00", MaxValueString=TimeSpanValidatorAttribute.TimeSpanMaxValue)] public TimeSpan ResponseDeadlockInterval { get { return (TimeSpan)base[_propResponseDeadlockInterval]; } set { base[_propResponseDeadlockInterval] = value; } } [ConfigurationProperty("responseRestartDeadlockInterval", DefaultValue = "00:03:00")] [TypeConverter(typeof(InfiniteTimeSpanConverter))] public TimeSpan ResponseRestartDeadlockInterval { get { return (TimeSpan)base[_propResponseRestartDeadlockInterval]; } set { base[_propResponseRestartDeadlockInterval] = value; } } // NOTE the AutoConfig default value is different then the value shipped in Machine.config // This is because the Whidbey value is supposed to be true, but if the user removes the value // it should act like pre whidbey behavior which did not have autoconfig. [ConfigurationProperty("autoConfig", DefaultValue = false)] public bool AutoConfig { get { return (bool)base[_propAutoConfig]; } set { base[_propAutoConfig] = value; } } [ConfigurationProperty("maxWorkerThreads", DefaultValue = 20)] [IntegerValidator(MinValue = 1, MaxValue = int.MaxValue - 1)] public int MaxWorkerThreads { get { return (int)base[_propMaxWorkerThreads]; } set { base[_propMaxWorkerThreads] = value; } } [ConfigurationProperty("maxIoThreads", DefaultValue = 20)] [IntegerValidator(MinValue = 1, MaxValue = int.MaxValue - 1)] public int MaxIOThreads { get { return (int)base[_propMaxIOThreads]; } set { base[_propMaxIOThreads] = value; } } [ConfigurationProperty("minWorkerThreads", DefaultValue = 1)] [IntegerValidator(MinValue = 1, MaxValue = int.MaxValue - 1)] public int MinWorkerThreads { get { return (int)base[_propMinWorkerThreads]; } set { base[_propMinWorkerThreads] = value; } } [ConfigurationProperty("minIoThreads", DefaultValue = 1)] [IntegerValidator(MinValue = 1, MaxValue = int.MaxValue - 1)] public int MinIOThreads { get { return (int)base[_propMinIOThreads]; } set { base[_propMinIOThreads] = value; } } [ConfigurationProperty("serverErrorMessageFile", DefaultValue = "")] public string ServerErrorMessageFile { get { return (string)base[_propServerErrorMessageFile]; } set { base[_propServerErrorMessageFile] = value; } } [ConfigurationProperty("pingFrequency", DefaultValue = TimeSpanValidatorAttribute.TimeSpanMaxValue)] [TypeConverter(typeof(InfiniteTimeSpanConverter))] public TimeSpan PingFrequency { get { return (TimeSpan)base[_propPingFrequency]; } set { base[_propPingFrequency] = value; } } [ConfigurationProperty("pingTimeout", DefaultValue = TimeSpanValidatorAttribute.TimeSpanMaxValue)] [TypeConverter(typeof(InfiniteTimeSpanConverter))] public TimeSpan PingTimeout { get { return (TimeSpan)base[_propPingTimeout]; } set { base[_propPingTimeout] = value; } } [ConfigurationProperty("maxAppDomains", DefaultValue = 2000)] [IntegerValidator(MinValue = 1, MaxValue = int.MaxValue - 1)] public int MaxAppDomains { get { return (int)base[_propMaxAppDomains]; } set { base[_propMaxAppDomains] = value; } } internal int CpuCount { get { return cpuCount; } } internal int DefaultMaxWorkerThreadsForAutoConfig { get { return DefaultMaxThreadsPerCPU * cpuCount; } } internal int DefaultMaxIoThreadsForAutoConfig { get { return DefaultMaxThreadsPerCPU * cpuCount; } } internal int MaxWorkerThreadsTimesCpuCount { get { return MaxWorkerThreads * cpuCount; } } internal int MaxIoThreadsTimesCpuCount { get { return MaxIOThreads * cpuCount; } } internal int MinWorkerThreadsTimesCpuCount { get { return MinWorkerThreads * cpuCount; } } internal int MinIoThreadsTimesCpuCount { get { return MinIOThreads * cpuCount; } } protected override ConfigurationElementProperty ElementProperty { get { return s_elemProperty; } } private static void Validate(object value) { if (value == null) { throw new ArgumentNullException("value"); } ProcessModelSection elem = (ProcessModelSection)value; int val = -1; try { val = elem.CpuMask; } catch { throw new ConfigurationErrorsException( SR.GetString(SR.Invalid_non_zero_hexadecimal_attribute, "cpuMask"), elem.ElementInformation.Properties["cpuMask"].Source, elem.ElementInformation.Properties["cpuMask"].LineNumber); } if (val == 0) { throw new ConfigurationErrorsException( SR.GetString(SR.Invalid_non_zero_hexadecimal_attribute, "cpuMask"), elem.ElementInformation.Properties["cpuMask"].Source, elem.ElementInformation.Properties["cpuMask"].LineNumber); } } } }