/// <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); }
/// <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); }