Exemplo n.º 1
0
        private static void BasicBatchCompilation(HttpContext context,
                                                  CompilerInfo compInfo, PagesWithSameCompilerInfo pwsci)
        {
            ICodeCompiler compiler = pwsci.CodeProvider.CreateCompiler();

            Debug.Trace("Batching", "Compiling " + pwsci.PageCount + " pages");

            CompilerParameters compilParams = compInfo.CompilParams;

            compilParams.TempFiles = new TempFileCollection(HttpRuntime.CodegenDirInternal);

            // Create the resource file (shared by all the pages in the bucket)
            if (pwsci._stringResourceBuilder.HasStrings)
            {
                string resFileName = compilParams.TempFiles.AddExtension("res");
                pwsci._stringResourceBuilder.CreateResourceFile(resFileName);
                compilParams.Win32Resource = resFileName;
            }

            // Never generate debug code when we're batching
            compilParams.TempFiles.KeepFiles     = false;
            compilParams.IncludeDebugInformation = false;

            // Compute a table of all the assemblies used by all the pages in the
            // bucket, removing duplicates
            Hashtable allAssemblies = new Hashtable();

            // Place all the generated source file names in an array
            string[] files     = new string[pwsci.PageCount];
            int      fileCount = 0;

            foreach (BatchCompilationEntry e in pwsci.Pages)
            {
                Debug.Assert(FileUtil.FileExists(e.GeneratedSourceFile), e.GeneratedSourceFile + " is missing!");

                files[fileCount++] = e.GeneratedSourceFile;

                // Add all the assemblies
                if (e.AssemblyDependencies != null)
                {
                    foreach (Assembly assembly in e.AssemblyDependencies.Keys)
                    {
                        string assemblyName = Util.GetAssemblyCodeBase(assembly);
                        allAssemblies[assemblyName] = null;
                    }
                }
            }
            Debug.Assert(fileCount == pwsci.PageCount, "fileCount == pwsci.PageCount");

            // Now, add all the (non-duplicate) assemblies to the compilParams
            foreach (string aname in allAssemblies.Keys)
            {
                compilParams.ReferencedAssemblies.Add(aname);
            }

            // Compile them all together into an assembly
            CompilerResults results;

            try {
                results = compiler.CompileAssemblyFromFileBatch(compilParams, files);
            }
            catch (Exception e) {
                Debug.Trace("Batching", "Compilation failed!  " + e.Message);
                throw new HttpUnhandledException(HttpRuntime.FormatResourceString(SR.CompilationUnhandledException, pwsci.CodeProvider.GetType().FullName), e);
            }
            finally {
                // Delete all the generated source files
                for (int i = 0; i < fileCount; i++)
                {
                    File.Delete(files[i]);
                }
            }

            BaseCompiler.ThrowIfCompilerErrors(results, pwsci.CodeProvider, null, null, null);

            // Note the assembly that everything ended up in
            foreach (BatchCompilationEntry e in pwsci.Pages)
            {
                e.SetTargetAssembly(results.CompiledAssembly);
                CacheResults(context, e);

                // Do some cleanup
                e.PostCompilation();
            }
        }
Exemplo n.º 2
0
        private static void BatchCompile(ArrayList inputList, HttpContext context, string virtualDir)
        {
            Exception errorException = null;

            // Used to create temporary source files
            TempFileCollection tempFiles = new TempFileCollection(HttpRuntime.CodegenDirInternal);

            // Counter to name generated files uniquely
            int fileCount = 0;

            int maxBatchGeneratedFileSize = CompilationConfiguration.GetMaxBatchGeneratedFileSize(context);
            int maxBatchSize = CompilationConfiguration.GetMaxBatchSize(context);

            Hashtable languageBuckets = new Hashtable();

            // Go through all the files that need to be compiled
            foreach (BatchCompilationEntry currentPage in inputList)
            {
                // precompile, and skip pages that fail to precompile
                try {
                    currentPage.Precompile();
                }
                catch (Exception e) {
                    // remember the first exception
                    if (errorException == null)
                    {
                        errorException = e;
                    }

                    Debug.Trace("Batching", "Skipping " + currentPage.PageFilename + " due to parse error ("
                                + e.Message + ")");

                    continue;
                }

                // Skip trivial pages and pages that have the debug flag
                if (currentPage.IsTrivialPage() || currentPage.IsDebugPage())
                {
                    continue;
                }

                // Determine what language bucket it belongs to based on the CompilerInfo
                CompilerInfo compInfo           = currentPage.CompilerInfo;
                PagesWithSameCompilerInfo pwsci = (PagesWithSameCompilerInfo)languageBuckets[compInfo];
                if (pwsci == null)
                {
                    pwsci = new PagesWithSameCompilerInfo(currentPage.CompilerInfo.CompilerType,
                                                          maxBatchGeneratedFileSize * 1024, maxBatchSize);
                    languageBuckets[compInfo] = pwsci;
                }

                ICodeGenerator generator = pwsci.CodeProvider.CreateGenerator();

                // Build the CodeDOM tree for the page
                currentPage.BuildCodeModel(generator, pwsci._stringResourceBuilder);
                CodeCompileUnit compileUnit = currentPage.GetCodeModel();

                // Generate a temporary source file from the CodeDOM tree
                string filename = tempFiles.AddExtension(
                    (fileCount++) + "." + pwsci.CodeProvider.FileExtension, true /*keepFiles*/);
                Stream temp = new FileStream(filename, FileMode.Create, FileAccess.Write, FileShare.Read);
                try {
                    StreamWriter sw = new StreamWriter(temp, Encoding.UTF8);
                    generator.GenerateCodeFromCompileUnit(compileUnit, sw, null /*CodeGeneratorOptions*/);
                    sw.Flush();
                    sw.Close();
                }
                finally {
                    temp.Close();
                }

                currentPage.GeneratedSourceFile = filename;

                // This releases a number of things that are no longer needed after this point
                currentPage.PostSourceCodeGeneration();

                // Add it to the language bucket
                pwsci.AddPage(currentPage);

                // If the bucket is full, compile all its pages and get rid of it
                if (pwsci.IsBucketFull)
                {
                    try {
                        BasicBatchCompilation(context, compInfo.Clone(), pwsci);

                        // Tell the server that we're still running to make sure it doesn't kill us (ASURT 96452)
                        context.SendEmptyResponse();
                    }
                    catch (Exception e) {
                        // remember the first exception
                        if (errorException == null)
                        {
                            errorException = e;
                        }
                    }
                    languageBuckets.Remove(compInfo);
                }
            }

            // Compile whatever is left in all the buckets
            for (IDictionaryEnumerator de = (IDictionaryEnumerator)languageBuckets.GetEnumerator(); de.MoveNext();)
            {
                try {
                    BasicBatchCompilation(context, ((CompilerInfo)de.Key).Clone(),
                                          (PagesWithSameCompilerInfo)de.Value);
                }
                catch (Exception e) {
                    // remember the first exception
                    if (errorException == null)
                    {
                        errorException = e;
                    }
                }
            }

            // If there was an error, rethrow it
            if (errorException != null)
            {
                throw new HttpException(null, errorException);
            }
        }