Beispiel #1
0
        /// <inheritdoc />
        public async Task <PlaceFileResult> PlaceFileAsync(
            Context context,
            ContentHash contentHash,
            AbsolutePath path,
            FileAccessMode accessMode,
            FileReplacementMode replacementMode,
            FileRealizationMode realizationMode,
            CancellationToken cts,
            UrgencyHint urgencyHint = UrgencyHint.Nominal)
        {
            var placeFileResult = await _sessionForPath.PlaceFileAsync(
                context,
                contentHash,
                path,
                accessMode,
                replacementMode,
                realizationMode,
                cts,
                urgencyHint);

            if (placeFileResult.Code == PlaceFileResult.ResultCode.NotPlacedContentNotFound)
            {
                placeFileResult = await _sessionForStream.PlaceFileAsync(
                    context,
                    contentHash,
                    path,
                    accessMode,
                    replacementMode,
                    realizationMode,
                    cts,
                    urgencyHint);
            }

            return(placeFileResult);
        }
Beispiel #2
0
        /// <inheritdoc />
        public Task <PlaceFileResult> PlaceFileAsync(
            Context context,
            ContentHash contentHash,
            AbsolutePath path,
            FileAccessMode accessMode,
            FileReplacementMode replacementMode,
            FileRealizationMode realizationMode,
            CancellationToken cts,
            UrgencyHint urgencyHint)
        {
            return(PlaceFileCall <ContentSessionTracer> .RunAsync(Tracer.ContentSessionTracer, new OperationContext(context), contentHash, path, accessMode, replacementMode, realizationMode, async() =>
            {
                if (WriteThroughContentSession != null)
                {
                    var writeThroughResult = await WriteThroughContentSession.PlaceFileAsync(context, contentHash, path, accessMode, replacementMode, realizationMode, cts, urgencyHint).ConfigureAwait(false);
                    if (writeThroughResult.Succeeded || writeThroughResult.Code != PlaceFileResult.ResultCode.NotPlacedContentNotFound)
                    {
                        UnixHelpers.OverrideFileAccessMode(_overrideUnixFileAccessMode, path.Path);
                        return writeThroughResult;
                    }
                }

                var backingResult = await BackingContentSession.PlaceFileAsync(context, contentHash, path, accessMode, replacementMode, realizationMode, cts, urgencyHint);
                UnixHelpers.OverrideFileAccessMode(_overrideUnixFileAccessMode, path.Path);
                return backingResult;
            }));
        }
Beispiel #3
0
        /// <inheritdoc />
        protected async override Task <PlaceFileResult> PlaceFileCoreAsync(OperationContext operationContext, ContentHash contentHash, AbsolutePath path, FileAccessMode accessMode, FileReplacementMode replacementMode, FileRealizationMode realizationMode, UrgencyHint urgencyHint, Counter retryCounter)
        {
            if (replacementMode != FileReplacementMode.ReplaceExisting && _fileSystem.FileExists(path))
            {
                if (replacementMode == FileReplacementMode.SkipIfExists)
                {
                    return(new PlaceFileResult(PlaceFileResult.ResultCode.NotPlacedAlreadyExists));
                }
                else if (replacementMode == FileReplacementMode.FailIfExists)
                {
                    return(new PlaceFileResult(
                               PlaceFileResult.ResultCode.Error,
                               $"File exists at destination {path} with FailIfExists specified"));
                }
            }

            var virtualPath = _contentManager.ToVirtualPath(path);

            if (virtualPath == null)
            {
                return(await _innerSession.PlaceFileAsync(operationContext, contentHash, path, accessMode, replacementMode, realizationMode, operationContext.Token, urgencyHint));
            }

            _contentManager.Tree.AddFileNode(virtualPath, new VfsFilePlacementData(contentHash, realizationMode, accessMode));
            return(new PlaceFileResult(GetPlaceResultCode(realizationMode, accessMode), fileSize: -1 /* Unknown */));
        }
Beispiel #4
0
        /// <inheritdoc />
        protected override async Task <PlaceFileResult> PlaceFileCoreAsync(OperationContext operationContext, ContentHash contentHash, AbsolutePath path, FileAccessMode accessMode, FileReplacementMode replacementMode, FileRealizationMode realizationMode, UrgencyHint urgencyHint, Counter retryCounter)
        {
            if (!path.IsVirtual)
            {
                return(await _innerSession.PlaceFileAsync(
                           operationContext,
                           contentHash,
                           path,
                           accessMode,
                           replacementMode,
                           realizationMode,
                           operationContext.Token,
                           urgencyHint));
            }

            if (replacementMode != FileReplacementMode.ReplaceExisting && _fileSystem.FileExists(path))
            {
                if (replacementMode == FileReplacementMode.SkipIfExists)
                {
                    return(new PlaceFileResult(PlaceFileResult.ResultCode.NotPlacedAlreadyExists));
                }
                else if (replacementMode == FileReplacementMode.FailIfExists)
                {
                    return(new PlaceFileResult(
                               PlaceFileResult.ResultCode.Error,
                               $"File exists at destination {path} with FailIfExists specified"));
                }
            }

            var placementData = new VfsFilePlacementData(contentHash, realizationMode, accessMode);

            return(await _contentManager.PlaceFileAsync(operationContext, path, placementData, operationContext.Token));
        }
        /// <inheritdoc />
        public Task <PlaceFileResult> PlaceFileAsync(
            Context context,
            ContentHash contentHash,
            AbsolutePath path,
            FileAccessMode accessMode,
            FileReplacementMode replacementMode,
            FileRealizationMode realizationMode,
            CancellationToken cts,
            UrgencyHint urgencyHint = UrgencyHint.Nominal)
        {
            IContentSession hardlinkSession = null;

            if (realizationMode == FileRealizationMode.HardLink)
            {
                var drive = path.GetPathRoot();
                if (SessionsByCacheRoot.TryGetValue(drive, out var session) && session is IContentSession writeableSession)
                {
                    hardlinkSession = writeableSession;
                }
                else
                {
                    return(Task.FromResult(new PlaceFileResult("Requested hardlink but there is no session on the same drive as destination path.")));
                }
            }

            return(PerformAggregateSessionOperationAsync <IReadOnlyContentSession, PlaceFileResult>(
                       context,
                       executeAsync: placeFileCore,
                       (r1, r2) => r1.Succeeded ? r1 : r2,
                       shouldBreak: r => r.Succeeded,
                       pathHint: path));

            async Task <PlaceFileResult> placeFileCore(IReadOnlyContentSession session)
            {
                // If we exclusively want a hardlink, we should make sure that we can copy from other drives to satisfy the request.
                if (realizationMode != FileRealizationMode.HardLink || session == hardlinkSession)
                {
                    return(await session.PlaceFileAsync(context, contentHash, path, accessMode, replacementMode, realizationMode, cts, urgencyHint));
                }

                // See if session has the content.
                var streamResult = await session.OpenStreamAsync(context, contentHash, cts, urgencyHint).ThrowIfFailure();

                // Put it into correct store
                var putResult = await hardlinkSession.PutStreamAsync(context, contentHash, streamResult.Stream, cts, urgencyHint).ThrowIfFailure();

                // Try the hardlink on the correct drive.
                return(await hardlinkSession.PlaceFileAsync(context, contentHash, path, accessMode, replacementMode, realizationMode, cts, urgencyHint));
            }
        }
Beispiel #6
0
        public Task TestColdStorageWithBulkFunction()
        {
            return(RunTestAsync(async(context, store, directory) =>
            {
                var originalPath = directory.Path / "original.txt";
                var fileContents = GetRandomFileContents();

                // Build destination IContentSession
                DisposableDirectory sessionDirectory = new DisposableDirectory(FileSystem);
                ConfigurationModel configurationModel = new ConfigurationModel(new ContentStoreConfiguration(new MaxSizeQuota("10MB")));
                FileSystemContentStore destination = new FileSystemContentStore(FileSystem, SystemClock.Instance, sessionDirectory.Path, configurationModel);
                _ = await destination.StartupAsync(context);
                IContentSession contentSession = destination.CreateSession(context, "test_session", BuildXL.Cache.ContentStore.Interfaces.Stores.ImplicitPin.None).Session;
                _ = await contentSession.StartupAsync(context);

                // Create the file and hardlink it into the cache.
                FileSystem.WriteAllText(originalPath, fileContents);

                var contentHasher = HashInfoLookup.GetContentHasher(HashType.MD5);
                var contentHash = contentHasher.GetContentHash(Encoding.UTF8.GetBytes(fileContents));

                await store.PutFileAsync(context, contentHash, new DisposableFile(context, FileSystem, originalPath), context.Token).ShouldBeSuccess();

                FileSystem.DeleteFile(originalPath);
                FileSystem.FileExists(originalPath).Should().Be(false);

                ContentHashWithPath contentHashWithPath = new ContentHashWithPath(contentHash, originalPath);
                List <ContentHashWithPath> listFile = new List <ContentHashWithPath>();
                listFile.Add(contentHashWithPath);

                // Hardlink back to original location trying to replace existing.
                var copyTask = await store.FetchThenPutBulkAsync(
                    context,
                    listFile,
                    contentSession);

                await copyTask.ToLookupAwait(r => { return r.Item.Succeeded; });

                FileSystem.FileExists(originalPath).Should().Be(false);

                // The file is in the destination.
                await contentSession.PlaceFileAsync(context, contentHash, originalPath, FileAccessMode.Write, FileReplacementMode.FailIfExists, FileRealizationMode.Copy, CancellationToken.None).ShouldBeSuccess();
                FileSystem.FileExists(originalPath).Should().Be(true);
                FileSystem.ReadAllText(originalPath).Should().Be(fileContents);

                _ = await contentSession.ShutdownAsync(context);
                _ = await destination.ShutdownAsync(context);
            }));
        }
Beispiel #7
0
        /// <summary>
        /// Places a hydrated file at the given VFS root relative path
        /// </summary>
        /// <param name="relativePath">the vfs root relative path</param>
        /// <param name="data">the content and placement data for the file</param>
        /// <param name="token">the cancellation token</param>
        /// <returns>a task which completes when the operation is complete or throws an exception if error is encountered during operation</returns>
        public Task PlaceHydratedFileAsync(VirtualPath relativePath, VfsFilePlacementData data, CancellationToken token)
        {
            var context = new OperationContext(new Context(_logger), token);

            return(context.PerformOperationAsync(
                       _tracer,
                       async() =>
            {
                var tempFilePath = _tempDirectory.CreateRandomFileName();
                var result = await _contentSession.PlaceFileAsync(
                    context,
                    data.Hash,
                    tempFilePath,
                    data.AccessMode,
                    FileReplacementMode.ReplaceExisting,
                    data.RealizationMode,
                    token).ThrowIfFailure();

                var fullPath = ToFullPath(relativePath);

                _fileSystem.MoveFile(tempFilePath, fullPath, true);

                if (result.FileSize >= 0)
                {
                    Counters[VfsCounters.PlaceHydratedFileBytes].Add(result.FileSize);
                }
                else
                {
                    Counters[VfsCounters.PlaceHydratedFileUnknownSizeCount].Increment();
                }

                return BoolResult.Success;
            },
                       extraStartMessage: $"RelativePath={relativePath}, Hash={data.Hash}",
                       counter: Counters[VfsCounters.PlaceHydratedFile]));
        }