/* * Delete an assembly that is out of date, as well as the associated files */ internal static void RemoveOutOfDateAssembly(string assemblyName) { DirectoryInfo directory = new DirectoryInfo(HttpRuntime.CodegenDirInternal); FileInfo[] files = directory.GetFiles(assemblyName + ".*"); foreach (FileInfo f in files) { try { // First, just try to delete the file f.Delete(); } catch (Exception) { try { // If the delete failed, rename it to ".delete", so it'll get // cleaned up next time by RemoveOldTempFiles() // Don't do that if it already has the delete extension if (f.Extension != ".delete") { f.MoveTo(f.FullName + ".delete"); } } catch (Exception) { // Ignore all exceptions Debug.Assert(false, "Cannot delete " + f.Name + " from " + directory); } } } }
/* * Set some fields that are needed for code generation */ internal BaseCompiler(TemplateParser parser) { _parser = parser; _baseClassType = Parser.BaseType; Debug.Assert(_baseClassType != null); }
/// <include file='doc\BaseCompiler.uex' path='docs/doc[@for="BaseCompiler.GetGeneratedClassName"]/*' /> /// <devdoc> /// Create a name for the generated class /// </devdoc> private string GetGeneratedClassName() { string className; // If the user specified the class name, just use that if (Parser.GeneratedClassName != null) { return(Parser.GeneratedClassName); } // If we know the input file name, use it to generate the class name if (Parser.InputFile != null) { // Make sure we have the file name's correct case (ASURT 59179) className = Util.CheckExistsAndGetCorrectCaseFileName(Parser.InputFile); Debug.Assert(className != null); // Get rid of the path className = Path.GetFileName(className); // Change invalid chars to underscores className = Util.MakeValidTypeNameFromString(className); } else { // Otherwise, use a default name className = tempClassName; } return(className); }
private void CreateHost() { Debug.Trace("CBM", "CreateHost"); Debug.Assert(_host == null); Debug.Assert(!_hostCreationPending, "CreateHost: creation already pending"); _hostCreationPending = true; // Use a local to avoid having a partially created _host BuildManagerHost host = null; try { string appId; IApplicationHost appHost; ApplicationManager appManager = ApplicationManager.GetApplicationManager(); host = (BuildManagerHost)appManager.CreateObjectWithDefaultAppHostAndAppId( _physicalPath, _virtualPath, typeof(BuildManagerHost), false /*failIfExists*/, _hostingParameters, out appId, out appHost); // host appdomain cannot be unloaded during creation. host.AddPendingCall(); host.Configure(this); _host = host; _appId = appId; _appHost = appHost; _hostCreationException = _host.InitializationException; } catch (Exception e) { // If an exception happens, keep track of it _hostCreationException = e; // Even though the host initialization failed, keep track of it so subsequent // request will see the error _host = host; } finally { _hostCreationPending = false; if (host != null) { // Notify the client that the host is ready if (AppDomainStarted != null) { AppDomainStarted(this, EventArgs.Empty); } // The host can be unloaded safely now. host.RemovePendingCall(); } } Debug.Trace("CBM", "CreateHost LEAVE"); }
static bool GetSiteNameFromISAPI() { Debug.Trace("config_loc", "GetSiteNameFromISAPI()"); HttpContext context = HttpContext.Current; if (context != null) { string metabaseAppKey = context.Request.ServerVariables["INSTANCE_META_PATH"]; const string KEY_LMW3SVC = "/LM/W3SVC/"; Debug.Assert(metabaseAppKey.StartsWith(KEY_LMW3SVC)); string appNumber = metabaseAppKey.Substring(KEY_LMW3SVC.Length - 1); //string appServerComment = "/" + appNumber + "/ServerComment"; Debug.Trace("config_loc", "appNumber:" + appNumber + " INSTANCE_META_PATH:" + metabaseAppKey); UnicodeEncoding encoding = new UnicodeEncoding(); // null-terminate appNumber and convert to byte array byte [] byteAppNumber = encoding.GetBytes(appNumber + "\0"); int retVal = 2; byte [] outBytes = new byte[64]; while (retVal == 2) { retVal = context.CallISAPI(UnsafeNativeMethods.CallISAPIFunc.GetSiteServerComment, byteAppNumber, outBytes); if (retVal == 2) { if (outBytes.Length > 1024) // should never happen { throw new ConfigurationException(HttpRuntime.FormatResourceString( SR.Config_site_name_too_long, metabaseAppKey)); } outBytes = new byte[outBytes.Length * 2]; } } // find WCHAR null terminator in byte array int i = 0; while (i + 1 < outBytes.Length && (outBytes[i] != 0 || outBytes[i + 1] != 0)) { i += 2; } // decode up to null terminator s_siteName = encoding.GetString(outBytes, 0, i); Debug.Trace("config_loc", "i: " + i + " site name:" + s_siteName); return(true); } else { Debug.Trace("config_loc", "could not query site name. No Context."); } return(false); // keep trying to evaluate }
// GetSection // // Get the Config for a specific path // static internal object GetSection(string sectionName, VirtualPath path) { Debug.Assert(UseHttpConfigurationSystem, "UseHttpConfigurationSystem"); CachedPathData pathData; pathData = CachedPathData.GetVirtualPathData(path, true); return(pathData.ConfigRecord.GetSection(sectionName)); }
protected SimpleWebHandlerParser(HttpContext context, string virtualPath, string physicalPath) { // These obsolete parameters should never be set Debug.Assert(context == null); Debug.Assert(physicalPath == null); Debug.Assert(virtualPath != null); _virtualPath = VirtualPath.Create(virtualPath); }
// GetAppSection // // Get the Config for a specific path // static internal object GetApplicationSection(string sectionName) { Debug.Assert(UseHttpConfigurationSystem, "UseHttpConfigurationSystem"); CachedPathData pathData; pathData = CachedPathData.GetApplicationPathData(); return(pathData.ConfigRecord.GetSection(sectionName)); }
/* * Build first-time intialization statements */ protected override void BuildInitStatements(CodeStatementCollection trueStatements, CodeStatementCollection topLevelStatements) { base.BuildInitStatements(trueStatements, topLevelStatements); CodeMemberField fileDependencies = new CodeMemberField(typeof(ArrayList), fileDependenciesName); fileDependencies.Attributes |= MemberAttributes.Static; _sourceDataClass.Members.Add(fileDependencies); // Note: it may look like this local variable declaraiton is redundant. However it is necessary // to make this init code re-entrant safe. This way, even if two threads enter the contructor // at the same time, they will not add multiple dependencies. // e.g. ArrayList dependencies; CodeVariableDeclarationStatement dependencies = new CodeVariableDeclarationStatement(); dependencies.Type = new CodeTypeReference(typeof(ArrayList)); dependencies.Name = dependenciesLocalName; topLevelStatements.Insert(0, dependencies); // e.g. dependencies = new System.Collections.ArrayList(); CodeAssignStatement assignDependencies = new CodeAssignStatement(); assignDependencies.Left = new CodeVariableReferenceExpression(dependenciesLocalName); assignDependencies.Right = new CodeObjectCreateExpression(typeof(ArrayList)); // Note: it is important to add all local variables at the top level for CodeDom Subset compliance. trueStatements.Add(assignDependencies); Debug.Assert(Parser.FileDependencies != null); if (Parser.FileDependencies != null) { int count = Parser.FileDependencies.Length; for (int i = 0; i < count; i++) { // depdendencies.Add("..."); CodeMethodInvokeExpression addFileDep = new CodeMethodInvokeExpression(); addFileDep.Method.TargetObject = new CodeVariableReferenceExpression(dependenciesLocalName); addFileDep.Method.MethodName = "Add"; addFileDep.Parameters.Add(new CodePrimitiveExpression((string)Parser.FileDependencies[i])); trueStatements.Add(new CodeExpressionStatement(addFileDep)); } } // e.g. __fileDependencies = dependencies; CodeAssignStatement initFile = new CodeAssignStatement(); initFile.Left = new CodeFieldReferenceExpression(_classTypeExpr, fileDependenciesName); initFile.Right = new CodeVariableReferenceExpression(dependenciesLocalName); #if DBG AppendDebugComment(trueStatements); #endif trueStatements.Add(initFile); }
internal static void RemoveBackgroundBatchCompilation(BackgroundBatchCompiler bbc) { lock (_backgroundBatchCompilations) { try { _backgroundBatchCompilations.Remove(bbc); } catch { Debug.Assert(false, "RemoveBackgroundBatchCompilation failed"); } } }
/// <devdoc> /// Returns an IEnumerable that is the DataSource, which either came /// from the DataSource property or from the control bound via the /// DataSourceID property. /// </devdoc> protected virtual IEnumerable GetData() { DataSourceView view = ConnectToDataSourceView(); Debug.Assert(_currentViewValid); if (view != null) { return(view.ExecuteSelect(DataSourceSelectArguments.Empty)); } return(null); }
/* * Build a ProcessRequest override which just calls the base. This is used to make sure * there is user code on the stack when requests are executed (VSWhidbey 499386) */ private void BuildProcessRequestOverride() { // public override void ProcessRequest(HttpContext context) { // base.ProcessRequest(context); // } CodeMemberMethod method = new CodeMemberMethod(); AddDebuggerNonUserCodeAttribute(method); method.Name = "ProcessRequest"; method.Attributes &= ~MemberAttributes.AccessMask; method.Attributes &= ~MemberAttributes.ScopeMask; // If the base type is non-default (i.e. not Page) we have to be careful overriding // ProcessRequest, because if the base has its own IHttpHandler.ProcessRequest implementation // and it's not overridable, we would fail to compile. So when we detect this situation, // we instead generate it as a new IHttpHandler.ProcessRequest implementation instead of an // override. In theory, we could *always* do this, but it's safer to limit it to this // constrained scenario (VSWhidbey 517240) MethodInfo methodInfo = null; if (Parser.BaseType != typeof(Page)) { methodInfo = Parser.BaseType.GetMethod("ProcessRequest", BindingFlags.Public | BindingFlags.Instance, null, new Type[] { typeof(HttpContext) }, null); Debug.Assert(methodInfo != null); } _sourceDataClass.BaseTypes.Add(new CodeTypeReference(typeof(IHttpHandler))); if (methodInfo != null && methodInfo.DeclaringType != typeof(Page)) { method.Attributes |= MemberAttributes.New | MemberAttributes.Public; } else { method.Attributes |= MemberAttributes.Override | MemberAttributes.Public; } method.Parameters.Add(new CodeParameterDeclarationExpression(typeof(HttpContext), "context")); CodeMethodInvokeExpression invokeExpr = new CodeMethodInvokeExpression(); invokeExpr.Method.TargetObject = new CodeBaseReferenceExpression(); invokeExpr.Method.MethodName = "ProcessRequest"; invokeExpr.Parameters.Add(new CodeArgumentReferenceExpression("context")); method.Statements.Add(invokeExpr); _sourceDataClass.Members.Add(method); }
private void CacheEntryToMemory(SourceCompilerCachedEntry scce) { Debug.Assert(_utcStart != DateTime.MinValue); // Always add the main compiled file itself as a source dependency AddSourceDependency(_physicalPath); // Get an array of source file dependencies string[] sourceDependencies = Util.StringArrayFromHashtable(_sourceDependencies); _cache.UtcInsert(_cacheKey, scce, new CacheDependency(false, sourceDependencies, _utcStart), Cache.NoAbsoluteExpiration, Cache.NoSlidingExpiration, CacheItemPriority.NotRemovable, null); Debug.Trace("Template", "Caching source code (" + _virtualPath + "," + scce._assembly.GetName().Name + ")"); }
/* * Compile an .aspx file into an HttpApplication Type */ internal static Type GetCompiledApplicationType(string inputFile, HttpContext context, out ApplicationFileParser parser) { parser = new ApplicationFileParser(); parser.CurrentVirtualPath = UrlPath.Combine(context.Request.ApplicationPath, HttpApplicationFactory.applicationFileName); parser.InputFile = inputFile; parser.Context = context; // Never use trivial pages for global.asax (ASURT 32420) parser._fAlwaysCompile = true; ParserCacheItem cacheItem = parser.GetParserCacheItem(); Debug.Assert(cacheItem.type != null); return(cacheItem.type); }
/* * Preserve the combined hash of the special files to a file. */ private static void WritePreservedSpecialFilesCombinedHash(long hash) { Debug.Assert(hash != 0, "WritePreservedSpecialFilesCombinedHash: hash != 0"); StreamWriter writer = null; try { writer = new StreamWriter(GetSpecialFilesCombinedHashFileName(), false, Encoding.UTF8); writer.Write(hash.ToString("x")); } finally { if (writer != null) { writer.Close(); } } }
/* * Create an object in the runtime appdomain */ public IRegisteredObject CreateObject(Type type, bool failIfExists) { if (type == null) { throw new ArgumentNullException("type"); } EnsureHostCreated(); Debug.Assert(_appId != null); Debug.Assert(_appHost != null); _host.RegisterAssembly(type.Assembly.FullName, type.Assembly.Location); ApplicationManager appManager = ApplicationManager.GetApplicationManager(); return(appManager.CreateObjectInternal(_appId, type, _appHost, failIfExists, _hostingParameters)); }
internal PreservedAssemblyEntry(HttpContext context, string virtualPath, bool fApplicationFile, Assembly assembly, Type type, Hashtable sourceDependencies) { _context = context; _virtualPath = virtualPath; _fApplicationFile = fApplicationFile; if (assembly != null) { _assembly = assembly; } else { _assembly = type.Module.Assembly; } _type = type; _sourceDependencies = sourceDependencies; _assemblyDependencies = Util.GetReferencedAssembliesHashtable(_assembly); // If any of the assemblies we depend on are in the bin directory, // add a file dependency for them. string binDir = HttpRuntime.BinDirectoryInternal; foreach (Assembly a in AssemblyDependencies.Keys) { string assemblyFilePath = Util.FilePathFromFileUrl(a.EscapedCodeBase); if (assemblyFilePath.StartsWith(binDir)) { _sourceDependencies[assemblyFilePath] = assemblyFilePath; } } // If there are some web.config files other than the global ones, depend on them string baseVirtualDir = UrlPath.GetDirectory(virtualPath); string[] configFiles = context.GetConfigurationDependencies(baseVirtualDir); Debug.Assert(configFiles.Length >= _numTopLevelConfigFiles, "configFiles.Length >= _numTopLevelConfigFiles"); for (int i = 0; i < configFiles.Length - _numTopLevelConfigFiles; i++) { _sourceDependencies[configFiles[i]] = configFiles[i]; } }
private void AddConstructorToSource(ConstructorInfo ctor) { Debug.Assert(ctor != null); Debug.Assert(ctor.GetParameters().Length > 0); var ctorCode = new CodeConstructor(); AddDebuggerNonUserCodeAttribute(ctorCode); ctorCode.Attributes &= ~MemberAttributes.AccessMask; ctorCode.Attributes |= MemberAttributes.Public; // copy all the attributes of the contrustor parameters foreach (var p in ctor.GetParameters()) { var parameterExpr = new CodeParameterDeclarationExpression(p.ParameterType, p.Name); foreach (var attr in p.CustomAttributes) { var attrArgs = new List <CodeAttributeArgument>(); foreach (var arg in attr.ConstructorArguments) { attrArgs.Add(new CodeAttributeArgument(new CodePrimitiveExpression(arg.Value))); } foreach (var arg in attr.NamedArguments) { attrArgs.Add(new CodeAttributeArgument(arg.MemberName, new CodePrimitiveExpression(arg.TypedValue.Value))); } var customAttrExpr = new CodeAttributeDeclaration(new CodeTypeReference(attr.AttributeType), attrArgs.ToArray()); parameterExpr.CustomAttributes.Add(customAttrExpr); } if (p.HasDefaultValue) { var defaultValAttrExpr = new CodeAttributeDeclaration(new CodeTypeReference(typeof(DefaultParameterValueAttribute)), new CodeAttributeArgument(new CodePrimitiveExpression(p.DefaultValue))); parameterExpr.CustomAttributes.Add(defaultValAttrExpr); } ctorCode.Parameters.Add(parameterExpr); ctorCode.BaseConstructorArgs.Add(new CodeVariableReferenceExpression(p.Name)); } ctorCode.Statements.Add(CreateInitInvoke()); _sourceDataClass.Members.Add(ctorCode); }
private void AddConstructorToSource(ConstructorInfo ctor) { Debug.Assert(ctor != null); Debug.Assert(ctor.GetParameters().Length > 0); var ctorCode = new CodeConstructor(); AddDebuggerNonUserCodeAttribute(ctorCode); ctorCode.Attributes &= ~MemberAttributes.AccessMask; ctorCode.Attributes |= MemberAttributes.Public; foreach (var p in ctor.GetParameters()) { ctorCode.Parameters.Add(new CodeParameterDeclarationExpression(p.ParameterType, p.Name)); ctorCode.BaseConstructorArgs.Add(new CodeVariableReferenceExpression(p.Name)); } ctorCode.Statements.Add(CreateInitInvoke()); _sourceDataClass.Members.Add(ctorCode); }
private long NextSample() { // not thread-safe, only invoke from timer callback Debug.Assert(_inPBytesMonitorThread == 1); // NtQuerySystemInformation is a very expensive call. A new function // exists on XP Pro and later versions of the OS and it performs much // better. The name of that function is GetProcessMemoryInfo. For hosting // scenarios where a larger number of w3wp.exe instances are running, we // want to use the new API (VSWhidbey 417366). long privateBytes; if (_useGetProcessMemoryInfo) { long privatePageCount; UnsafeNativeMethods.GetPrivateBytesIIS6(out privatePageCount, true /*nocache*/); privateBytes = privatePageCount; } else { uint dummy; uint privatePageCount = 0; // this is a very expensive call UnsafeNativeMethods.GetProcessMemoryInformation(_pid, out privatePageCount, out dummy, true /*nocache*/); privateBytes = (long)privatePageCount << MEGABYTE_SHIFT; } // increment the index (it's either 1 or 0) Debug.Assert(SAMPLE_COUNT == 2); _idx = _idx ^ 1; // remember the sample time _sampleTimes[_idx] = DateTime.UtcNow; // remember the sample value _samples[_idx] = privateBytes; #if PERF SafeNativeMethods.OutputDebugString(String.Format("CacheManager.NextSample: privateBytes={0:N}, _highPresureMark={1:N}\n", privateBytes, _highPressureMark)); #endif return(privateBytes); }
/* * Helper method for building application and session scope injected * properties. If useApplicationState, build application properties, otherwise * build session properties. */ private void BuildObjectPropertiesHelper(IDictionary objects, bool useApplicationState) { IDictionaryEnumerator en = objects.GetEnumerator(); while (en.MoveNext()) { HttpStaticObjectsEntry entry = (HttpStaticObjectsEntry)en.Value; // e.g. (PropType)Session.StaticObjects["PropName"] // Use the appropriate collection CodePropertyReferenceExpression stateObj = new CodePropertyReferenceExpression(new CodePropertyReferenceExpression(new CodeThisReferenceExpression(), useApplicationState ? "Application" : "Session"), "StaticObjects"); CodeMethodInvokeExpression getObject = new CodeMethodInvokeExpression(stateObj, "GetObject"); getObject.Parameters.Add(new CodePrimitiveExpression(entry.Name)); Type declaredType = entry.DeclaredType; Debug.Assert(!Util.IsLateBoundComClassicType(declaredType)); if (useApplicationState) { // for application state use property that does caching in a member BuildInjectedGetPropertyMethod(entry.Name, declaredType.FullName, new CodeCastExpression(declaredType.FullName, getObject), false /*fPublicProp*/); } else { // for session state use lookup every time, as one application instance deals with many sessions CodeMemberProperty prop = new CodeMemberProperty(); prop.Name = entry.Name; prop.Type = new CodeTypeReference(declaredType.FullName); prop.GetStatements.Add(new CodeMethodReturnStatement(new CodeCastExpression(declaredType.FullName, getObject))); _sourceDataClass.Members.Add(prop); } } }
internal BatchCompilationEntry(string virtualPath, string filename, HttpContext context) { _virtualPath = virtualPath; string extension = Path.GetExtension(filename); if (string.Compare(extension, ".aspx", true, CultureInfo.InvariantCulture) == 0) { _templateParser = new PageParser(); } else if (string.Compare(extension, ".ascx", true, CultureInfo.InvariantCulture) == 0) { _templateParser = new UserControlParser(); _fUserControl = true; } else { Debug.Assert(false, "Unexpected extension"); } _templateParser.InputFile = filename; _templateParser.Context = context; _templateParser.CurrentVirtualPath = virtualPath; }
internal override CodeExpression BuildStringPropertyExpression(PropertyEntry pse) { // Make the UrlProperty based on virtualDirPath for control themes. if (pse.PropertyInfo != null) { UrlPropertyAttribute urlAttrib = Attribute.GetCustomAttribute(pse.PropertyInfo, typeof(UrlPropertyAttribute)) as UrlPropertyAttribute; if (urlAttrib != null) { if (pse is SimplePropertyEntry) { SimplePropertyEntry spse = (SimplePropertyEntry)pse; string strValue = (string)spse.Value; if (UrlPath.IsRelativeUrl(strValue) && !UrlPath.IsAppRelativePath(strValue)) { spse.Value = UrlPath.MakeVirtualPathAppRelative(UrlPath.Combine(_themeParser.VirtualDirPath.VirtualPathString, strValue)); } } else { Debug.Assert(pse is ComplexPropertyEntry); ComplexPropertyEntry cpe = (ComplexPropertyEntry)pse; StringPropertyBuilder builder = (StringPropertyBuilder)cpe.Builder; string strValue = (string)builder.BuildObject(); if (UrlPath.IsRelativeUrl(strValue) && !UrlPath.IsAppRelativePath(strValue)) { cpe.Builder = new StringPropertyBuilder(UrlPath.MakeVirtualPathAppRelative(UrlPath.Combine(_themeParser.VirtualDirPath.VirtualPathString, strValue))); } } } } return(base.BuildStringPropertyExpression(pse)); }
protected override void BuildSourceDataTreeFromBuilder(ControlBuilder builder, bool fInTemplate, bool topLevelControlInTemplate, PropertyEntry pse) { // Don't do anything for code blocks if (builder is CodeBlockBuilder) { return; } // Is the current builder for a template? bool fTemplate = (builder is TemplateBuilder); // Is the current builder the root builder? bool fRootBuilder = (builder == _themeParser.RootBuilder); // Is this a control theme? bool fControlSkin = !fInTemplate && !fTemplate && topLevelControlInTemplate; // Ignore the ID attribute, always auto generate ID. _controlCount++; builder.ID = "__control" + _controlCount.ToString(NumberFormatInfo.InvariantInfo); builder.IsGeneratedID = true; // Check for the SkinID property. if (fControlSkin && !(builder is DataBoundLiteralControlBuilder)) { Type ctrlType = builder.ControlType; Debug.Assert(typeof(Control).IsAssignableFrom(ctrlType)); Debug.Assert(ThemeableAttribute.IsTypeThemeable(ctrlType)); string skinID = builder.SkinID; object skinKey = PageTheme.CreateSkinKey(builder.ControlType, skinID); if (_controlSkinTypeNameCollection.Contains(skinKey)) { if (String.IsNullOrEmpty(skinID)) { throw new HttpParseException(SR.GetString(SR.Page_theme_default_theme_already_defined, builder.ControlType.FullName), null, builder.VirtualPath, null, builder.Line); } else { throw new HttpParseException(SR.GetString(SR.Page_theme_skinID_already_defined, skinID), null, builder.VirtualPath, null, builder.Line); } } _controlSkinTypeNameCollection.Add(skinKey, true); _controlSkinBuilderEntryList.Add(new ControlSkinBuilderEntry(builder, skinID)); } // Process the children // only root builders and template builders are processed. if (builder.SubBuilders != null) { foreach (object child in builder.SubBuilders) { if (child is ControlBuilder) { bool isTopLevelCtrlInTemplate = fTemplate && typeof(Control).IsAssignableFrom(((ControlBuilder)child).ControlType); BuildSourceDataTreeFromBuilder((ControlBuilder)child, fInTemplate, isTopLevelCtrlInTemplate, null); } } } foreach (TemplatePropertyEntry entry in builder.TemplatePropertyEntries) { BuildSourceDataTreeFromBuilder(((TemplatePropertyEntry)entry).Builder, true, false /*topLevelControlInTemplate*/, entry); } foreach (ComplexPropertyEntry entry in builder.ComplexPropertyEntries) { if (!(entry.Builder is StringPropertyBuilder)) { BuildSourceDataTreeFromBuilder(((ComplexPropertyEntry)entry).Builder, fInTemplate, false /*topLevelControlInTemplate*/, entry); } } // Build a Build method for the control // fControlSkin indicates whether the method is a theme build method. if (!fRootBuilder) { BuildBuildMethod(builder, fTemplate, fInTemplate, topLevelControlInTemplate, pse, fControlSkin); } // Build a Render method for the control, unless it has no code if (!fControlSkin && builder.HasAspCode) { BuildRenderMethod(builder, fTemplate); } // Build a method to extract values from the template BuildExtractMethod(builder); // Build a property binding method for the control BuildPropertyBindingMethod(builder, fControlSkin); }
void Adjust() { // not thread-safe, only invoke from timer callback Debug.Assert(_inPBytesMonitorThread == 1); Debug.Assert(SAMPLE_COUNT == 2); // current sample long s2 = _samples[_idx]; // previous sample long s1 = _samples[_idx ^ 1]; // adjust _maxDelta and pressure marks if (s2 > s1 && s1 > 0) { // current time DateTime d2 = _sampleTimes[_idx]; // previous time DateTime d1 = _sampleTimes[_idx ^ 1]; long numBytes = s2 - s1; long numSeconds = (long)Math.Round(d2.Subtract(d1).TotalSeconds); if (numSeconds > 0) { long delta = numBytes / numSeconds; _deltaSamples[_idxDeltaSamples] = delta; _idxDeltaSamples = (_idxDeltaSamples + 1) % DELTA_SAMPLE_COUNT; // update rate of change in private bytes and pressure marks AdjustMaxDeltaAndPressureMarks(delta); } } lock (_timerLock) { if (_timer == null) { return; } // adjust timer frequency if (s2 > _mediumPressureMark) { if (_currentPollInterval > HIGH_FREQ_INTERVAL_MS) { _currentPollInterval = HIGH_FREQ_INTERVAL_MS; _timer.Change(_currentPollInterval, _currentPollInterval); } } else if (s2 > _lowPressureMark) { if (_currentPollInterval > MEDIUM_FREQ_INTERVAL_MS) { _currentPollInterval = MEDIUM_FREQ_INTERVAL_MS; _timer.Change(_currentPollInterval, _currentPollInterval); } } else { if (_currentPollInterval != LOW_FREQ_INTERVAL_MS) { _currentPollInterval = LOW_FREQ_INTERVAL_MS; _timer.Change(_currentPollInterval, _currentPollInterval); } } } }
void AdjustMaxDeltaAndPressureMarks(long delta) { // not thread-safe...only invoke from ctor or timer callback Debug.Assert(_inPBytesMonitorThread == 1 || _timer == null); // The value of _maxDelta is the largest rate of change we've seen, // but it is reduced if the rate is now consistently less than what // it once was. long newMaxDelta = _maxDelta; if (delta > newMaxDelta) { // set maxDelta to the current rate of change newMaxDelta = delta; } else { // if _maxDelta is at least four times larger than every sample rate in the history, // then reduce _maxDelta bool reduce = true; long maxDelta = _maxDelta / 4; foreach (long rate in _deltaSamples) { if (rate > maxDelta) { reduce = false; break; } } if (reduce) { newMaxDelta = maxDelta * 2; } } // ensure that maxDelta is sufficiently large so that the _highPressureMark is sufficiently // far away from the memory limit newMaxDelta = Math.Max(newMaxDelta, _minMaxDelta); // Do we have a new maxDelta? If so, adjust it and pressure marks. if (_maxDelta != newMaxDelta) { // adjust _maxDelta _maxDelta = newMaxDelta; // instead of using _maxDelta, use twice _maxDelta since recycling is // expensive and the real delta fluctuates _highPressureMark = Math.Max(_limit * 9 / 10, _limit - (_maxDelta * 2 * HIGH_FREQ_INTERVAL_S)); _lowPressureMark = Math.Max(_limit * 6 / 10, _limit - (_maxDelta * 2 * LOW_FREQ_INTERVAL_S)); _mediumPressureMark = Math.Max((_highPressureMark + _lowPressureMark) / 2, _limit - (_maxDelta * 2 * MEDIUM_FREQ_INTERVAL_S)); _mediumPressureMark = Math.Min(_highPressureMark, _mediumPressureMark); #if PERF SafeNativeMethods.OutputDebugString(String.Format("CacheManager.AdjustMaxDeltaAndPressureMarks: _highPressureMark={0:N}, _mediumPressureMark={1:N}, _lowPressureMark={2:N}, _maxDelta={3:N}\n", _highPressureMark, _mediumPressureMark, _lowPressureMark, _maxDelta)); #endif #if DBG Debug.Trace("CacheMemory", "AdjustMaxDeltaAndPressureMarks " + "delta=" + delta + ", _maxDelta=" + _maxDelta + ", _highPressureMark=" + _highPressureMark + ", _mediumPressureMark=" + _mediumPressureMark + ", _lowPressureMark=" + _lowPressureMark); #endif } }
// This function is named after a comment in the original code that sums up what it does nicely. // // now we zip up the path, composing config HttpConfigurationRecord ComposeConfig(String reqPath, IHttpMapPath configmap) { // remove ending "/" if (reqPath != null && reqPath.Length > 0 && reqPath[reqPath.Length - 1] == '/') { reqPath = reqPath.Substring(0, reqPath.Length - 1); } if (configmap == null && reqPath != null) { // // s_contextlessMapPath only works for paths from machine-level to application-level // This is only exposed to internal APIs, so this is just to make sure we don't break ourselves. // Debug.Assert(reqPath != null && (reqPath.Length > s_contextlessMapPath.ApplicationPath.Length || s_contextlessMapPath.ApplicationPath.Substring(0, reqPath.Length) == reqPath)); configmap = s_contextlessMapPath; } // QUICK: look up record in cache (case-insensitive) // // This is the common case because most pages are requested more than once every five minutes // Note: will be null on first invocation // HttpConfigurationRecord configRecord = CacheLookup(reqPath); if (configRecord != null) { return(configRecord); } DateTime utcStart = DateTime.UtcNow; // SLOW: hunt around // // Next, we start from the end of the request path and work our way toward the machine-level config // record. The first record we find is the one we use. Later we'll walk back down the path stack // building all the records that weren't found in the cache. // // Note: On first invocation for this appdomain we won't find anything in the cache, so we'll compose // all config records from machine-level down. // ArrayList pathStack = new ArrayList(); String path = reqPath; HttpConfigurationRecord parentRecord = null; for (;;) { // stack child pathStack.Add(path); // escape from root if (path == null) { break; } // go to parent path = ParentPath(path); // look it up parentRecord = CacheLookup(path); if (parentRecord == null) { configRecord = null; } else { if (parentRecord.IsInheritable) // only inherit from directory ConfigRecords, else keep looking { Debug.Trace("config", "Config located in cache " + QuoteString(path)); break; } configRecord = parentRecord; } } // now we zip down the path, composing config // // We walk down the path ... // For each directory, we build a config record and add a dependency on the config file // The first path that doesn't map to a directory we assume // is a file (leaf in the config system and not inheritable) // Anything left in the path stack after the file* is assumed to // be pathinfo** and is ignored. // // Notes: // * - we never verify the physical file, it's assumed if the mapped path // is not a directory (is this correct behavior?) // ** - pathinfo is the possible junk on the path after the file path: // example: http://localhost/myapp/foo.aspx/bar // /myapp/foo.aspx - file path (see Request.FilePath) // /bar - pathinfo // bool isDir = true; CacheInternal cacheInternal = HttpRuntime.CacheInternal; for (int i = pathStack.Count - 1; i >= 0 && isDir == true; i--) { String configFile = null; String mappedPath = null; Hashtable cachedeps = null; path = (String)pathStack[i]; if (path == null) { mappedPath = ""; if (configmap == null) { configFile = HttpConfigurationSystemBase.MachineConfigurationFilePath; } else { configFile = configmap.MachineConfigPath; } // null MachineConfigPath -> never cache config - always return an empty record. if (configFile == null) { return(HttpConfigurationRecord.Empty); } AddFileDependency(configFile); } else { if (IsPath(path)) { mappedPath = configmap.MapPath(path); if (IsDirectory(mappedPath)) { // for the directory case, grab the config file and a dependency on it configFile = Path.Combine(mappedPath, WebConfigFileName); AddFileDependency(configFile); } else { // otherwise, we're a file and we go ahead and compute as a file isDir = false; // break loop (after record is built) // we need make the cache item dependent on the mapped file location // in case it becomes a directory. if (mappedPath != null) { Debug.Assert(cachedeps == null, "ctracy investigation - cachedeps == null"); cachedeps = new Hashtable(SymbolHashCodeProvider.Default, SymbolEqualComparer.Default); cachedeps[mappedPath] = mappedPath; } } } } configRecord = new HttpConfigurationRecord(configFile, parentRecord, /*mappedPath,*/ isDir, path); string key = CacheKey(path); CacheDependency dependency = GetCacheDependencies(cachedeps, utcStart); Debug.Trace("config_verbose", "Inserting :" + path); if (IsBreakOnUnrecognizedElement) { // If the registry key is set to debug the rare 'Unrecognized Element' // stress error, lets try to reproduce the error by having an absolute // expiry of 5 minutes (this will cause us to re-read config much more // often. Before it took memory pressure. DateTime absouteExpiry = DateTime.UtcNow + new TimeSpan(0, 5, 0); cacheInternal.UtcInsert(key, configRecord, dependency, absouteExpiry, Cache.NoSlidingExpiration); } else { if (configRecord.HasError) { cacheInternal.UtcInsert(key, configRecord, dependency, DateTime.UtcNow.AddSeconds(5), Cache.NoSlidingExpiration); } else { // default: default cache priority, sliding expiration // this will make us rarely expire, config is expensive cacheInternal.UtcInsert(key, configRecord, dependency); } } // This is to wire-up notification of directories who exist (without a config file) and // are then deleted. In this case we don't want to restart the appdomain because no config information has // changed. We do want to remove the cache record and recreate it on the next request. (Something in // the cache record might be assuming the directory still exists.) if (isDir && !FileUtil.FileExists(configFile) && HandlerBase.IsPathAtAppLevel(path) == PathLevel.BelowApp) { //AddDirectoryDependency(mappedPath, path, configRecord); } configRecord.CheckCachedException(); parentRecord = configRecord; } return(configRecord); }
private void CollectInfrequently(long privateBytes) { // not thread-safe, only invoke from timer callback Debug.Assert(_inPBytesMonitorThread == 1); // The Server GC on x86 can traverse ~200mb per CPU per second, and the maximum heap size // is about 3400mb, so the worst case scenario on x86 would take about 8 seconds to collect // on a dual CPU box. // // The Server GC on x64 can traverse ~300mb per CPU per second, so a 6000 MB heap will take // about 10 seconds to collect on a dual CPU box. The worst case scenario on x64 would make // you want to return your hardware for a refund. long timeSinceInducedGC = DateTime.UtcNow.Subtract(_inducedGCFinishTime).Ticks; bool infrequent = (timeSinceInducedGC > _inducedGCMinInterval); // if we haven't collected recently, or if the trim percent is low (less than 50%), // we need to collect again if (infrequent || _lastTrimPercent < 50) { // if we're inducing GC too frequently, increase the trim percentage, but don't go above 50% if (!infrequent) { _lastTrimPercent = Math.Min(50, _lastTrimPercent + 10); } // if we're inducing GC infrequently, we may want to decrease the trim percentage else if (_lastTrimPercent > 10 && timeSinceInducedGC > 2 * _inducedGCMinInterval) { _lastTrimPercent = Math.Max(10, _lastTrimPercent - 10); } int percent = (_totalCacheSize > 0) ? _lastTrimPercent : 0; long trimmedOrExpired = 0; if (percent > 0) { Stopwatch sw1 = Stopwatch.StartNew(); trimmedOrExpired = _appManager.TrimCaches(percent); sw1.Stop(); _trimDurationTicks = sw1.Elapsed.Ticks; } // if (trimmedOrExpired == 0 || _appManager.ShutdownInProgress) { return; } // collect and record statistics Stopwatch sw2 = Stopwatch.StartNew(); GC.Collect(); sw2.Stop(); _inducedGCCount++; // only used for debugging _inducedGCFinishTime = DateTime.UtcNow; _inducedGCDurationTicks = sw2.Elapsed.Ticks; _inducedGCPostPrivateBytes = NextSample(); _inducedGCPrivateBytesChange = privateBytes - _inducedGCPostPrivateBytes; // target 3.3% Time in GC, but don't induce a GC more than once every 5 seconds // Notes on calculation below: If G is duration of garbage collection and T is duration // between starting the next collection, then G/T is % Time in GC. If we target 3.3%, // then G/T = 3.3% = 33/1000, so T = G * 1000/33. _inducedGCMinInterval = Math.Max(_inducedGCDurationTicks * 1000 / 33, 5 * TimeSpan.TicksPerSecond); // no more frequently than every 60 seconds if change is less than 1% if (_inducedGCPrivateBytesChange * 100 <= privateBytes) { _inducedGCMinInterval = Math.Max(_inducedGCMinInterval, 60 * TimeSpan.TicksPerSecond); } #if DBG Debug.Trace("CacheMemory", "GC.COLLECT STATS " + "TrimCaches(" + percent + ")" + ", trimDurationSeconds=" + (_trimDurationTicks / TimeSpan.TicksPerSecond) + ", trimmedOrExpired=" + trimmedOrExpired + ", #secondsSinceInducedGC=" + (timeSinceInducedGC / TimeSpan.TicksPerSecond) + ", InducedGCCount=" + _inducedGCCount + ", gcDurationSeconds=" + (_inducedGCDurationTicks / TimeSpan.TicksPerSecond) + ", PrePrivateBytes=" + privateBytes + ", PostPrivateBytes=" + _inducedGCPostPrivateBytes + ", PrivateBytesChange=" + _inducedGCPrivateBytesChange + ", gcMinIntervalSeconds=" + (_inducedGCMinInterval / TimeSpan.TicksPerSecond)); #endif #if PERF SafeNativeMethods.OutputDebugString(" ** COLLECT **: " + percent + "%, " + (_trimDurationTicks / TimeSpan.TicksPerSecond) + " seconds" + ", infrequent=" + infrequent + ", removed=" + trimmedOrExpired + ", sinceIGC=" + (timeSinceInducedGC / TimeSpan.TicksPerSecond) + ", IGCCount=" + _inducedGCCount + ", IGCDuration=" + (_inducedGCDurationTicks / TimeSpan.TicksPerSecond) + ", preBytes=" + privateBytes + ", postBytes=" + _inducedGCPostPrivateBytes + ", byteChange=" + _inducedGCPrivateBytesChange + ", IGCMinInterval=" + (_inducedGCMinInterval / TimeSpan.TicksPerSecond) + "\n"); #endif } }
private Control LoadControl(IWebObjectFactory objectFactory, VirtualPath virtualPath, Type t, object[] parameters) { // Make sure we get an object factory or a type, but not both Debug.Assert((objectFactory == null) != (t == null)); BuildResultCompiledType compiledUCResult = null; BuildResultNoCompileUserControl noCompileUCResult = null; if (objectFactory != null) { // It can be a compiled or no-compile user control compiledUCResult = objectFactory as BuildResultCompiledType; if (compiledUCResult != null) { t = compiledUCResult.ResultType; Debug.Assert(t != null); // Make sure it's a user control (VSWhidbey 428718) Util.CheckAssignableType(typeof(UserControl), t); } else { noCompileUCResult = (BuildResultNoCompileUserControl)objectFactory; Debug.Assert(noCompileUCResult != null); } } else { // Make sure the type has the correct base class (ASURT 123677) if (t != null) { Util.CheckAssignableType(typeof(Control), t); } } PartialCachingAttribute cacheAttrib; // Check if the user control has a PartialCachingAttribute attribute if (t != null) { cacheAttrib = (PartialCachingAttribute) TypeDescriptor.GetAttributes(t)[typeof(PartialCachingAttribute)]; } else { cacheAttrib = noCompileUCResult.CachingAttribute; } if (cacheAttrib == null) { // The control is not cached. Just create it. Control c; if (objectFactory != null) { c = (Control)objectFactory.CreateInstance(); } else { c = (Control)HttpRuntime.CreatePublicInstance(t, parameters); } // If it's a user control, do some extra initialization UserControl uc = c as UserControl; if (uc != null) { Debug.Assert(virtualPath != null); if (virtualPath != null) { uc.TemplateControlVirtualPath = virtualPath; } uc.InitializeAsUserControl(Page); } return(c); } HashCodeCombiner combinedHashCode = new HashCodeCombiner(); // Start by adding the type or object factory of the user control to the hash. // This guarantees that two unrelated user controls don't share the same cached data. if (objectFactory != null) { combinedHashCode.AddObject(objectFactory); } else { combinedHashCode.AddObject(t); } // If it's not shared, add some stack frames to the hash if (!cacheAttrib.Shared) { AddStackContextToHashCode(combinedHashCode); } string cacheKey = combinedHashCode.CombinedHashString; // Wrap it to allow it to be cached return(new PartialCachingControl(objectFactory, t, cacheAttrib, "_" + cacheKey, parameters)); }
/* * Build first-time intialization statements */ protected override void BuildInitStatements(CodeStatementCollection trueStatements, CodeStatementCollection topLevelStatements) { base.BuildInitStatements(trueStatements, topLevelStatements); // CodeMemberField fileDependencies = new CodeMemberField(typeof(object), fileDependenciesName); fileDependencies.Attributes |= MemberAttributes.Static; _sourceDataClass.Members.Add(fileDependencies); // Note: it may look like this local variable declaration is redundant. However it is necessary // to make this init code re-entrant safe. This way, even if two threads enter the contructor // at the same time, they will not add multiple dependencies. // e.g. string[] dependencies; CodeVariableDeclarationStatement dependencies = new CodeVariableDeclarationStatement(); dependencies.Type = new CodeTypeReference(typeof(string[])); dependencies.Name = dependenciesLocalName; // Note: it is important to add all local variables at the top level for CodeDom Subset compliance. topLevelStatements.Insert(0, dependencies); Debug.Assert(Parser.SourceDependencies != null); StringSet virtualDependencies = new StringSet(); virtualDependencies.AddCollection(Parser.SourceDependencies); // e.g. dependencies = new string[{{virtualDependencies.Count}}];; CodeAssignStatement assignDependencies = new CodeAssignStatement(); assignDependencies.Left = new CodeVariableReferenceExpression(dependenciesLocalName); assignDependencies.Right = new CodeArrayCreateExpression(typeof(String), virtualDependencies.Count); trueStatements.Add(assignDependencies); int i = 0; foreach (string virtualDependency in virtualDependencies) { // e.g. dependencies[i] = "~/sub/foo.aspx"; CodeAssignStatement addFileDep = new CodeAssignStatement(); addFileDep.Left = new CodeArrayIndexerExpression( new CodeVariableReferenceExpression(dependenciesLocalName), new CodeExpression[] { new CodePrimitiveExpression(i++) }); string src = UrlPath.MakeVirtualPathAppRelative(virtualDependency); addFileDep.Right = new CodePrimitiveExpression(src); trueStatements.Add(addFileDep); } // e.g. __fileDependencies = this.GetWrappedFileDependencies(dependencies); CodeAssignStatement initFile = new CodeAssignStatement(); initFile.Left = new CodeFieldReferenceExpression(_classTypeExpr, fileDependenciesName); CodeMethodInvokeExpression createWrap = new CodeMethodInvokeExpression(); createWrap.Method.TargetObject = new CodeThisReferenceExpression(); createWrap.Method.MethodName = "GetWrappedFileDependencies"; createWrap.Parameters.Add(new CodeVariableReferenceExpression(dependenciesLocalName)); initFile.Right = createWrap; #if DBG AppendDebugComment(trueStatements); #endif trueStatements.Add(initFile); }