internal void DistributedService ( [Description("Cache name")] string cacheName, [Description("Cache root path")] string cachePath, [DefaultValue(ServiceConfiguration.GrpcDisabledPort), Description(GrpcPortDescription)] int grpcPort, [Description("Name of the memory mapped file used to share GRPC port. 'CASaaS GRPC port' if not specified.")] string grpcPortFileName, [DefaultValue(null), Description("Writable directory for service operations (use CWD if null)")] string dataRootPath, [DefaultValue(null), Description("Identifier for the stamp this service will run as")] string stampId, [DefaultValue(null), Description("Identifier for the ring this service will run as")] string ringId, [DefaultValue(Constants.OneMB), Description("Max size quota in MB")] int maxSizeQuotaMB, [DefaultValue(false), Description("Whether or not GRPC is used for file copies")] bool useDistributedGrpc, [DefaultValue(false), Description("Whether or not GZip is used for GRPC file copies")] bool useCompressionForCopies, [DefaultValue(null), Description("Buffer size for streaming GRPC copies")] int?bufferSizeForGrpcCopies ) { Initialize(); try { var cancellationTokenSource = new CancellationTokenSource(); Console.CancelKeyPress += (sender, args) => { cancellationTokenSource.Cancel(); }; var host = new HostInfo(stampId, ringId, new List <string>()); if (grpcPort == 0) { grpcPort = Helpers.GetGrpcPortFromFile(_logger, grpcPortFileName); } var arguments = CreateDistributedCacheServiceArguments( copier: useDistributedGrpc ? new GrpcFileCopier(new Interfaces.Tracing.Context(_logger), grpcPort, useCompressionForCopies) : (IAbsolutePathFileCopier) new DistributedCopier(), pathTransformer: useDistributedGrpc ? new GrpcDistributedPathTransformer() : (IAbsolutePathTransformer) new DistributedPathTransformer(), host: host, cacheName: cacheName, cacheRootPath: cachePath, grpcPort: (uint)grpcPort, maxSizeQuotaMB: maxSizeQuotaMB, dataRootPath: dataRootPath, ct: cancellationTokenSource.Token, bufferSizeForGrpcCopies: bufferSizeForGrpcCopies); DistributedCacheServiceFacade.RunAsync(arguments).GetAwaiter().GetResult(); } catch (Exception e) { Console.WriteLine(e); throw; } }
internal void DistributedService ( [Description("Cache name")] string cacheName, [Description("Cache root path")] string cachePath, [DefaultValue(ServiceConfiguration.GrpcDisabledPort), Description(GrpcPortDescription)] uint grpcPort, [DefaultValue(null), Description("Writable directory for service operations (use CWD if null)")] string dataRootPath, [DefaultValue(null), Description("Identifier for the stamp this service will run as")] string stampId, [DefaultValue(null), Description("Identifier for the ring this service will run as")] string ringId, [DefaultValue(Constants.OneMB), Description("Max size quota in MB")] int maxSizeQuotaMB ) { Initialize(); try { var cancellationTokenSource = new CancellationTokenSource(); Console.CancelKeyPress += (sender, args) => { cancellationTokenSource.Cancel(); }; var copier = new DistributedCopier(); var pathTransformer = new DistributedPathTransformer(); var host = new HostInfo(stampId, ringId, new List <string>()); var arguments = CreateDistributedCacheServiceArguments( copier: copier, pathTransformer: pathTransformer, host: host, cacheName: cacheName, cacheRootPath: cachePath, grpcPort: grpcPort, maxSizeQuotaMB: maxSizeQuotaMB, dataRootPath: dataRootPath, ct: cancellationTokenSource.Token); DistributedCacheServiceFacade.RunAsync(arguments).GetAwaiter().GetResult(); } catch (Exception e) { Console.WriteLine(e); throw; } }
public TestCacheServerWrapper(TestHost testHost, DistributedCacheServiceArguments arguments) { string[] commandLineArguments = CreateCommandLine(arguments); var hostParameters = HostParameters.FromEnvironment(); var hostInfo = new HostInfo(hostParameters.Stamp, hostParameters.Ring, new List <string>()); var serviceHost = new CacheServiceStartup.ServiceHost( new string[0], arguments.Configuration, hostParameters, new Context(TestGlobal.Logger)); Host = new TestServiceHost(testHost, serviceHost); var _ = arguments.Cancellation.Register(() => Host.StartupCompletedSignal.TrySetCanceled()); RunInBackground("RunCacheService", async context => { using (var cts = CancellationTokenSource.CreateLinkedTokenSource(context.Token, arguments.Cancellation)) { arguments = arguments with { Host = Host, Cancellation = cts.Token }; await DistributedCacheServiceFacade.RunAsync(arguments); Assert.True(cts.IsCancellationRequested, "Cache service task shutdown prematurely"); } return(BoolResult.Success); }, fireAndForget: false); }
internal void DistributedService ( [Description("Path to DistributedContentSettings file")] string settingsPath, [Description("Cache name")] string cacheName, [Description("Cache root path")] string cachePath, [DefaultValue((int)ServiceConfiguration.GrpcDisabledPort), Description(GrpcPortDescription)] int grpcPort, [Description("Name of the memory mapped file used to share GRPC port. 'CASaaS GRPC port' if not specified.")] string grpcPortFileName, [DefaultValue(null), Description("Writable directory for service operations (use CWD if null)")] string dataRootPath, [DefaultValue(null), Description("Identifier for the stamp this service will run as")] string stampId, [DefaultValue(null), Description("Identifier for the ring this service will run as")] string ringId, [DefaultValue(Constants.OneMB), Description("Max size quota in MB")] int maxSizeQuotaMB, [DefaultValue(false)] bool debug, [DefaultValue(false), Description("Whether or not GRPC is used for file copies")] bool useDistributedGrpc, [DefaultValue(false), Description("Whether or not GZip is used for GRPC file copies")] bool useCompressionForCopies, [DefaultValue(null), Description("Buffer size for streaming GRPC copies")] int? bufferSizeForGrpcCopies, [DefaultValue(null), Description("Files greater than this size are compressed if compression is used")] int? gzipBarrierSizeForGrpcCopies ) { Initialize(); if (debug) { System.Diagnostics.Debugger.Launch(); } try { Validate(); var dcs = JsonConvert.DeserializeObject<DistributedContentSettings>(File.ReadAllText(settingsPath)); var host = new HostInfo(stampId, ringId, new List<string>()); if (grpcPort == 0) { grpcPort = Helpers.GetGrpcPortFromFile(_logger, grpcPortFileName); } var arguments = CreateDistributedCacheServiceArguments( copier: useDistributedGrpc ? new GrpcFileCopier( context: new Interfaces.Tracing.Context(_logger), grpcPort: grpcPort, maxGrpcClientCount: dcs.MaxGrpcClientCount, maxGrpcClientAgeMinutes: dcs.MaxGrpcClientAgeMinutes, grpcClientCleanupDelayMinutes: dcs.GrpcClientCleanupDelayMinutes, useCompression: useCompressionForCopies, bufferSize: bufferSizeForGrpcCopies) : (IAbsolutePathFileCopier)new DistributedCopier(), pathTransformer: useDistributedGrpc ? new GrpcDistributedPathTransformer() : (IAbsolutePathTransformer)new DistributedPathTransformer(), dcs: dcs, host: host, cacheName: cacheName, cacheRootPath: cachePath, grpcPort: (uint)grpcPort, maxSizeQuotaMB: maxSizeQuotaMB, dataRootPath: dataRootPath, ct: _cancellationToken, bufferSizeForGrpcCopies: bufferSizeForGrpcCopies, gzipBarrierSizeForGrpcCopies: gzipBarrierSizeForGrpcCopies); DistributedCacheServiceFacade.RunAsync(arguments).GetAwaiter().GetResult(); } catch (Exception e) { Console.WriteLine(e); throw; } }
internal void DistributedService ( [Description("Path to DistributedContentSettings file")] string settingsPath, [Description("Cache root path")] string cachePath, [DefaultValue((int)ServiceConfiguration.GrpcDisabledPort), Description(GrpcPortDescription)] int grpcPort, [Description("Name of the memory mapped file used to share GRPC port. 'CASaaS GRPC port' if not specified.")] string grpcPortFileName, [DefaultValue(null), Description("Writable directory for service operations (use CWD if null)")] string dataRootPath, [DefaultValue(null), Description("Identifier for the stamp this service will run as")] string stampId, [DefaultValue(null), Description("Identifier for the ring this service will run as")] string ringId, [DefaultValue(Constants.OneMB), Description("Max size quota in MB")] int maxSizeQuotaMB, [DefaultValue(false)] bool debug, [DefaultValue(false), Description("Whether or not GRPC is used for file copies")] bool useDistributedGrpc, [DefaultValue(false), Description("Whether or not GZip is used for GRPC file copies")] bool useCompressionForCopies, [DefaultValue(null), Description("Buffer size for streaming GRPC copies")] int?bufferSizeForGrpcCopies, [DefaultValue(null), Description("Files greater than this size are compressed if compression is used")] int?gzipBarrierSizeForGrpcCopies, [DefaultValue(null), Description("nLog configuration path. If empty, it is disabled")] string nLogConfigurationPath, [DefaultValue(null), Description("Whether to use Azure Blob logging or not")] string nLogToBlobStorageSecretName, [DefaultValue(null), Description("If using Azure Blob logging, where to temporarily store logs")] string nLogToBlobStorageWorkspacePath ) { // We don't actually support the cache name being anything different than this, so there is no point in // allowing it. var cacheName = "Default"; Initialize(); if (debug) { System.Diagnostics.Debugger.Launch(); } try { Validate(); var dcs = JsonConvert.DeserializeObject <DistributedContentSettings>(File.ReadAllText(settingsPath)); var host = new HostInfo(stampId, ringId, new List <string>()); if (grpcPort == 0) { grpcPort = Helpers.GetGrpcPortFromFile(_logger, grpcPortFileName); } // We don't have to dispose the copier here. RunAsync will take care of that. var grpcCopier = new GrpcFileCopier( context: new Interfaces.Tracing.Context(_logger), grpcPort: grpcPort, maxGrpcClientCount: dcs.MaxGrpcClientCount, maxGrpcClientAgeMinutes: dcs.MaxGrpcClientAgeMinutes, useCompression: useCompressionForCopies); var copier = useDistributedGrpc ? grpcCopier : (IAbsolutePathFileCopier) new DistributedCopier(); LoggingSettings loggingSettings = null; if (!string.IsNullOrEmpty(nLogConfigurationPath)) { loggingSettings = new LoggingSettings() { NLogConfigurationPath = nLogConfigurationPath, Configuration = new AzureBlobStorageLogPublicConfiguration() { SecretName = nLogToBlobStorageSecretName, WorkspaceFolderPath = nLogToBlobStorageWorkspacePath, } }; } var arguments = CreateDistributedCacheServiceArguments( copier: copier, pathTransformer: useDistributedGrpc ? new GrpcDistributedPathTransformer(_logger) : (IAbsolutePathTransformer) new DistributedPathTransformer(), copyRequester: grpcCopier, dcs: dcs, host: host, cacheName: cacheName, cacheRootPath: cachePath, grpcPort: (uint)grpcPort, maxSizeQuotaMB: maxSizeQuotaMB, dataRootPath: dataRootPath, ct: _cancellationToken, bufferSizeForGrpcCopies: bufferSizeForGrpcCopies, gzipBarrierSizeForGrpcCopies: gzipBarrierSizeForGrpcCopies, loggingSettings: loggingSettings, telemetryFieldsProvider: new TelemetryFieldsProvider(ringId, stampId)); DistributedCacheServiceFacade.RunAsync(arguments).GetAwaiter().GetResult(); } catch (Exception e) { Console.WriteLine(e); throw; } }
internal void Service ( [Description("Cache names")] string[] names, [Description("Cache root paths")] string[] paths, [DefaultValue(DefaultMaxConnections), Description(MaxConnectionsDescription)] uint maxConnections, [DefaultValue(DefaultGracefulShutdownSeconds), Description(GracefulShutdownSecondsDescription)] uint gracefulShutdownSeconds, [DefaultValue(ServiceConfiguration.GrpcDisabledPort), Description(GrpcPortDescription)] int grpcPort, [Description("Name of the memory mapped file used to share GRPC port. 'CASaaS GRPC port' if not specified.")] string grpcPortFileName, [DefaultValue(null), Description("Writable directory for service operations (use CWD if null)")] string dataRootPath, [DefaultValue(null), Description("Duration of inactivity after which a session will be timed out.")] double?unusedSessionTimeoutSeconds, [DefaultValue(null), Description("Duration of inactivity after which a session with a heartbeat will be timed out.")] double?unusedSessionHeartbeatTimeoutSeconds, [DefaultValue(false), Description("Stop running service")] bool stop, [DefaultValue(Constants.OneMB), Description("Max size quota in MB")] int maxSizeQuotaMB ) { Initialize(); if (stop) { IpcUtilities.SetShutdown(_scenario); return; } if (names == null || paths == null) { throw new CacheException("At least one cache name/path is required."); } if (names.Length != paths.Length) { throw new CacheException("Mismatching lengths of names/paths arguments."); } var caches = new Dictionary <string, string>(); for (var i = 0; i < names.Length; i++) { caches.Add(names[i], paths[i]); } var serverDataRootPath = !string.IsNullOrWhiteSpace(dataRootPath) ? new AbsolutePath(dataRootPath) : new AbsolutePath(Environment.CurrentDirectory); var cancellationTokenSource = new CancellationTokenSource(); #if !FEATURE_CORECLR var configuration = new ServiceConfiguration(caches, serverDataRootPath, maxConnections, gracefulShutdownSeconds, grpcPort, grpcPortFileName); if (!configuration.IsValid) { throw new CacheException($"Invalid service configuration, error=[{configuration.Error}]"); } var localContentServerConfiguration = new LocalServerConfiguration(configuration); if (unusedSessionTimeoutSeconds != null) { localContentServerConfiguration.UnusedSessionTimeout = TimeSpan.FromSeconds(unusedSessionTimeoutSeconds.Value); } if (unusedSessionHeartbeatTimeoutSeconds != null) { localContentServerConfiguration.UnusedSessionHeartbeatTimeout = TimeSpan.FromSeconds(unusedSessionHeartbeatTimeoutSeconds.Value); } if (_scenario != null) { _logger.Debug($"scenario=[{_scenario}]"); } var exitSignal = new ManualResetEvent(false); Console.CancelKeyPress += (sender, args) => { exitSignal.Set(); args.Cancel = true; }; using (var exitEvent = IpcUtilities.GetShutdownWaitHandle(_scenario)) { var server = new LocalContentServer( _fileSystem, _logger, _scenario, path => new FileSystemContentStore( _fileSystem, SystemClock.Instance, path, new ConfigurationModel(inProcessConfiguration: ContentStoreConfiguration.CreateWithMaxSizeQuotaMB((uint)maxSizeQuotaMB))), localContentServerConfiguration); using (server) { var context = new Context(_logger); try { var result = server.StartupAsync(context).Result; if (!result.Succeeded) { throw new CacheException(result.ErrorMessage); } int completedIndex = WaitHandle.WaitAny(new WaitHandle[] { exitSignal, exitEvent }); var source = completedIndex == 0 ? "control-C" : "exit event"; _tracer.Always(context, $"Shutdown by {source}."); } finally { var result = server.ShutdownAsync(context).Result; if (!result.Succeeded) { _tracer.Warning(context, $"Failed to shutdown store: {result.ErrorMessage}"); } } } } #else Console.CancelKeyPress += (sender, args) => { cancellationTokenSource.Cancel(); args.Cancel = true; }; var localCasSettings = LocalCasSettings.Default(maxSizeQuotaMB, serverDataRootPath.Path, names[0], (uint)grpcPort); var distributedContentSettings = DistributedContentSettings.CreateDisabled(); var distributedCacheServiceConfiguration = new DistributedCacheServiceConfiguration(localCasSettings, distributedContentSettings); // Ensure the computed keyspace is computed based on the hostInfo's StampId distributedCacheServiceConfiguration.UseStampBasedIsolation = false; var distributedCacheServiceArguments = new DistributedCacheServiceArguments( logger: _logger, copier: null, pathTransformer: null, host: new EnvironmentVariableHost(), hostInfo: new HostInfo(null, null, new List <string>()), cancellation: cancellationTokenSource.Token, dataRootPath: serverDataRootPath.Path, configuration: distributedCacheServiceConfiguration, keyspace: null); DistributedCacheServiceFacade.RunAsync(distributedCacheServiceArguments).GetAwaiter().GetResult(); // Because the facade completes immediately and named wait handles don't exist in CORECLR, // completion here is gated on Control+C. In the future, this can be redone with another option, // such as a MemoryMappedFile or GRPC heartbeat. This is just intended to be functional. cancellationTokenSource.Token.WaitHandle.WaitOne(); #endif }
internal void Service ( [Description("Cache names")] string[] names, [Description("Cache root paths")] string[] paths, [DefaultValue(DefaultMaxConnections), Description(MaxConnectionsDescription)] uint maxConnections, [DefaultValue(DefaultGracefulShutdownSeconds), Description(GracefulShutdownSecondsDescription)] uint gracefulShutdownSeconds, [DefaultValue(ServiceConfiguration.GrpcDisabledPort), Description(GrpcPortDescription)] uint grpcPort, [Description("Name of the memory mapped file used to share GRPC port. 'CASaaS GRPC port' if not specified.")] string grpcPortFileName, [DefaultValue(null), Description("Writable directory for service operations (use CWD if null)")] string dataRootPath, [DefaultValue(null), Description("Duration of inactivity after which a session will be timed out.")] double?unusedSessionTimeoutSeconds, [DefaultValue(null), Description("Duration of inactivity after which a session with a heartbeat will be timed out.")] double?unusedSessionHeartbeatTimeoutSeconds, [DefaultValue(false), Description("Stop running service")] bool stop, [DefaultValue(Constants.OneGBInMB), Description("Max size quota in MB")] int maxSizeQuotaMB, [DefaultValue(ServiceConfiguration.GrpcDisabledPort), Description(RemoteGrpcPortDescription)] uint backingGrpcPort, [DefaultValue(null), Description("Name of scenario for backing CAS service")] string backingScenario, [DefaultValue("None"), Description("Ring Id. Used only for telemetry.")] string ringId, [DefaultValue("None"), Description("Stamp Id. Used only for telemetry.")] string stampId, [DefaultValue(null), Description("nLog configuration path. If empty, it is disabled")] string nLogConfigurationPath, [DefaultValue(null), Description("Whether to use Azure Blob logging or not")] string nLogToBlobStorageSecretName, [DefaultValue(null), Description("If using Azure Blob logging, where to temporarily store logs")] string nLogToBlobStorageWorkspacePath, [DefaultValue(false), Description("Enable metadata")] bool enableMetadata ) { Initialize(); if (stop) { IpcUtilities.SetShutdown(_scenario); return; } if (names == null || paths == null) { throw new CacheException("At least one cache name/path is required."); } if (names.Length != paths.Length) { throw new CacheException("Mismatching lengths of names/paths arguments."); } var serverDataRootPath = !string.IsNullOrWhiteSpace(dataRootPath) ? new AbsolutePath(dataRootPath) : new AbsolutePath(Environment.CurrentDirectory); var cancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(_cancellationToken); if (_scenario != null) { _logger.Debug($"scenario=[{_scenario}]"); } using var exitEvent = GetExitEvent(); var localCasSettings = LocalCasSettings.Default(maxSizeQuotaMB, paths[0], names[0], grpcPort, grpcPortFileName); for (int i = 1; i < names.Length; i++) { localCasSettings.AddNamedCache(names[i], paths[i]); } localCasSettings.ServiceSettings.ScenarioName = _scenario; if (unusedSessionTimeoutSeconds != null) { localCasSettings.ServiceSettings.UnusedSessionTimeoutMinutes = TimeSpan.FromSeconds(unusedSessionTimeoutSeconds.Value).TotalMinutes; } if (unusedSessionHeartbeatTimeoutSeconds != null) { localCasSettings.ServiceSettings.UnusedSessionHeartbeatTimeoutMinutes = TimeSpan.FromSeconds(unusedSessionHeartbeatTimeoutSeconds.Value).TotalMinutes; } var distributedContentSettings = DistributedContentSettings.CreateDisabled(); if (backingGrpcPort != ServiceConfiguration.GrpcDisabledPort) { distributedContentSettings.BackingGrpcPort = (int)backingGrpcPort; distributedContentSettings.BackingScenario = backingScenario; } if (enableMetadata) { distributedContentSettings.EnableMetadataStore = true; } LoggingSettings loggingSettings = null; if (!string.IsNullOrEmpty(nLogConfigurationPath)) { loggingSettings = new LoggingSettings() { NLogConfigurationPath = nLogConfigurationPath, Configuration = new AzureBlobStorageLogPublicConfiguration() { SecretName = nLogToBlobStorageSecretName, WorkspaceFolderPath = nLogToBlobStorageWorkspacePath, } }; } var distributedCacheServiceConfiguration = new DistributedCacheServiceConfiguration(localCasSettings, distributedContentSettings, loggingSettings); // Ensure the computed keyspace is computed based on the hostInfo's StampId distributedCacheServiceConfiguration.UseStampBasedIsolation = false; var distributedCacheServiceArguments = new DistributedCacheServiceArguments( logger: _logger, copier: new DistributedCopier(), copyRequester: null, host: new EnvironmentVariableHost(), hostInfo: new HostInfo(null, null, new List <string>()), cancellation: cancellationTokenSource.Token, dataRootPath: serverDataRootPath.Path, configuration: distributedCacheServiceConfiguration, keyspace: null) { TelemetryFieldsProvider = new TelemetryFieldsProvider(ringId, stampId, serviceName: "Service"), }; var runTask = Task.Run(() => DistributedCacheServiceFacade.RunAsync(distributedCacheServiceArguments)); // Because the facade completes immediately and named wait handles don't exist in CORECLR, // completion here is gated on Control+C. In the future, this can be redone with another option, // such as a MemoryMappedFile or GRPC heartbeat. This is just intended to be functional. int completedIndex = WaitHandle.WaitAny(new WaitHandle[] { cancellationTokenSource.Token.WaitHandle, exitEvent }); var source = completedIndex == 0 ? "control-C" : "exit event"; _logger.Always($"Shutdown by {source}."); if (completedIndex == 1) { cancellationTokenSource.Cancel(); } runTask.GetAwaiter().GetResult(); }