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