private static CommandInfo Build(CommandInfo parent, ConfiguredCommand command)
        {
            var info = new CommandInfo(parent, command);

            foreach (var parameter in GetParameters(info))
            {
                info.Parameters.Add(parameter);
            }

            foreach (var childCommand in command.Children)
            {
                var child = Build(info, childCommand);
                info.Children.Add(child);
            }

            // Normalize argument positions.
            var index = 0;

            foreach (var argument in info.Parameters.OfType <CommandArgument>()
                     .OrderBy(argument => argument.Position))
            {
                argument.Position = index;
                index++;
            }

            return(info);
        }
Exemple #2
0
    public CommandInfo(CommandInfo?parent, ConfiguredCommand prototype)
    {
        Parent = parent;

        Name             = prototype.Name;
        Aliases          = new HashSet <string>(prototype.Aliases);
        Description      = prototype.Description;
        Data             = prototype.Data;
        CommandType      = prototype.CommandType;
        SettingsType     = prototype.SettingsType;
        Delegate         = prototype.Delegate;
        IsDefaultCommand = prototype.IsDefaultCommand;
        IsHidden         = prototype.IsHidden;

        Children   = new List <CommandInfo>();
        Parameters = new List <CommandParameter>();
        Examples   = prototype.Examples ?? new List <string[]>();

        if (CommandType != null && string.IsNullOrWhiteSpace(Description))
        {
            var description = CommandType.GetCustomAttribute <DescriptionAttribute>();
            if (description != null)
            {
                Description = description.Description;
            }
        }
    }
    public ICommandConfigurator AddCommand <TCommand>(string name)
        where TCommand : class, ICommand
    {
        var command = Commands.AddAndReturn(ConfiguredCommand.FromType <TCommand>(name, false));

        return(new CommandConfigurator(command));
    }
    public ICommandConfigurator AddDelegate <TSettings>(string name, Func <CommandContext, TSettings, int> func)
        where TSettings : CommandSettings
    {
        var command = Commands.AddAndReturn(ConfiguredCommand.FromDelegate <TSettings>(
                                                name, (context, settings) => func(context, (TSettings)settings)));

        return(new CommandConfigurator(command));
    }
    public void AddBranch <TSettings>(string name, Action <IConfigurator <TSettings> > action)
        where TSettings : CommandSettings
    {
        var command = ConfiguredCommand.FromBranch <TSettings>(name);

        action(new Configurator <TSettings>(command, _registrar));
        Commands.Add(command);
    }
Exemple #6
0
    public void AddBranch <TDerivedSettings>(string name, Action <IConfigurator <TDerivedSettings> > action)
        where TDerivedSettings : TSettings
    {
        var command = ConfiguredCommand.FromBranch <TDerivedSettings>(name);

        action(new Configurator <TDerivedSettings>(command, _registrar));
        _command.Children.Add(command);
    }
Exemple #7
0
    public ICommandConfigurator AddDelegate <TDerivedSettings>(string name, Func <CommandContext, TDerivedSettings, int> func)
        where TDerivedSettings : TSettings
    {
        var command = ConfiguredCommand.FromDelegate <TDerivedSettings>(
            name, (context, settings) => func(context, (TDerivedSettings)settings));

        _command.Children.Add(command);
        return(new CommandConfigurator(command));
    }
Exemple #8
0
    public ICommandConfigurator AddCommand <TCommand>(string name)
        where TCommand : class, ICommandLimiter <TSettings>
    {
        var command      = ConfiguredCommand.FromType <TCommand>(name);
        var configurator = new CommandConfigurator(command);

        _command.Children.Add(command);
        return(configurator);
    }
Exemple #9
0
        public CommandInfo(CommandInfo parent, ConfiguredCommand prototype)
        {
            Parent = parent;

            Name         = prototype.Name;
            Description  = prototype.Description;
            CommandType  = prototype.CommandType;
            SettingsType = prototype.SettingsType;

            Children   = new List <CommandInfo>();
            Parameters = new List <CommandParameter>();
        }
Exemple #10
0
        public void TestConnectionErrorExitCode()
        {
            ConfiguredCommand conf = ParseArgs($"{StopDaemonCmd.Name} --{Moniker.LongName} 1 --{ConnectRetryDelayMillis.LongName} 10 --{MaxConnectRetries.LongName} 0");

            using (var client = CreateClient(conf))
            {
                var exitCode = conf.Command.ClientAction(conf, client);
                Assert.Equal((int)IpcResultStatus.ConnectionError, exitCode);
                client.RequestStop();
                client.Completion.GetAwaiter().GetResult();
            }
        }
    void IUnsafeConfigurator.AddBranch(string name, Type settings, Action <IUnsafeBranchConfigurator> action)
    {
        var command = ConfiguredCommand.FromBranch(settings, name);

        // Create the configurator.
        var configuratorType = typeof(Configurator <>).MakeGenericType(settings);

        if (!(Activator.CreateInstance(configuratorType, new object?[] { command, _registrar }) is IUnsafeBranchConfigurator configurator))
        {
            throw new CommandConfigurationException("Could not create configurator by reflection.");
        }

        action(configurator);
        Commands.Add(command);
    }
Exemple #12
0
 private Thread CreateThreadForCommand(string cmdLine, IClient client)
 {
     return(new Thread(() =>
     {
         Console.WriteLine($"running command: " + cmdLine);
         var logger = new LambdaLogger((level, format, args) =>
         {
             var formatted = LoggerExtensions.Format(level, format, args);
             Console.WriteLine(format);
             Output.WriteLine(format);
         });
         ConfiguredCommand conf = ParseArgs(cmdLine, UnixParser.Instance, logger);
         var exitCode = conf.Command.ClientAction(conf, client);
         Assert.Equal(0, exitCode);
     }));
 }
Exemple #13
0
        private static async Task <IIpcResult> RegisterManifestInternalAsync(ConfiguredCommand conf, MaterializationDaemon daemon)
        {
            var directoryPaths = Directory.GetValues(conf.Config).ToArray();
            var directoryIds   = DirectoryId.GetValues(conf.Config).ToArray();

            if (directoryPaths.Length != directoryIds.Length)
            {
                return(new IpcResult(
                           IpcResultStatus.GenericError,
                           I($"Directory counts don't match: #directories = {directoryPaths.Length}, #directoryIds = {directoryIds.Length}")));
            }

            if (daemon.ApiClient == null)
            {
                return(new IpcResult(IpcResultStatus.GenericError, "ApiClient is not initialized"));
            }

            var manifests = new List <SealedDirectoryFile>();

            for (int i = 0; i < directoryIds.Length; i++)
            {
                var directoryArtifact = BuildXL.Ipc.ExternalApi.DirectoryId.Parse(directoryIds[i]);
                var possibleContent   = await daemon.ApiClient.GetSealedDirectoryContent(directoryArtifact, directoryPaths[i]);

                if (!possibleContent.Succeeded)
                {
                    return(new IpcResult(
                               IpcResultStatus.GenericError,
                               I($"Failed to get the content of a directory artifact ({directoryIds[i]}, {directoryPaths[i]}){Environment.NewLine}{possibleContent.Failure.DescribeIncludingInnerFailures()}")));
                }

                manifests.AddRange(possibleContent.Result);
            }

            daemon.Logger.Verbose(string.Join(Environment.NewLine, manifests.Select(f => f.FileName)));

            // TODO: placeholder for now - to be implemented in another pr
            return(IpcResult.Success("done"));
        }
Exemple #14
0
        public CommandInfo(CommandInfo parent, ConfiguredCommand prototype)
        {
            Parent = parent;

            Name             = prototype.Name;
            Description      = prototype.Description;
            CommandType      = prototype.CommandType;
            SettingsType     = prototype.SettingsType;
            IsDefaultCommand = prototype.IsDefaultCommand;

            Children   = new List <CommandInfo>();
            Parameters = new List <CommandParameter>();
            Examples   = prototype.Examples ?? new List <string[]>();

            if (!IsBranch)
            {
                var description = CommandType.GetCustomAttribute <DescriptionAttribute>();
                if (description != null)
                {
                    Description = description.Description;
                }
            }
        }
        private static CommandInfo Build(CommandInfo parent, ConfiguredCommand command)
        {
            var info = new CommandInfo(parent, command);

            if (!info.IsProxy)
            {
                var description = info.CommandType.GetCustomAttribute <DescriptionAttribute>();
                if (description != null)
                {
                    info.Description = description.Description;
                }
            }

            foreach (var parameter in GetParameters(info))
            {
                info.Parameters.Add(parameter);
            }

            foreach (var childCommand in command.Children)
            {
                var child = Build(info, childCommand);
                info.Children.Add(child);
            }

            // Normalize argument positions.
            var index = 0;

            foreach (var argument in info.Parameters.OfType <CommandArgument>()
                     .OrderBy(argument => argument.Position))
            {
                argument.Position = index;
                index++;
            }

            return(info);
        }
Exemple #16
0
 internal static MaterializationDaemonConfig CreateMaterializationDaemonConfig(ConfiguredCommand conf)
 {
     return(new MaterializationDaemonConfig(
                maxDegreeOfParallelism: conf.Get(MaxDegreeOfParallelism),
                parserExe: conf.Get(ManifestParserExeLocation),
                parserArgs: conf.Get(ManifestParserAdditionalArgs),
                logDir: conf.Get(LogDir)));
 }
Exemple #17
0
 public Configurator(ConfiguredCommand command, ITypeRegistrar?registrar)
 {
     _command   = command;
     _registrar = registrar;
 }
Exemple #18
0
        internal static IClient CreateClient(ConfiguredCommand conf)
        {
            var daemonConfig = ServicePipDaemon.ServicePipDaemon.CreateDaemonConfig(conf);

            return(IpcFactory.GetProvider().GetClient(daemonConfig.Moniker, daemonConfig));
        }
 public void SetDefaultCommand <TDefaultCommand>()
     where TDefaultCommand : class, ICommand
 {
     DefaultCommand = ConfiguredCommand.FromType <TDefaultCommand>(
         CliConstants.DefaultCommandName, isDefaultCommand: true);
 }
 public static void ShouldBeBranch <TSettings>(this ConfiguredCommand command)
 {
     command.CommandType.ShouldBeNull();
     command.SettingsType.ShouldBe <TSettings>();
 }
Exemple #21
0
 internal static MaterializationDaemonConfig CreateMaterializationDaemonConfig(ConfiguredCommand conf)
 {
     return(new MaterializationDaemonConfig(
                maxDegreeOfParallelism: conf.Get(MaxDegreeOfParallelism),
                logDir: conf.Get(LogDir)));
 }
 public static void ShouldBeCommand <TCommand, TSettings>(this ConfiguredCommand command)
 {
     command.CommandType.ShouldBe <TCommand>();
     command.SettingsType.ShouldBe <TSettings>();
 }
Exemple #23
0
        private async Task <IIpcResult> MaterializeDirectoriesAsync(ConfiguredCommand conf)
        {
            m_counters.IncrementCounter(MaterializationDaemonCounter.MaterializeDirectoriesRequestCount);

            var directoryPaths       = Directory.GetValues(conf.Config).ToArray();
            var directoryIds         = DirectoryId.GetValues(conf.Config).ToArray();
            var directoryFilters     = DirectoryContentFilter.GetValues(conf.Config).ToArray();
            var directoryFilterKinds = DirectoryContentFilterKind.GetValues(conf.Config).ToArray();

            if (directoryPaths.Length != directoryIds.Length || directoryPaths.Length != directoryFilters.Length || directoryPaths.Length != directoryFilterKinds.Length)
            {
                return(new IpcResult(
                           IpcResultStatus.InvalidInput,
                           I($"Directory counts don't match: #directories = {directoryPaths.Length}, #directoryIds = {directoryIds.Length}, #directoryFilters = {directoryFilters.Length}, #directoryFilterKinds = {directoryFilterKinds.Length}")));
            }

            if (ApiClient == null)
            {
                return(new IpcResult(IpcResultStatus.GenericError, "ApiClient is not initialized"));
            }

            var possibleFilters = InitializeFilters(directoryFilters);

            if (!possibleFilters.Succeeded)
            {
                return(new IpcResult(IpcResultStatus.ExecutionError, possibleFilters.Failure.Describe()));
            }

            var possibleFilterKinds = ParseFilterKinds(directoryFilterKinds);

            if (!possibleFilterKinds.Succeeded)
            {
                return(new IpcResult(IpcResultStatus.InvalidInput, possibleFilterKinds.Failure.Describe()));
            }

            var initializedFilters = possibleFilters.Result;
            var filterKinds        = possibleFilterKinds.Result;
            var possibleFiles      = await GetUniqueFilteredDirectoryContentAsync(directoryPaths, directoryIds, initializedFilters, filterKinds);

            if (!possibleFiles.Succeeded)
            {
                return(new IpcResult(IpcResultStatus.ExecutionError, possibleFiles.Failure.Describe()));
            }

            var filesToMaterialize = possibleFiles.Result;
            var sw = Stopwatch.StartNew();

            using (m_counters.StartStopwatch(MaterializationDaemonCounter.MaterializeDirectoriesOuterMaterializationDuration))
            {
                try
                {
                    await m_actionQueue.ForEachAsync(
                        filesToMaterialize,
                        async (file, i) =>
                    {
                        m_counters.AddToCounter(MaterializationDaemonCounter.MaterializeDirectoriesMaterializationQueueDuration, sw.ElapsedMilliseconds);
                        await MaterializeFileAsync(file.Artifact, file.FileName, ignoreMaterializationFailures: false);
                    });
                }
                catch (Exception e)
                {
                    return(new IpcResult(
                               IpcResultStatus.GenericError,
                               e.ToStringDemystified()));
                }
            }

            m_counters.IncrementCounter(MaterializationDaemonCounter.MaterializeDirectoriesFilesToMaterialize);
            return(IpcResult.Success(
                       $"Materialized files ({filesToMaterialize.Count}):{Environment.NewLine}{string.Join(Environment.NewLine, filesToMaterialize.Select(f => f.FileName))}"));
        }
Exemple #24
0
        /// <summary>
        /// Takes a list of sealed directories, searches their contents for special manifest files, parses each of them to obtain
        /// a list of files to materialize, and finally requests from BuildXL's ApiServer to materialize them.
        /// </summary>
        private async Task <IIpcResult> RegisterManifestInternalAsync(ConfiguredCommand conf)
        {
            m_counters.IncrementCounter(MaterializationDaemonCounter.RegisterManifestRequestCount);

            var directoryPaths   = Directory.GetValues(conf.Config).ToArray();
            var directoryIds     = DirectoryId.GetValues(conf.Config).ToArray();
            var directoryFilters = DirectoryContentFilter.GetValues(conf.Config).ToArray();

            if (directoryPaths.Length != directoryIds.Length || directoryPaths.Length != directoryFilters.Length)
            {
                return(new IpcResult(
                           IpcResultStatus.GenericError,
                           I($"Directory counts don't match: #directories = {directoryPaths.Length}, #directoryIds = {directoryIds.Length}, #directoryFilters = {directoryFilters.Length}")));
            }

            if (ApiClient == null)
            {
                return(new IpcResult(IpcResultStatus.GenericError, "ApiClient is not initialized"));
            }

            var possibleFilters = InitializeFilters(directoryFilters);

            if (!possibleFilters.Succeeded)
            {
                return(new IpcResult(IpcResultStatus.ExecutionError, possibleFilters.Failure.Describe()));
            }

            var initializedFilters    = possibleFilters.Result;
            var possibleManifestFiles = await GetUniqueFilteredDirectoryContentAsync(directoryPaths, directoryIds, initializedFilters);

            if (!possibleManifestFiles.Succeeded)
            {
                return(new IpcResult(IpcResultStatus.ExecutionError, possibleManifestFiles.Failure.Describe()));
            }

            var           manifestFiles      = possibleManifestFiles.Result;
            var           sw                 = Stopwatch.StartNew();
            List <string> filesToMaterialize = null;

            try
            {
                // ensure that the manifest files are actually present on disk
                using (m_counters.StartStopwatch(MaterializationDaemonCounter.RegisterManifestFileMaterializationDuration))
                {
                    await m_actionQueue.ForEachAsync(
                        manifestFiles,
                        async (manifest, i) =>
                    {
                        m_counters.AddToCounter(MaterializationDaemonCounter.RegisterManifestFileMaterializationQueueDuration, sw.ElapsedMilliseconds);
                        await MaterializeFileAsync(manifest.Artifact, manifest.FileName, ignoreMaterializationFailures: false);
                    });
                }

                Possible <List <string> > possibleFiles;
                using (m_counters.StartStopwatch(MaterializationDaemonCounter.ManifestParsingOuterDuration))
                {
                    m_counters.AddToCounter(MaterializationDaemonCounter.ManifestParsingTotalFiles, possibleManifestFiles.Result.Count);
                    possibleFiles = await ParseManifestFilesAsync(manifestFiles);

                    if (!possibleFiles.Succeeded)
                    {
                        return(new IpcResult(IpcResultStatus.ExecutionError, possibleFiles.Failure.Describe()));
                    }

                    m_counters.AddToCounter(MaterializationDaemonCounter.ManifestParsingReferencedTotalFiles, possibleFiles.Result.Count);
                }

                filesToMaterialize = possibleFiles.Result;
                sw = Stopwatch.StartNew();
                using (m_counters.StartStopwatch(MaterializationDaemonCounter.RegisterManifestReferencedFileMaterializationDuration))
                {
                    await m_actionQueue.ForEachAsync(
                        filesToMaterialize,
                        async (file, i) =>
                    {
                        // Since these file paths are not real build artifacts (i.e., just strings constructed by a parser),
                        // they might not be "known" to BuildXL, and because of that, BuildXL won't be able to materialize them.
                        // Manifests are known to contain references to files that are not produced during a build, so we are
                        // ignoring materialization failures for such files. We are doing this so we won't fail IPC pips and
                        // a build could succeed.
                        // If there are real materialization errors (e.g., cache failure), the daemon relies on BuildXL logging
                        // the appropriate error events and failing the build.
                        m_counters.AddToCounter(MaterializationDaemonCounter.RegisterManifestReferencedFileMaterializationQueueDuration, sw.ElapsedMilliseconds);
                        await MaterializeFileAsync(FileArtifact.Invalid, file, ignoreMaterializationFailures: true);
                    });
                }
            }
            catch (Exception e)
            {
                return(new IpcResult(
                           IpcResultStatus.GenericError,
                           e.ToStringDemystified()));
            }

            // Note: we are not claiming here that all the files in filesToMaterialize were materialized cause we are ignoring materialization failures.
            // The real materialization status will be logged during execution of the Finalize command.
            return(IpcResult.Success(
                       $"Processed paths ({filesToMaterialize.Count}):{Environment.NewLine}{string.Join(Environment.NewLine, filesToMaterialize)}"));
        }
Exemple #25
0
 public CommandConfigurator(ConfiguredCommand command)
 {
     Command = command;
 }