internal void Hello( string hash, [Required, Description("Machine to send Hello request to")] string host, [Description("GRPC port on the target machine"), DefaultValue(ServiceConfiguration.GrpcDisabledPort)] int grpcPort, [Description("Name of the memory mapped file used to share GRPC port. 'CASaaS GRPC port' if not specified.")] string grpcPortFileName) { try { Initialize(); if (grpcPort == 0) { grpcPort = Helpers.GetGrpcPortFromFile(_logger, grpcPortFileName); } var _channel = new Channel(host, grpcPort, ChannelCredentials.Insecure); var _client = new ContentServer.ContentServerClient(_channel); var helloResponse = _client.Hello(new HelloRequest(), new CallOptions(deadline: DateTime.UtcNow + TimeSpan.FromSeconds(2))); _logger.Always("Hello response {0}: {1}", helloResponse.Success ? "succeeded" : "failed", helloResponse.ToString()); } catch (Exception e) { _logger.Always(e.ToString()); } }
internal void CopyFile( [Required, Description("Machine to copy from")] string host, [Required, Description("Expected content hash")] string hashString, [Required, Description("Path to destination file")] string destinationPath, [Description("Whether or not GZip is enabled"), DefaultValue(false)] bool useCompressionForCopies, [Description("File name where the GRPC port can be found when using cache service. 'CASaaS GRPC port' if not specified")] string grpcPortFileName, [Description("The GRPC port"), DefaultValue(0)] int grpcPort) { Initialize(); var context = new Context(_logger); var retryPolicy = RetryPolicyFactory.GetLinearPolicy(ex => ex is ClientCanRetryException, (int)_retryCount, TimeSpan.FromSeconds(_retryIntervalSeconds)); if (grpcPort == 0) { grpcPort = Helpers.GetGrpcPortFromFile(_logger, grpcPortFileName); } if (!ContentHash.TryParse(hashString, out var hash)) { throw new CacheException($"Invalid content hash string provided: {hashString}"); } try { var config = new GrpcCopyClientConfiguration(); using var clientCache = new GrpcCopyClientCache(context, new GrpcCopyClientCacheConfiguration() { GrpcCopyClientConfiguration = config }); var finalPath = new AbsolutePath(destinationPath); var copyFileResult = clientCache.UseAsync(new OperationContext(context), host, grpcPort, (nestedContext, rpcClient) => { return(retryPolicy.ExecuteAsync( () => rpcClient.CopyFileAsync(nestedContext, hash, finalPath, new CopyOptions(bandwidthConfiguration: null) { CompressionHint = useCompressionForCopies ? CopyCompression.Gzip : CopyCompression.None, }), _cancellationToken)); }).GetAwaiter().GetResult(); if (!copyFileResult.Succeeded) { throw new CacheException(copyFileResult.ErrorMessage); } else { _logger.Debug($"Copy of {hashString} to {finalPath} was successful"); } } catch (Exception ex) { throw new CacheException(ex.ToString()); } }
internal void CopyFile( [Required, Description("Machine to copy from")] string host, [Required, Description("Expected content hash")] string hashString, [Required, Description("Path to destination file")] string destinationPath, [Description("Whether or not GZip is enabled"), DefaultValue(false)] bool useCompressionForCopies, [Description("File name where the GRPC port can be found when using cache service. 'CASaaS GRPC port' if not specified")] string grpcPortFileName, [Description("The GRPC port"), DefaultValue(0)] int grpcPort, [Description("Interval at which to check the bandwidth. 0 will disable bandwidth checks"), DefaultValue(0)] int bandwidthCheckIntervalSeconds, [Description("Minimum bandwidth required. Null will enable historical bandwidth check."), DefaultValue(null)] double?minimumBandwidthMbPerSec) { Initialize(); var context = new Context(_logger); var retryPolicy = new RetryPolicy( new TransientErrorDetectionStrategy(), new FixedInterval("RetryInterval", (int)_retryCount, TimeSpan.FromSeconds(_retryIntervalSeconds), false)); if (grpcPort == 0) { grpcPort = Helpers.GetGrpcPortFromFile(_logger, grpcPortFileName); } if (!ContentHash.TryParse(hashString, out var hash)) { throw new CacheException($"Invalid content hash string provided: {hashString}"); } try { var copyClientConfig = bandwidthCheckIntervalSeconds > 0 ? new GrpcCopyClient.Configuration(TimeSpan.FromSeconds(bandwidthCheckIntervalSeconds), minimumBandwidthMbPerSec, clientBufferSize: null) : GrpcCopyClient.Configuration.Default; using (var clientCache = new GrpcCopyClientCache(context, copyClientConfig)) using (var rpcClientWrapper = clientCache.CreateAsync(host, grpcPort, useCompressionForCopies).GetAwaiter().GetResult()) { var rpcClient = rpcClientWrapper.Value; var finalPath = new AbsolutePath(destinationPath); // This action is synchronous to make sure the calling application doesn't exit before the method returns. var copyFileResult = retryPolicy.ExecuteAsync(() => rpcClient.CopyFileAsync(context, hash, finalPath, CancellationToken.None)).Result; if (!copyFileResult.Succeeded) { throw new CacheException(copyFileResult.ErrorMessage); } else { _logger.Debug($"Copy of {hashString} to {finalPath} was successful"); } } } catch (Exception ex) { throw new CacheException(ex.ToString()); } }
internal void CopyFileTo( [Required, Description("Machine to copy to")] string host, [Required, Description("Path to source file")] string sourcePath, [Description("File name where the GRPC port can be found when using cache service. 'CASaaS GRPC port' if not specified")] string grpcPortFileName, [Description("The GRPC port"), DefaultValue(0)] int grpcPort) { Initialize(); var context = new Context(_logger); var operationContext = new OperationContext(context, CancellationToken.None); var retryPolicy = RetryPolicyFactory.GetLinearPolicy(ex => ex is ClientCanRetryException, (int)_retryCount, TimeSpan.FromSeconds(_retryIntervalSeconds)); if (grpcPort == 0) { grpcPort = Helpers.GetGrpcPortFromFile(_logger, grpcPortFileName); } var hasher = ContentHashers.Get(HashType.MD5); var bytes = File.ReadAllBytes(sourcePath); var hash = hasher.GetContentHash(bytes); try { var path = new AbsolutePath(sourcePath); using Stream stream = File.OpenRead(path.Path); var config = GrpcCopyClientConfiguration.WithGzipCompression(false); config.BandwidthCheckerConfiguration = BandwidthChecker.Configuration.Disabled; using var clientCache = new GrpcCopyClientCache(context, new GrpcCopyClientCacheConfiguration() { GrpcCopyClientConfiguration = config }); var copyFileResult = clientCache.UseAsync(operationContext, host, grpcPort, (nestedContext, rpcClient) => { return(retryPolicy.ExecuteAsync( () => rpcClient.PushFileAsync(nestedContext, hash, stream, new CopyOptions(bandwidthConfiguration: null)), _cancellationToken)); }).GetAwaiter().GetResult(); if (!copyFileResult.Succeeded) { _tracer.Error(context, $"{copyFileResult}"); throw new CacheException(copyFileResult.ErrorMessage); } else { _tracer.Info(context, $"Copy of {sourcePath} was successful"); } } catch (Exception ex) { throw new CacheException(ex.ToString()); } }
internal void CopyFile( [Required, Description("Machine to copy from")] string host, [Required, Description("Expected content hash")] string hashString, [Required, Description("Path to destination file")] string destinationPath, [Description("Whether or not GZip is enabled"), DefaultValue(false)] bool useCompressionForCopies, [Description("File name where the GRPC port can be found when using cache service. 'CASaaS GRPC port' if not specified")] string grpcPortFileName, [Description("The GRPC port"), DefaultValue(0)] int grpcPort) { Initialize(); var context = new Context(_logger); var retryPolicy = new RetryPolicy( new TransientErrorDetectionStrategy(), new FixedInterval("RetryInterval", (int)_retryCount, TimeSpan.FromSeconds(_retryIntervalSeconds), false)); if (grpcPort == 0) { grpcPort = Helpers.GetGrpcPortFromFile(_logger, grpcPortFileName); } if (!ContentHash.TryParse(hashString, out ContentHash hash)) { throw new CacheException($"Invalid content hash string provided: {hashString}"); } try { using (var rpcClient = GrpcCopyClient.Create(host, grpcPort, useCompressionForCopies)) { var finalPath = new AbsolutePath(destinationPath); // This action is synchronous to make sure the calling application doesn't exit before the method returns. var copyFileResult = retryPolicy.ExecuteAsync(() => rpcClient.CopyFileAsync(context, hash, finalPath, CancellationToken.None)).Result; if (!copyFileResult.Succeeded) { throw new CacheException(copyFileResult.ErrorMessage); } else { _logger.Debug($"Copy of {hashString} to {finalPath} was successful"); } var shutdownResult = rpcClient.ShutdownAsync(context).Result; if (!shutdownResult.Succeeded) { throw new CacheException(shutdownResult.ErrorMessage); } } } catch (Exception ex) { throw new CacheException(ex.ToString()); } }
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 CopyFileTo( [Required, Description("Machine to copy to")] string host, [Required, Description("Path to source file")] string sourcePath, [Description("File name where the GRPC port can be found when using cache service. 'CASaaS GRPC port' if not specified")] string grpcPortFileName, [Description("The GRPC port"), DefaultValue(0)] int grpcPort) { Initialize(); var context = new Context(_logger); var operationContext = new OperationContext(context, CancellationToken.None); var retryPolicy = new RetryPolicy( new TransientErrorDetectionStrategy(), new FixedInterval("RetryInterval", (int)_retryCount, TimeSpan.FromSeconds(_retryIntervalSeconds), false)); if (grpcPort == 0) { grpcPort = Helpers.GetGrpcPortFromFile(_logger, grpcPortFileName); } var hasher = ContentHashers.Get(HashType.MD5); var bytes = File.ReadAllBytes(sourcePath); var hash = hasher.GetContentHash(bytes); try { using var clientCache = new GrpcCopyClientCache(context); using var rpcClientWrapper = clientCache.CreateAsync(host, grpcPort, useCompression: false).GetAwaiter().GetResult(); var rpcClient = rpcClientWrapper.Value; var path = new AbsolutePath(sourcePath); using Stream stream = File.OpenRead(path.Path); // This action is synchronous to make sure the calling application doesn't exit before the method returns. var copyFileResult = retryPolicy.ExecuteAsync(() => rpcClient.PushFileAsync(operationContext, hash, () => Task.FromResult(stream))).Result; if (!copyFileResult.Succeeded) { _logger.Error($"{copyFileResult}"); throw new CacheException(copyFileResult.ErrorMessage); } else { _logger.Info($"Copy of {sourcePath} was successful"); } } catch (Exception ex) { throw new CacheException(ex.ToString()); } }
internal void OpenStream ( [Description("Cache root directory path (using in-process cache)")] string cachePath, [Description("Cache name (using cache service)")] string cacheName, [Required, Description("Content hash value of referenced content to place")] string hash, [Description(HashTypeDescription)] string hashType, [Description("File name where the GRPC port can be found when using cache service. 'CASaaS GRPC port' if not specified.")] string grpcPortFileName, [Description("The GRPC port."), DefaultValue(0)] int grpcPort ) { var ht = GetHashTypeByNameOrDefault(hashType); var contentHash = new ContentHash(ht, HexUtilities.HexToBytes(hash)); ServiceClientRpcConfiguration rpcConfig = null; if (cacheName != null) { if (grpcPort == 0) { grpcPort = Helpers.GetGrpcPortFromFile(_logger, grpcPortFileName); } rpcConfig = new ServiceClientRpcConfiguration(grpcPort); } RunContentStore(cacheName, cachePath, rpcConfig, async(context, session) => { var r = await session.OpenStreamAsync(context, contentHash, CancellationToken.None).ConfigureAwait(false); if (r.Succeeded) { using (r.Stream) { var path = _fileSystem.GetTempPath() / $"{contentHash.ToHex()}.dat"; using (Stream fileStream = await _fileSystem.OpenSafeAsync(path, FileAccess.Write, FileMode.Create, FileShare.None)) { await r.Stream.CopyToAsync(fileStream); context.Always($"Content streamed to file path=[{path}]"); } } } else { context.Error(r.ToString()); } }); }
internal void PutStream ( [Description("Cache root directory path (using in-process cache)")] string cachePath, [Description("Cache name (using cache service)")] string cacheName, [DefaultValue(100), Description("Content size in bytes")] int size, [Description(HashTypeDescription)] string hashType, [Description("File name where the GRPC port can be found when using cache service. 'CASaaS GRPC port' if not specified.")] string grpcPortFileName, [Description("The GRPC port."), DefaultValue(0)] int grpcPort ) { var ht = GetHashTypeByNameOrDefault(hashType); ServiceClientRpcConfiguration rpcConfig = null; if (cacheName != null) { if (grpcPort == 0) { grpcPort = Helpers.GetGrpcPortFromFile(_logger, grpcPortFileName); } rpcConfig = new ServiceClientRpcConfiguration(grpcPort); } RunContentStore(cacheName, cachePath, rpcConfig, async(context, session) => { using (var stream = new MemoryStream(ThreadSafeRandom.GetBytes(size))) { PutResult result = await session.PutStreamAsync( context, ht, stream, CancellationToken.None).ConfigureAwait(false); if (!result.Succeeded) { context.Error(result.ToString()); } else { context.Always($"Content added with hash=[{result.ContentHash}], size=[{result.ContentSize}]"); } } }); }
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 PlaceFile ( [Description("Cache root directory path (using in-process cache)")] string cachePath, [Description("Cache name (using cache service)")] string cacheName, [Required, Description("Content hash value of referenced content to place")] string hash, [Required, Description("Path to destination file")] string path, [Description(HashTypeDescription)] string hashType, [DefaultValue(FileAccessMode.ReadOnly)] FileAccessMode accessMode, [DefaultValue(FileReplacementMode.ReplaceExisting)] FileReplacementMode replacementMode, [DefaultValue(FileRealizationMode.HardLink)] FileRealizationMode realizationMode, [DefaultValue(false), Description("Stream bytes if true")] bool useStream, [Description("File name where the GRPC port can be found when using cache service. 'CASaaS GRPC port' if not specified.")] string grpcPortFileName, [Description("The GRPC port."), DefaultValue(0)] int grpcPort ) { var ht = GetHashTypeByNameOrDefault(hashType); var contentHash = new ContentHash(ht, HexUtilities.HexToBytes(hash)); var filePath = new AbsolutePath(path); ServiceClientRpcConfiguration rpcConfig = null; if (cacheName != null) { if (grpcPort == 0) { grpcPort = Helpers.GetGrpcPortFromFile(_logger, grpcPortFileName); } rpcConfig = new ServiceClientRpcConfiguration(grpcPort); } RunContentStore(cacheName, cachePath, rpcConfig, async(context, session) => { if (useStream) { var r = await session.OpenStreamAsync(context, contentHash, CancellationToken.None).ConfigureAwait(false); if (r.Succeeded) { using (r.Stream) { using (var fileStream = File.OpenWrite(filePath.Path)) { await r.Stream.CopyToAsync(fileStream); context.Always("Success"); } } } else { context.Error(r.ToString()); } } else { var r = await session.PlaceFileAsync( context, contentHash, filePath, accessMode, replacementMode, realizationMode, CancellationToken.None).ConfigureAwait(false); if (!r.Succeeded) { context.Error(r.ToString()); } else { context.Always("Success"); } } }); }
internal void PutFile ( [Description("Cache root directory path (using in-process cache)")] string cachePath, [Description("Cache name (using cache service)")] string cacheName, [Required, Description("Path to destination file")] string path, [Description(HashTypeDescription)] string hashType, [DefaultValue(FileRealizationMode.Any)] FileRealizationMode realizationMode, [DefaultValue(false), Description("Stream bytes if true")] bool useStream, [Description("File name where the GRPC port can be found when using cache service. 'CASaaS GRPC port' if not specified.")] string grpcPortFileName, [Description("The GRPC port."), DefaultValue(0)] int grpcPort ) { var ht = GetHashTypeByNameOrDefault(hashType); ServiceClientRpcConfiguration rpcConfig = null; if (cacheName != null) { if (grpcPort == 0) { grpcPort = Helpers.GetGrpcPortFromFile(_logger, grpcPortFileName); } rpcConfig = new ServiceClientRpcConfiguration(grpcPort); } RunContentStore(cacheName, cachePath, rpcConfig, async(context, session) => { BoolResult result; ContentHash contentHash; long contentSize; if (useStream) { using (var stream = File.OpenRead(path)) { var r = await session.PutStreamAsync(context, ht, stream, CancellationToken.None).ConfigureAwait(false); contentHash = r.ContentHash; contentSize = r.ContentSize; result = r; } } else { var r = await session.PutFileAsync( context, ht, new AbsolutePath(path), realizationMode, CancellationToken.None).ConfigureAwait(false); contentHash = r.ContentHash; contentSize = r.ContentSize; result = r; } if (!result.Succeeded) { context.Error(result.ToString()); } else { context.Always($"Content added with hash=[{contentHash}], size=[{contentSize}]"); } }); }