コード例 #1
0
        public CachingCentralStorage(
            DistributedCentralStoreConfiguration configuration,
            CentralStorage fallbackStorage,
            IAbsFileSystem fileSystem)
        {
            Configuration    = configuration;
            _fallbackStorage = fallbackStorage;

            var maxRetentionMb  = (int)Math.Ceiling(configuration.MaxRetentionGb * 1024);
            var softRetentionMb = (int)(maxRetentionMb * 0.8);

            var cacheFolder = configuration.CacheRoot / CacheSubFolderName;

            // Create a private CAS for storing checkpoint data
            // Avoid introducing churn into primary CAS
            PrivateCas = new FileSystemContentStoreInternal(
                fileSystem,
                SystemClock.Instance,
                cacheFolder,
                new ConfigurationModel(
                    new ContentStoreConfiguration(new MaxSizeQuota(hardExpression: maxRetentionMb + "MB", softExpression: softRetentionMb + "MB")),
                    ConfigurationSelection.RequireAndUseInProcessConfiguration),
                settings: new ContentStoreSettings()
            {
                TraceFileSystemContentStoreDiagnosticMessages = Configuration.TraceFileSystemContentStoreDiagnosticMessages,
                SelfCheckSettings = Configuration.SelfCheckSettings,
            });
        }
コード例 #2
0
        protected override bool TraceErrorsOnly => true; // This type adds nothing in terms of tracing. So configure it to trace errors only.

        /// <summary>
        ///     Initializes a new instance of the <see cref="ReadOnlyFileSystemContentSession" /> class.
        /// </summary>
        public ReadOnlyFileSystemContentSession(string name, FileSystemContentStoreInternal store, ImplicitPin implicitPin)
            : base(name)
        {
            Store        = store;
            _pinContext  = Store.CreatePinContext();
            _implicitPin = implicitPin;
        }
コード例 #3
0
        /// <nodoc />
        public DeploymentProxyService(
            ProxyServiceConfiguration configuration,
            HostParameters hostParameters,
            IAbsFileSystem fileSystem = null,
            IClock clock = null,
            IDeploymentServiceClient client = null)
        {
            clock ??= SystemClock.Instance;
            Configuration        = configuration;
            Root                 = new AbsolutePath(configuration.RootPath);
            Clock                = clock;
            ContentCacheRequests = new VolatileMap <(string, string), AsyncLazy <BoolResult> >(Clock);
            ProxyAddress         = new VolatileMap <UnitValue, AsyncLazy <string> >(Clock);
            Client               = client ?? DeploymentLauncherHost.Instance.CreateServiceClient();
            HostParameters       = hostParameters;

            DownloadQueue = new ActionQueue(configuration.DownloadConcurrency ?? Environment.ProcessorCount);

            Store = new FileSystemContentStoreInternal(
                fileSystem ?? new PassThroughFileSystem(),
                Clock,
                DeploymentUtilities.GetCasRootPath(Root),
                new ConfigurationModel(new ContentStoreConfiguration(new MaxSizeQuota($"{Configuration.RetentionSizeGb}GB"))),
                settings: new ContentStoreSettings()
            {
                TraceFileSystemContentStoreDiagnosticMessages = true,
            });
        }
コード例 #4
0
        private async Task TestSuccessfulPutStreamAndGet(FileSystemContentStoreInternal store, byte[] content)
        {
            ContentHash actualContentHash = content.CalculateHash(ContentHashType);

            using (var contentStream = new MemoryStream(content))
            {
                var context = new Context(Logger);
                var result  = await store.PutStreamAsync(context, contentStream, actualContentHash);

                ContentHash hashFromPut = result.ContentHash;
                long        sizeFromPut = result.ContentSize;

                Assert.True(actualContentHash.Equals(hashFromPut));
                Assert.Equal(content.Length, sizeFromPut);

                // Get the content from the store
                using (var pinContext = store.CreatePinContext())
                {
                    var r2 = await store.PinAsync(context, hashFromPut, pinContext);

                    r2.ShouldBeSuccess();
                    var r3 = await store.OpenStreamAsync(context, hashFromPut);

                    r3.ShouldBeSuccess();
                    byte[] bytes = await r3.Stream.GetBytes();

                    Assert.True(content.SequenceEqual(bytes));
                }
            }
        }
コード例 #5
0
        protected async Task <PutResult> PutStreamAsync(FileSystemContentStoreInternal store, MemoryStream content)
        {
            var r = await store.PutStreamAsync(Context, content, ContentHashType);

            Clock.Increment();
            return(r);
        }
コード例 #6
0
        /// <summary>
        ///     Initializes a new instance of the <see cref="FileSystemContentStore" /> class.
        /// </summary>
        public FileSystemContentStore(
            IAbsFileSystem fileSystem,
            IClock clock,
            AbsolutePath rootPath,
            ConfigurationModel?configurationModel,
            IDistributedLocationStore?distributedStore,
            ContentStoreSettings?settings)
        {
            Contract.Requires(fileSystem != null);
            Contract.Requires(clock != null);
            Contract.Requires(rootPath != null);

            int singleInstanceTimeoutSeconds = ContentStoreConfiguration.DefaultSingleInstanceTimeoutSeconds;

            if (configurationModel?.InProcessConfiguration != null)
            {
                // TODO: Stop using the configurationModel's SingleInstanceTimeout (bug 1365340)
                // because FileSystemContentStore doesn't respect the config file's value
                singleInstanceTimeoutSeconds = configurationModel.InProcessConfiguration.SingleInstanceTimeoutSeconds;
            }

            // FileSystemContentStore implicitly uses a null component name for compatibility with older versions' directory locks.
            _directoryLock = new DirectoryLock(rootPath, fileSystem, TimeSpan.FromSeconds(singleInstanceTimeoutSeconds));

            Store = new FileSystemContentStoreInternal(
                fileSystem,
                clock,
                rootPath,
                configurationModel,
                settings,
                distributedStore);
        }
コード例 #7
0
        public DistributedCentralStorage(
            DistributedCentralStoreConfiguration configuration,
            ILocationStore locationStore,
            IDistributedContentCopier copier,
            CentralStorage fallbackStorage)
        {
            _configuration = configuration;
            _copier = copier;
            _fallbackStorage = fallbackStorage;
            _locationStore = locationStore;

            var maxRetentionMb = configuration.MaxRetentionGb * 1024;
            var softRetentionMb = (int)(maxRetentionMb * 0.8);

            var cacheFolder = configuration.CacheRoot / CacheSubFolderName;

            _copierWorkingDirectory = new DisposableDirectory(copier.FileSystem, cacheFolder / "Temp");

            // Create a private CAS for storing checkpoint data
            // Avoid introducing churn into primary CAS
            _privateCas = new FileSystemContentStoreInternal(
                copier.FileSystem,
                SystemClock.Instance,
                cacheFolder,
                new ConfigurationModel(
                    new ContentStoreConfiguration(new MaxSizeQuota(hardExpression: maxRetentionMb + "MB", softExpression: softRetentionMb + "MB")),
                    ConfigurationSelection.RequireAndUseInProcessConfiguration),
                settings: new ContentStoreSettings()
                {
                    TraceFileSystemContentStoreDiagnosticMessages = _configuration.TraceFileSystemContentStoreDiagnosticMessages,
                    SelfCheckSettings = _configuration.SelfCheckSettings,
                });
        }
コード例 #8
0
        private async Task TestSuccessfulPutAbsolutePathAndGet(FileSystemContentStoreInternal store, byte[] content, FileRealizationMode ingressModes)
        {
            using (var tempDirectory = new DisposableDirectory(FileSystem))
            {
                AbsolutePath pathToFile = CreateRandomFile(tempDirectory.Path, content);

                using (var contentStream = new MemoryStream(content))
                {
                    ContentHash actualContentHash = await contentStream.WithLength().CalculateHashAsync(ContentHashType);

                    var context = new Context(Logger);
                    var result  = await store.PutFileAsync(context, pathToFile, ingressModes, ContentHashType);

                    ContentHash hashFromPut = result.ContentHash;
                    long        sizeFromPut = result.ContentSize;

                    Assert.True(actualContentHash.Equals(hashFromPut));
                    Assert.Equal(content.Length, sizeFromPut);

                    // Get the content from the store
                    using (var pinContext = store.CreatePinContext())
                    {
                        var r2 = await store.PinAsync(context, hashFromPut, pinContext);

                        r2.ShouldBeSuccess();
                        var r3 = await store.OpenStreamAsync(context, hashFromPut);

                        var bytes = await r3.Stream.GetBytes();

                        Assert.True(content.SequenceEqual(bytes));
                    }
                }
            }
        }
コード例 #9
0
        /// <inheritdoc />
        public virtual Task <FileExistenceResult> CheckFileExistsAsync(OperationContext context, ContentLocation sourceLocation)
        {
            var path = new AbsolutePath(sourceLocation.Machine.Path) / FileSystemContentStoreInternal.GetPrimaryRelativePath(sourceLocation.Hash, includeSharedFolder: false);

            var resultCode = FileUtilities.Exists(path.Path) ? FileExistenceResult.ResultCode.FileExists : FileExistenceResult.ResultCode.FileNotFound;

            return(Task.FromResult(new FileExistenceResult(resultCode)));
        }
コード例 #10
0
        protected async Task <bool> ContainsAsync(FileSystemContentStoreInternal store, ContentHash contentHash)
        {
            var r = await store.ContainsAsync(Context, contentHash);

            Clock.Increment();

            return(r);
        }
コード例 #11
0
        private async Task <bool> ValidateContentDirectoryAsync(Context context)
        {
            _tracer.Always(context, "Validating local CAS content directory");
            int contentDirectoryMismatchCount = 0;

            var fileSystemContentDirectory = _enumerateBlobPathsFromDisk()
                                             .Select(blobPath => FileSystemContentStoreInternal.TryGetHashFromPath(blobPath.FullPath, out var hash) ? (ContentHash?)hash : null)
                                             .Where(hash => hash != null)
                                             .GroupBy(hash => hash !.Value)
                                             .ToDictionary(replicaGroup => replicaGroup.Key, replicaGroup => replicaGroup.Count());

            foreach (var x in fileSystemContentDirectory.Keys)
            {
                var fileSystemHash             = x;
                int fileSystemHashReplicaCount = fileSystemContentDirectory[fileSystemHash];

                await _contentDirectory.UpdateAsync(fileSystemHash, false, _clock, fileInfo =>
                {
                    if (fileInfo == null)
                    {
                        contentDirectoryMismatchCount++;
                        _tracer.Always(context, $"Cache content directory for hash {fileSystemHash.ToShortString()} from disk does not exist.");
                    }
                    else if (fileInfo.ReplicaCount != fileSystemHashReplicaCount)
                    {
                        contentDirectoryMismatchCount++;
                        _tracer.Always(
                            context,
                            $"Directory for hash {fileSystemHash.ToShortString()} describes {fileInfo.ReplicaCount} replicas, but {fileSystemHashReplicaCount} replicas exist on disk.");
                    }

                    return(null);
                });
            }

            foreach (var x in (await _contentDirectory.EnumerateContentHashesAsync())
                     .Where(hash => !fileSystemContentDirectory.ContainsKey(hash)))
            {
                var missingHash = x;
                contentDirectoryMismatchCount++;
                await _contentDirectory.UpdateAsync(missingHash, false, _clock, fileInfo =>
                {
                    if (fileInfo != null)
                    {
                        _tracer.Always(
                            context,
                            $"Directory for hash {missingHash.ToShortString()} describes {fileInfo.ReplicaCount} replicas, but no replicas exist on disk.");
                    }

                    return(null);
                });
            }

            _tracer.Always(
                context, $"{contentDirectoryMismatchCount} mismatches between cache content directory and content files on disk.");

            return(contentDirectoryMismatchCount == 0);
        }
コード例 #12
0
        public void PathWithTildaShouldNotCauseArgumentException()
        {
            var path = PathGeneratorUtilities.GetAbsolutePath("e", @".BuildXLCache\Shared\VSO0\364\~DE-1");

            var context = new Context(Logger);
            var tracer  = new Tracer(string.Empty);

            FileSystemContentStoreInternal.TryGetHashFromPath(context, tracer, new AbsolutePath(path), out _).Should().BeFalse();
        }
コード例 #13
0
        /// <summary>
        ///     Put a randomly-sized piece of content into the store.
        /// </summary>
        public static async Task <PutResult> PutRandomAsync(
            this FileSystemContentStoreInternal store, Context context, int size, HashType hashType = HashType.Vso0, PinRequest pinRequest = default(PinRequest))
        {
            var data = ThreadSafeRandom.GetBytes(size);

            using (var stream = new MemoryStream(data))
            {
                return(await store.PutStreamAsync(context, stream, hashType, pinRequest));
            }
        }
コード例 #14
0
        protected async Task PutRandomAndPinAsync(FileSystemContentStoreInternal store, int contentSize, PinContext pinContext)
        {
            PutResult putResult = await store.PutRandomAsync(Context, contentSize);

            putResult.ShouldBeSuccess();

            PinResult pinResult = await store.PinAsync(Context, putResult.ContentHash, pinContext);

            pinResult.ShouldBeSuccess();
        }
コード例 #15
0
        public Task ContainsFalse()
        {
            var context = new Context(Logger);

            return(TestStore(context, _clock, async store =>
            {
                FileSystemContentStoreInternal cas = store;
                var contentHash = ContentHash.Random();
                (await cas.ContainsAsync(context, contentHash)).Should().BeFalse();
            }));
        }
コード例 #16
0
        private async Task <bool> ValidateNameHashesMatchContentHashesAsync(Context context)
        {
            int mismatchedParentDirectoryCount = 0;
            int mismatchedContentHashCount     = 0;

            _tracer.Always(context, "Validating local CAS content hashes...");
            await TaskSafetyHelpers.WhenAll(_enumerateBlobPathsFromDisk().Select(
                                                async blobPath =>
            {
                var contentFile = blobPath.FullPath;
                if (!contentFile.FileName.StartsWith(contentFile.GetParent().FileName, StringComparison.OrdinalIgnoreCase))
                {
                    mismatchedParentDirectoryCount++;

                    _tracer.Debug(
                        context,
                        $"The first {FileSystemContentStoreInternal.HashDirectoryNameLength} characters of the name of content file at {contentFile}" +
                        $" do not match the name of its parent directory {contentFile.GetParent().FileName}.");
                }

                if (!FileSystemContentStoreInternal.TryGetHashFromPath(contentFile, out var hashFromPath))
                {
                    _tracer.Debug(
                        context,
                        $"The path '{contentFile}' does not contain a well-known hash name.");
                    return;
                }

                var hasher = ContentHashers.Get(hashFromPath.HashType);
                ContentHash hashFromContents;
                using (var contentStream = await _fileSystem.OpenSafeAsync(
                           contentFile, FileAccess.Read, FileMode.Open, FileShare.Read | FileShare.Delete, FileOptions.SequentialScan, HashingExtensions.HashStreamBufferSize))
                {
                    hashFromContents = await hasher.GetContentHashAsync(contentStream);
                }

                if (hashFromContents != hashFromPath)
                {
                    mismatchedContentHashCount++;

                    _tracer.Debug(
                        context,
                        $"Content at {contentFile} content hash {hashFromContents.ToShortString()} did not match expected value of {hashFromPath.ToShortString()}.");
                }
            }));

            _tracer.Always(context, $"{mismatchedParentDirectoryCount} mismatches between content file name and parent directory.");
            _tracer.Always(context, $"{mismatchedContentHashCount} mismatches between content file name and file contents.");

            return(mismatchedContentHashCount == 0 && mismatchedParentDirectoryCount == 0);
        }
コード例 #17
0
ファイル: QuotaKeeper.cs プロジェクト: rustedwizard/BuildXL
        public static QuotaKeeper Create(
            IAbsFileSystem fileSystem,
            ContentStoreInternalTracer tracer,
            CancellationToken token,
            FileSystemContentStoreInternal store,
            IDistributedLocationStore?distributedStore,
            QuotaKeeperConfiguration configuration)
        {
            Contract.RequiresNotNull(fileSystem);
            Contract.RequiresNotNull(tracer);
            Contract.RequiresNotNull(configuration);

            return(new QuotaKeeper(fileSystem, tracer, configuration, token, store, distributedStore));
        }
コード例 #18
0
 public FileSystemContentStoreInternalChecker(
     IAbsFileSystem fileSystem,
     IClock clock,
     AbsolutePath rootPath,
     Tracer tracer,
     SelfCheckSettings?settings,
     FileSystemContentStoreInternal contentStoreInternal)
 {
     _fileSystem           = fileSystem;
     _clock                = clock;
     _contentStoreInternal = contentStoreInternal;
     _tracer               = tracer;
     _settings             = CreateOrAdjustSelfCheckSettings(settings, rootPath);
     _selfCheckFilePath    = rootPath / "selfCheckMarker.txt";
 }
コード例 #19
0
 /// <nodoc />
 public FileSystemContentStoreInternalChecker(
     IAbsFileSystem fileSystem,
     IClock clock,
     AbsolutePath rootPath,
     Tracer tracer,
     ContentStoreSettings settings,
     FileSystemContentStoreInternal contentStoreInternal)
 {
     _fileSystem           = fileSystem;
     _clock                = clock;
     _contentStoreInternal = contentStoreInternal;
     _tracer               = tracer;
     _settings             = settings;
     _selfCheckFilePath    = rootPath / "selfCheckMarker.txt";
 }
コード例 #20
0
        /// <inheritdoc />
        public virtual async Task <CopyFileResult> CopyToAsync(OperationContext context, ContentLocation sourceLocation, Stream destinationStream, CopyOptions options)
        {
            var sourcePath = new AbsolutePath(sourceLocation.Machine.Path) / FileSystemContentStoreInternal.GetPrimaryRelativePath(sourceLocation.Hash, includeSharedFolder: false);

            if (!FileUtilities.Exists(sourcePath.Path))
            {
                return(new CopyFileResult(CopyResultCode.FileNotFoundError, $"Source file {sourcePath} doesn't exist."));
            }

            long startPosition = destinationStream.Position;

            using (Stream s = FileUtilities.CreateAsyncFileStream(sourcePath.Path, FileMode.Open, FileAccess.Read, FileShare.Read, FileOptions.Asynchronous | FileOptions.SequentialScan))
            {
                return(await s.CopyToAsync(destinationStream, 81920, context.Token).ContinueWith(_ => CopyFileResult.SuccessWithSize(destinationStream.Position - startPosition)));
            }
        }
コード例 #21
0
        protected async Task Replicate(FileSystemContentStoreInternal store, ContentHash contentHash, DisposableDirectory directory, int numberOfFiles = 1500)
        {
            // ReSharper disable once UnusedVariable
            foreach (var x in Enumerable.Range(0, numberOfFiles))
            {
                var result = await store.PlaceFileAsync(
                    Context,
                    contentHash,
                    directory.CreateRandomFileName(),
                    FileAccessMode.ReadOnly,
                    FileReplacementMode.FailIfExists,
                    FileRealizationMode.HardLink);

                result.Code.Should().Be(PlaceFileResult.ResultCode.PlacedWithHardLink);

                Clock.Increment();
            }
        }
コード例 #22
0
        /// <summary>
        /// Converts the full path to a VFS root relative path
        /// </summary>
        internal VirtualPath ToVirtualPath(VfsFilePlacementData data, FullPath path)
        {
            // Use the same index (0) for ReadOnly/Hardlink files
            var shouldHardlink = FileSystemContentStoreInternal.ShouldAttemptHardLink(path, data.AccessMode, data.RealizationMode);

            // All hardlinks of a hash share the same file under the vfs root so just
            // use index 0 to represent that file. Otherwise, create a unique index so
            // that copies get unique files
            var index = shouldHardlink
                ? 0
                : Interlocked.Increment(ref _nextVfsCasTargetFileUniqueId);

            VirtualPath casRelativePath = VfsUtilities.CreateCasRelativePath(data, index);

            var virtualPath = _configuration.VfsCasRelativeRoot / casRelativePath;

            return(virtualPath.Path);
        }
コード例 #23
0
ファイル: QuotaKeeper.cs プロジェクト: rustedwizard/BuildXL
 public QuotaKeeper(
     IAbsFileSystem fileSystem,
     ContentStoreInternalTracer tracer,
     QuotaKeeperConfiguration configuration,
     CancellationToken token,
     FileSystemContentStoreInternal store,
     IDistributedLocationStore?distributedStore)
 {
     _contentStoreTracer = tracer;
     Tracer            = new Tracer(name: $"{Component}({store.RootPath})");
     _allContentSize   = configuration.ContentDirectorySize;
     _token            = token;
     _store            = store;
     _distributedStore = distributedStore;
     _reserveQueue     = new BlockingCollection <QuotaRequest>();
     _evictionQueue    = new ConcurrentQueue <ReserveSpaceRequest>();
     _rules            = CreateRules(fileSystem, configuration, store);
     Counters          = new CounterCollection <QuotaKeeperCounters>();
 }
コード例 #24
0
        protected async Task <ContentHash> PutAsync
        (
            FileSystemContentStoreInternal store,
            MemoryStream content,
            bool useFile      = false,
            HashType hashType = ContentHashType,
            bool sync         = false
        )
        {
            ContentHash contentHash;

            if (useFile)
            {
                using (var directory = new DisposableDirectory(FileSystem))
                {
                    var path = directory.CreateRandomFileName();
                    using (var stream = FileSystem.TryOpen(
                               path, FileAccess.Write, FileMode.CreateNew, FileShare.Delete))
                    {
                        content.WriteTo(stream);
                    }

                    var r = await store.PutFileAsync(Context, path, FileRealizationMode.Any, hashType).ShouldBeSuccess();

                    contentHash = r.ContentHash;
                }
            }
            else
            {
                var r = await store.PutStreamAsync(Context, content, hashType).ShouldBeSuccess();

                contentHash = r.ContentHash;
            }

            Clock.Increment();

            if (sync)
            {
                await store.SyncAsync(Context);
            }

            return(contentHash);
        }
        public async Task ConstructorSucceedsWithLargestPossibleCacheRootLength()
        {
            var context = new Context(Logger);

            using (var testDirectory = new DisposableDirectory(FileSystem))
            {
                int extraLength = FileSystemConstants.LongPathsSupported ? 100 : 0;
                int maxAllowedCacheRootLength = FileSystemConstants.MaxShortPath - 1 -
                                                FileSystemContentStoreInternal.GetMaxContentPathLengthRelativeToCacheRoot() -
                                                testDirectory.Path.Length - 1 +
                                                extraLength;
                var cacheRoot = new AbsolutePath(testDirectory.Path + new string('a', maxAllowedCacheRootLength));

                using (var store = Create(cacheRoot, _clock))
                {
                    await store.StartupAsync(context).ShouldBeSuccess();

                    await store.ShutdownAsync(context).ShouldBeSuccess();
                }
            }
        }
コード例 #26
0
        /// <nodoc />
        public DistributedCentralStorage(
            DistributedCentralStoreConfiguration configuration,
            IDistributedContentCopier copier,
            CentralStorage fallbackStorage)
        {
            _configuration   = configuration;
            _copier          = copier;
            _fallbackStorage = fallbackStorage;

            var maxRetentionMb  = configuration.MaxRetentionGb * 1024;
            var softRetentionMb = (int)(maxRetentionMb * 0.8);

            // Create a private CAS for storing checkpoint data
            // Avoid introducing churn into primary CAS
            _privateCas = new FileSystemContentStoreInternal(
                new PassThroughFileSystem(),
                SystemClock.Instance,
                configuration.CacheRoot / CacheSubFolderName,
                new ConfigurationModel(
                    new ContentStoreConfiguration(new MaxSizeQuota(hardExpression: maxRetentionMb + "MB", softExpression: softRetentionMb + "MB")),
                    ConfigurationSelection.RequireAndUseInProcessConfiguration));
        }
コード例 #27
0
        private List <IQuotaRule> CreateRules(
            IAbsFileSystem fileSystem,
            QuotaKeeperConfiguration configuration,
            FileSystemContentStoreInternal store)
        {
            var rules = new List <IQuotaRule>();

            if (configuration.EnableElasticity)
            {
                var elasticSizeRule = new ElasticSizeRule(
                    configuration.HistoryWindowSize,
                    configuration.InitialElasticSize,
                    () => CurrentSize,
                    store.ReadPinSizeHistory,
                    fileSystem,
                    store.RootPath);
                rules.Add(elasticSizeRule);
            }
            else
            {
                if (configuration.MaxSizeQuota != null)
                {
                    rules.Add(new MaxSizeRule(configuration.MaxSizeQuota, () => CurrentSize));
                }

                if (configuration.DiskFreePercentQuota != null)
                {
                    rules.Add(new DiskFreePercentRule(configuration.DiskFreePercentQuota, fileSystem, store.RootPath));
                }
            }

            if (!rules.Any())
            {
                throw new CacheException("At least one quota rule must be defined");
            }

            return(rules);
        }
コード例 #28
0
 /// <summary>
 /// Gets the relative from deployment root to the file with given hash in CAS
 /// </summary>
 public static RelativePath GetContentRelativePath(ContentHash hash)
 {
     return(CasRelativeRoot / FileSystemContentStoreInternal.GetPrimaryRelativePath(hash));
 }
コード例 #29
0
 /// <summary>
 ///     Initializes a new instance of the <see cref="FileSystemContentSession" /> class.
 /// </summary>
 public FileSystemContentSession(string name, ImplicitPin implicitPin, FileSystemContentStoreInternal store)
     : base(name, store, implicitPin)
 {
 }
コード例 #30
0
        protected async Task AssertDoesNotContain(FileSystemContentStoreInternal store, ContentHash contentHash)
        {
            var contains = await store.ContainsAsync(Context, contentHash);

            contains.Should().BeFalse($"Expected hash={contentHash.ToShortString()} to not be present but was");
        }