Example #1
0
        /// <summary>
        /// Filters out <see cref="NamedCacheSettings"/> entries whose capability demands are not met by the host.
        /// Also filters out entries pointing to e physical drive that doesn't exist.
        /// </summary>
        /// <param name="this"></param>
        /// <param name="hostCapabilities">Capabilities provided by the host</param>
        /// <param name="logger"></param>
        /// <param name="driveExistenceOverride">For testing purposes</param>
        /// <returns></returns>
        public static LocalCasSettings FilterUnsupportedNamedCaches(
            this LocalCasSettings @this, IEnumerable <string> hostCapabilities, ILogger logger, Predicate <string> driveExistenceOverride = null)
        {
            Predicate <string> checkDriveExists = driveExistenceOverride ?? Directory.Exists;

            var result = new LocalCasSettings
            {
                CasClientSettings    = @this.CasClientSettings,
                ServiceSettings      = @this.ServiceSettings,
                DrivePreferenceOrder = new List <string>(@this.DrivePreferenceOrder)
            };

            var filteredCaches = new Dictionary <string, NamedCacheSettings>(@this.CacheSettingsByCacheName.Comparer);

            foreach (KeyValuePair <string, NamedCacheSettings> kvp
                     in @this.CacheSettingsByCacheName)
            {
                // check that the stamp has the capabilities required by the named cache.
                if (kvp.Value.RequiredCapabilities != null && kvp.Value.RequiredCapabilities.Count > 0)
                {
                    string missingCaps = string.Join(",", kvp.Value.RequiredCapabilities
                                                     .Where(cap => !hostCapabilities.Contains(cap, StringComparer.OrdinalIgnoreCase)));
                    if (!string.IsNullOrEmpty(missingCaps))
                    {
                        logger.Debug(
                            "Named cache '{0}' was discarded since environment lacks required capabilities: {1}.",
                            kvp.Key, missingCaps);

                        continue;
                    }
                }

                // check that machine the drive required by named cache.
                // TODO: Should remove this, after measuring this doesn't happens.  If the drive layout doesn't match capability
                //       we'd rather fail.
                AbsolutePath rootPath = @this.GetCacheRootPathWithScenario(kvp.Key);
                string       root     = Path.GetPathRoot(rootPath.Path);

                if (!checkDriveExists(root))
                {
                    logger.Error(
                        "Named cache '{0}' was discarded since the drive required by {1} does not exist or is inaccessible on the machine.",
                        kvp.Key, rootPath);

                    continue;
                }

                filteredCaches.Add(kvp.Key, kvp.Value);
            }

            result.CacheSettingsByCacheName = filteredCaches;
            result.DrivePreferenceOrder     = GetSupportedDrivePreferenceOrder(@this.DrivePreferenceOrder, filteredCaches, logger);

            return(result);
        }
        private static ServiceConfiguration CreateServiceConfiguration(
            ILogger logger,
            IAbsFileSystem fileSystem,
            LocalCasSettings localCasSettings,
            DistributedContentSettings distributedSettings,
            AbsolutePath dataRootPath,
            bool isDistributed)
        {
            var namedCacheRoots = new Dictionary <string, AbsolutePath>(StringComparer.OrdinalIgnoreCase);

            foreach (KeyValuePair <string, NamedCacheSettings> settings in localCasSettings.CacheSettingsByCacheName)
            {
                var rootPath = localCasSettings.GetCacheRootPathWithScenario(settings.Key);

                logger.Debug($"Writing content store config file at {rootPath}.");
                WriteContentStoreConfigFile(settings.Value.CacheSizeQuotaString, rootPath, fileSystem);

                if (!isDistributed)
                {
                    namedCacheRoots[settings.Key] = rootPath;
                }
                else
                {
                    // Arbitrary set to match ServiceConfiguration and LocalContentServer pattern
                    namedCacheRoots[localCasSettings.CasClientSettings.DefaultCacheName] = rootPath;
                }
            }

            if (!namedCacheRoots.Keys.Any(name => localCasSettings.CasClientSettings.DefaultCacheName.Equals(name, StringComparison.OrdinalIgnoreCase)))
            {
                throw new ArgumentException(
                          $"Must have the default cache name {localCasSettings.CasClientSettings.DefaultCacheName} as one of the named cache roots.");
            }

            var result = new ServiceConfiguration(
                namedCacheRoots,
                dataRootPath,
                localCasSettings.ServiceSettings.MaxPipeListeners,
                localCasSettings.ServiceSettings.GracefulShutdownSeconds,
                (int)localCasSettings.ServiceSettings.GrpcPort,
                grpcPortFileName: localCasSettings.ServiceSettings.GrpcPortFileName,
                bufferSizeForGrpcCopies: localCasSettings.ServiceSettings.BufferSizeForGrpcCopies,
                proactivePushCountLimit: localCasSettings.ServiceSettings.MaxProactivePushRequestHandlers,
                logIncrementalStatsInterval: distributedSettings?.LogIncrementalStatsInterval,
                logMachineStatsInterval: distributedSettings?.LogMachineStatsInterval,
                logIncrementalStatsCounterNames: distributedSettings?.IncrementalStatisticsCounterNames,
                asyncSessionShutdownTimeout: distributedSettings?.AsyncSessionShutdownTimeout);

            ApplyIfNotNull(distributedSettings?.TraceServiceGrpcOperations, v => result.TraceGrpcOperation = v);
            return(result);
        }
Example #3
0
        /// <summary>
        /// Filters out <see cref="NamedCacheSettings"/> entries whose capability demands are not met by the host.
        /// Also filters out entries pointing to e physical drive that doesn't exist.
        /// </summary>
        public static LocalCasSettings FilterUnsupportedNamedCaches(
            this LocalCasSettings @this, IEnumerable <string> hostCapabilities, ILogger logger)
        {
            Predicate <string> checkDriveExists = Directory.Exists;

            var result = new LocalCasSettings
            {
                UseScenarioIsolation = @this.UseScenarioIsolation,
                CasClientSettings    = @this.CasClientSettings,
                ServiceSettings      = @this.ServiceSettings,
                DrivePreferenceOrder = new List <string>(@this.DrivePreferenceOrder)
            };

            var filteredCaches = new Dictionary <string, NamedCacheSettings>(@this.CacheSettingsByCacheName.Comparer);

            foreach (KeyValuePair <string, NamedCacheSettings> kvp in @this.CacheSettingsByCacheName)
            {
                // check that the stamp has the capabilities required by the named cache.
                if (kvp.Value.RequiredCapabilities != null && kvp.Value.RequiredCapabilities.Count > 0)
                {
                    string missingCaps = string.Join(",", kvp.Value.RequiredCapabilities
                                                     .Where(cap => !hostCapabilities.Contains(cap, StringComparer.OrdinalIgnoreCase)));
                    if (!string.IsNullOrEmpty(missingCaps))
                    {
                        logger.Debug(
                            "Named cache '{0}' was discarded since environment lacks required capabilities: {1}.",
                            kvp.Key, missingCaps);

                        continue;
                    }
                }

                AbsolutePath rootPath = @this.GetCacheRootPathWithScenario(kvp.Key);
                string       root     = rootPath.GetPathRoot();

                if (!checkDriveExists(root))
                {
                    // Currently it's totally fine to have, for instance, both D and K drives configured for the entire stamp,
                    // even though only some machines in the stamp have both.
                    // For instance, GlobalCache machines usually do have K drive and that drive is preferred if available,
                    // but D drive should be used for CommandAgent machines.

                    // The next trace used to be an error, but in the current state this situation is happening on all CmdAgent machines almost everywhere.
                    logger.Debug(
                        "Named cache '{0}' was discarded since the drive required by {1} does not exist or is inaccessible on the machine.",
                        kvp.Key, rootPath);

                    continue;
                }

                filteredCaches.Add(kvp.Key, kvp.Value);
            }

            result.CacheSettingsByCacheName = filteredCaches;
            result.DrivePreferenceOrder     = GetSupportedDrivePreferenceOrder(@this.DrivePreferenceOrder, filteredCaches, logger);

            if (result.CacheSettingsByCacheName.Count == 0)
            {
                // It seems that all the cache configs were filtered out. This is bad and the system can't work like that!
                string message = $"All ({@this.CacheSettingsByCacheName.Count}) cache configs were discarded due to lack of capabilities. The cache service can't start without valid cache settings.";
                throw new CacheException(message);
            }

            return(result);
        }