<commit_before>using Microsoft.Extensions.DependencyInjection;

namespace Orleans.CodeGeneration
{
    using System;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.Reflection;
    using Orleans.Runtime;

    /// <summary>
    /// Methods for invoking code generation.
    /// </summary>
    internal class CodeGeneratorManager
    {
        /// <summary>
        /// The name of the code generator assembly.
        /// </summary>
        private const string CodeGenAssemblyName = "OrleansCodeGenerator";

        /// <summary>
        /// The log.
        /// </summary>
        private static readonly Logger Log = LogManager.GetLogger("CodeGenerator");

        /// <summary>
        /// Empty generated assemblies.
        /// </summary>
        private static readonly ReadOnlyDictionary<string, GeneratedAssembly> EmptyGeneratedAssemblies =
            new ReadOnlyDictionary<string, GeneratedAssembly>(new Dictionary<string, GeneratedAssembly>());

        /// <summary>
        /// The runtime code generator.
        /// </summary>
        private IRuntimeCodeGenerator codeGeneratorInstance;

        /// <summary>
        /// The code generator cache.
        /// </summary>
        private static ICodeGeneratorCache codeGeneratorCacheInstance;

        private readonly IServiceProvider serviceProvider;

        public CodeGeneratorManager(IServiceProvider serviceProvider)
        {
            this.serviceProvider = serviceProvider;
        }

        /// <summary>
        /// Loads the code generator on demand
        /// </summary>
        public void Initialize()
        {
            this.codeGeneratorInstance = this.serviceProvider.GetService<IRuntimeCodeGenerator>() ?? this.LoadCodeGenerator();
            codeGeneratorCacheInstance = this.codeGeneratorInstance as ICodeGeneratorCache;
        }

        /// <summary>
        /// Ensures code for the <paramref name="input"/> assembly has been generated and loaded.
        /// </summary>
        /// <param name="input">
        /// The input assembly.
        /// </param>
        public GeneratedAssembly GenerateAndCacheCodeForAssembly(Assembly input)
        {
            return codeGeneratorInstance?.GenerateAndLoadForAssembly(input);
        }

        /// <summary>
        /// Ensures code for all currently loaded assemblies has been generated and loaded.
        /// </summary>
        /// <param name="inputs">The assemblies to generate code for.</param>
        public IReadOnlyList<GeneratedAssembly> GenerateAndLoadForAssemblies(Assembly[] inputs)
        {
            return codeGeneratorInstance?.GenerateAndLoadForAssemblies(inputs);
        }

        /// <summary>
        /// Returns the collection of generated assemblies as pairs of target assembly name to raw assembly bytes.
        /// </summary>
        /// <returns>The collection of generated assemblies.</returns>
        public static IDictionary<string, GeneratedAssembly> GetGeneratedAssemblies()
        {
            if (codeGeneratorCacheInstance != null)
            {
                return codeGeneratorCacheInstance.GetGeneratedAssemblies();
            }

            return EmptyGeneratedAssemblies;
        }

        /// <summary>
        /// Adds a pre-generated assembly to the assembly cache.
        /// </summary>
        /// <param name="targetAssemblyName">
        /// The name of the assembly the provided <paramref name="generatedAssembly"/> targets.
        /// </param>
        /// <param name="generatedAssembly">
        /// The generated assembly.
        /// </param>
        public static void AddGeneratedAssembly(string targetAssemblyName, GeneratedAssembly generatedAssembly)
        {
            if (codeGeneratorCacheInstance != null)
            {
                codeGeneratorCacheInstance.AddGeneratedAssembly(targetAssemblyName, generatedAssembly);
            }
            else
            {
                Log.Warn(
                    ErrorCode.CodeGenDllMissing,
                    "CodeGenerationManager.AddCachedAssembly called but no code generator has been loaded.");
            }
        }

        /// <summary>
        /// Loads the code generator.
        /// </summary>
        /// <returns>The code generator.</returns>
        private IRuntimeCodeGenerator LoadCodeGenerator()
        {
            IRuntimeCodeGenerator result = AssemblyLoader.TryLoadAndCreateInstance<IRuntimeCodeGenerator>(CodeGenAssemblyName, Log, this.serviceProvider);
            if (result == null)
            {
                Log.Warn(
                    ErrorCode.CodeGenDllMissing,<commit_msg>Reduce severity of ~"codegen asm not present" message from Warn to Info (#2739)<commit_after>using Microsoft.Extensions.DependencyInjection;

namespace Orleans.CodeGeneration
{
    using System;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.Reflection;
    using Orleans.Runtime;

    /// <summary>
    /// Methods for invoking code generation.
    /// </summary>
    internal class CodeGeneratorManager
    {
        /// <summary>
        /// The name of the code generator assembly.
        /// </summary>
        private const string CodeGenAssemblyName = "OrleansCodeGenerator";

        /// <summary>
        /// The log.
        /// </summary>
        private static readonly Logger Log = LogManager.GetLogger("CodeGenerator");

        /// <summary>
        /// Empty generated assemblies.
        /// </summary>
        private static readonly ReadOnlyDictionary<string, GeneratedAssembly> EmptyGeneratedAssemblies =
            new ReadOnlyDictionary<string, GeneratedAssembly>(new Dictionary<string, GeneratedAssembly>());

        /// <summary>
        /// The runtime code generator.
        /// </summary>
        private IRuntimeCodeGenerator codeGeneratorInstance;

        /// <summary>
        /// The code generator cache.
        /// </summary>
        private static ICodeGeneratorCache codeGeneratorCacheInstance;

        private readonly IServiceProvider serviceProvider;

        public CodeGeneratorManager(IServiceProvider serviceProvider)
        {
            this.serviceProvider = serviceProvider;
        }

        /// <summary>
        /// Loads the code generator on demand
        /// </summary>
        public void Initialize()
        {
            this.codeGeneratorInstance = this.serviceProvider.GetService<IRuntimeCodeGenerator>() ?? this.LoadCodeGenerator();
            codeGeneratorCacheInstance = this.codeGeneratorInstance as ICodeGeneratorCache;
        }

        /// <summary>
        /// Ensures code for the <paramref name="input"/> assembly has been generated and loaded.
        /// </summary>
        /// <param name="input">
        /// The input assembly.
        /// </param>
        public GeneratedAssembly GenerateAndCacheCodeForAssembly(Assembly input)
        {
            return codeGeneratorInstance?.GenerateAndLoadForAssembly(input);
        }

        /// <summary>
        /// Ensures code for all currently loaded assemblies has been generated and loaded.
        /// </summary>
        /// <param name="inputs">The assemblies to generate code for.</param>
        public IReadOnlyList<GeneratedAssembly> GenerateAndLoadForAssemblies(Assembly[] inputs)
        {
            return codeGeneratorInstance?.GenerateAndLoadForAssemblies(inputs);
        }

        /// <summary>
        /// Returns the collection of generated assemblies as pairs of target assembly name to raw assembly bytes.
        /// </summary>
        /// <returns>The collection of generated assemblies.</returns>
        public static IDictionary<string, GeneratedAssembly> GetGeneratedAssemblies()
        {
            if (codeGeneratorCacheInstance != null)
            {
                return codeGeneratorCacheInstance.GetGeneratedAssemblies();
            }

            return EmptyGeneratedAssemblies;
        }

        /// <summary>
        /// Adds a pre-generated assembly to the assembly cache.
        /// </summary>
        /// <param name="targetAssemblyName">
        /// The name of the assembly the provided <paramref name="generatedAssembly"/> targets.
        /// </param>
        /// <param name="generatedAssembly">
        /// The generated assembly.
        /// </param>
        public static void AddGeneratedAssembly(string targetAssemblyName, GeneratedAssembly generatedAssembly)
        {
            if (codeGeneratorCacheInstance != null)
            {
                codeGeneratorCacheInstance.AddGeneratedAssembly(targetAssemblyName, generatedAssembly);
            }
            else
            {
                Log.Warn(
                    ErrorCode.CodeGenDllMissing,
                    "CodeGenerationManager.AddCachedAssembly called but no code generator has been loaded.");
            }
        }

        /// <summary>
        /// Loads the code generator.
        /// </summary>
        /// <returns>The code generator.</returns>
        private IRuntimeCodeGenerator LoadCodeGenerator()
        {
            IRuntimeCodeGenerator result = AssemblyLoader.TryLoadAndCreateInstance<IRuntimeCodeGenerator>(CodeGenAssemblyName, Log, this.serviceProvider);
            if (result == null)
            {
                Log.Info(
                    ErrorCode.CodeGenDllMissing,
{'fraction_non_alphanumeric': 0.09527878658406323, 'fraction_numerical': 0.0004272591326639607, 'mean_word_length': 2.031078018776303, 'pattern_counts': {'":': 0, '<': 93, '<?xml version=': 0, '>': 93, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2135400', 'n_tokens_mistral': 2130, 'n_tokens_neox': 2042, 'n_words': 557}