/// <inheritdoc /> protected override BoolResult RestoreCheckpointCore(OperationContext context, AbsolutePath checkpointDirectory) { try { var nextActiveSlot = GetNextSlot(_activeSlot); var newStoreLocation = GetStoreLocation(nextActiveSlot); Tracer.Info(context.TracingContext, $"Loading content location database checkpoint from '{checkpointDirectory}' into '{newStoreLocation}'."); if (Directory.Exists(newStoreLocation)) { FileUtilities.DeleteDirectoryContents(newStoreLocation, deleteRootDirectory: true); } Directory.Move(checkpointDirectory.ToString(), newStoreLocation); var possiblyLoaded = Load(context, nextActiveSlot, clean: false); if (possiblyLoaded.Succeeded) { SaveActiveSlot(context.TracingContext); } return(possiblyLoaded); } catch (Exception ex) when(ex.IsRecoverableIoException()) { return(new BoolResult(ex, "Restore checkpoint failed.")); } }
/// <inheritdoc /> public int GetHardLinkCount(AbsolutePath path) { path.ThrowIfPathTooLong(); if (BuildXL.Utilities.OperatingSystemHelper.IsUnixOS) { return((int)FileUtilities.GetHardLinkCount(path.ToString())); } else { using (SafeFileHandle sourceFileHandle = NativeMethods.CreateFile( path.Path, NativeMethods.FILE_READ_ATTRIBUTES, FileShare.ReadWrite | FileShare.Delete, IntPtr.Zero, FileMode.Open, 0, IntPtr.Zero)) { string errorMessage = string.Format(CultureInfo.InvariantCulture, "Could not get link count of {0}.", path.Path); if (sourceFileHandle.IsInvalid) { throw new FileNotFoundException(errorMessage, path.FileName); } if (!NativeMethods.GetFileInformationByHandle(sourceFileHandle, out var handleInfo)) { throw ThrowLastWin32Error(path.Path, errorMessage); } return(checked ((int)handleInfo.NumberOfLinks)); } } }
/// <inheritdoc /> public ulong GetFileId(AbsolutePath path) { path.ThrowIfPathTooLong(); if (BuildXL.Utilities.OperatingSystemHelper.IsUnixOS) { var createOrOpenResult = FileUtilities.TryCreateOrOpenFile(path.ToString(), FileDesiredAccess.FileReadAttributes, FileShare.ReadWrite | FileShare.Delete, FileMode.Open, FileFlagsAndAttributes.FileFlagOverlapped, out SafeFileHandle handle); if (!createOrOpenResult.Succeeded) { throw ThrowLastWin32Error(path.ToString(), $"Failed to create or open file {path} to get its ID. Status: {createOrOpenResult.Status}"); } return((ulong)handle.DangerousGetHandle().ToInt64()); } else { using (SafeFileHandle sourceFileHandle = NativeMethods.CreateFile( path.Path, NativeMethods.FILE_READ_ATTRIBUTES, FileShare.ReadWrite | FileShare.Delete, IntPtr.Zero, FileMode.Open, 0, /* Allow symbolic links to redirect us */ IntPtr.Zero)) { string errorMessage = string.Format(CultureInfo.InvariantCulture, "Could not get file id of {0}.", path.Path); if (sourceFileHandle.IsInvalid) { throw new FileNotFoundException(errorMessage, path.FileName); } if (!NativeMethods.GetFileInformationByHandle(sourceFileHandle, out var handleInfo)) { throw ThrowLastWin32Error(path.Path, errorMessage); } return((((ulong)handleInfo.FileIndexHigh) << 32) | handleInfo.FileIndexLow); } } }
private async Task CreateFullCheckpointAsync(OperationContext context, EventSequencePoint sequencePoint) { // Zipping the checkpoint var targetZipFile = _checkpointStagingDirectory + ".zip"; File.Delete(targetZipFile); ZipFile.CreateFromDirectory(_checkpointStagingDirectory.ToString(), targetZipFile); // Track checkpoint size var fileInfo = new System.IO.FileInfo(targetZipFile); _tracer.TrackMetric(context, CheckpointSizeMetricName, fileInfo.Length); var checkpointBlobName = $"checkpoints/{sequencePoint.SequenceNumber}.{Guid.NewGuid()}.zip"; var checkpointId = await _storage.UploadFileAsync(context, new AbsolutePath(targetZipFile), checkpointBlobName, garbageCollect : true).ThrowIfFailureAsync(); // Uploading the checkpoint await _checkpointRegistry.RegisterCheckpointAsync(context, checkpointId, sequencePoint).ThrowIfFailure(); }
[Trait("Category", "WindowsOSOnly")] // PathTooLongException is windows specific issue. public void NoErrorsIfLongPathsSupported() { if (LongPathsSupported) { // Parent property throws PathTooLongException, not a constructor. // So need to access it to make sure the exception is not thrown. var longPath = new AbsolutePath(Constants.ValidAbsoluteLocalLongPath); Assert.NotNull(longPath.Parent); Assert.StartsWith(FileSystemConstants.LongPathPrefix, longPath.ToString()); } }
public void ReturnsTrueForLocalLongPathConstructedByCombiningThePath() { if (LongPathsSupported) { var path = new AbsolutePath(Constants.ValidAbsoluteLocalLongPath) / new string('a', 200); Assert.True(path.IsLocal); if (OperatingSystemHelper.IsWindowsOS) { // Windows specific check: the resulting long path should have a long path prefix. Assert.StartsWith(FileSystemConstants.LongPathPrefix, path.ToString()); } } }
/// <inheritdoc /> protected override BoolResult SaveCheckpointCore(OperationContext context, AbsolutePath checkpointDirectory) { try { var targetDirectory = checkpointDirectory.ToString(); Tracer.Info(context.TracingContext, $"Saving content location database checkpoint to '{targetDirectory}'."); if (Directory.Exists(targetDirectory)) { FileUtilities.DeleteDirectoryContents(targetDirectory, deleteRootDirectory: true); } return(_keyValueStore.Use(store => store.SaveCheckpoint(targetDirectory)).ToBoolResult()); } catch (Exception ex) when(ex.IsRecoverableIoException()) { return(new BoolResult(ex, "Save checkpoint failed.")); } }
/// <inheritdoc /> public void DeleteFile(AbsolutePath path) { path.ThrowIfPathTooLong(); try { FileUtilities.DeleteFile(path.Path); } catch (BuildXLException e) { // Preserving backward compatibility and throwing 'UnauthorizedAccessException' due to shared violation. // 0x20 is shared violation. if (e.InnerException is NativeWin32Exception win32 && win32.ErrorCode == 0x20) { var extraMessage = FileUtilities.TryFindOpenHandlesToFile(path.ToString(), out var info, printCurrentFilePath: false) ? info : "Attempt to find processes with open handles to the file failed."; throw new UnauthorizedAccessException($"{e.Message} {extraMessage}", e); } } }
/// <inheritdoc /> protected override BoolResult RestoreCheckpointCore(OperationContext context, AbsolutePath checkpointDirectory) { try { var activeSlot = _activeSlot; var newActiveSlot = GetNextSlot(activeSlot); var newStoreLocation = GetStoreLocation(newActiveSlot); Tracer.Info(context.TracingContext, $"Loading content location database checkpoint from '{checkpointDirectory}' into '{newStoreLocation}'."); if (Directory.Exists(newStoreLocation)) { FileUtilities.DeleteDirectoryContents(newStoreLocation, deleteRootDirectory: true); } Directory.Move(checkpointDirectory.ToString(), newStoreLocation); var possiblyLoaded = Load(context, newActiveSlot, clean: false); if (possiblyLoaded.Succeeded) { SaveActiveSlot(context.TracingContext); } // At this point in time, we have unloaded the old database and loaded the new one. This means we're // free to backup the old one's logs. var oldStoreLocation = GetStoreLocation(activeSlot); BackupLogs(context, oldStoreLocation, name: $"Restore{activeSlot}"); return(possiblyLoaded); } catch (Exception ex) when(ex.IsRecoverableIoException()) { return(new BoolResult(ex, "Restore checkpoint failed.")); } }
private CreateHardLinkResult CreateHardLinkUnix(AbsolutePath sourceFileName, AbsolutePath destinationFileName, bool replaceExisting) { var createOrOpenResult = FileUtilities.TryCreateOrOpenFile(sourceFileName.ToString(), 0, FileShare.ReadWrite | FileShare.Delete, FileMode.Open, FileFlagsAndAttributes.FileFlagOverlapped, out var sourceFileHandle); using (sourceFileHandle) { if (!createOrOpenResult.Succeeded) { switch (createOrOpenResult.Status) { case OpenFileStatus.Success: break; case OpenFileStatus.FileNotFound: case OpenFileStatus.PathNotFound: return(CreateHardLinkResult.FailedSourceDoesNotExist); case OpenFileStatus.Timeout: case OpenFileStatus.AccessDenied: case OpenFileStatus.UnknownError: default: throw ThrowLastWin32Error(destinationFileName.Path, $"Failed to create or open file {sourceFileName.Path} to create hard link. Status: {createOrOpenResult.Status}"); } } } if (!replaceExisting && FileExists(destinationFileName)) { return(CreateHardLinkResult.FailedDestinationExists); } var createHardLinkResult = FileUtilities.TryCreateHardLink(destinationFileName.ToString(), sourceFileName.ToString()); if (createHardLinkResult.HasFlag(CreateHardLinkStatus.FailedAccessDenied)) { return(CreateHardLinkResult.FailedAccessDenied); } else if (createHardLinkResult.HasFlag(CreateHardLinkStatus.FailedDueToPerFileLinkLimit)) { return(CreateHardLinkResult.FailedMaxHardLinkLimitReached); } else if (createHardLinkResult.HasFlag(CreateHardLinkStatus.FailedSinceDestinationIsOnDifferentVolume)) { return(CreateHardLinkResult.FailedSourceAndDestinationOnDifferentVolumes); } else if (createHardLinkResult.HasFlag(CreateHardLinkStatus.FailedSinceNotSupportedByFilesystem)) { return(CreateHardLinkResult.FailedNotSupported); } else if (createHardLinkResult.HasFlag(CreateHardLinkStatus.Failed)) { return(CreateHardLinkResult.Unknown); } else if (createHardLinkResult.HasFlag(CreateHardLinkStatus.Success)) { return(CreateHardLinkResult.Success); } else { throw ThrowLastWin32Error(sourceFileName.Path, $"Failed to create hard link for file {sourceFileName.Path} with unknown error: {createHardLinkResult.ToString()}"); } }
private Stream OpenInternal(AbsolutePath path, FileAccess accessMode, FileMode mode, FileShare share, FileOptions options, int bufferSize) { if (OperatingSystemHelper.IsUnixOS) { if (DirectoryExists(path)) { throw new UnauthorizedAccessException($"Cannot open directory {path} as a file."); } if (mode == FileMode.Open && !FileExists(path)) { return(null); } return(new FileStream(path.Path, mode, accessMode, share)); } int access = GetDwAccess(accessMode); options = GetOptions(path, options); SafeFileHandle handle; void openHandle() { handle = NativeMethods.CreateFile(path.Path, access, share, IntPtr.Zero, mode, options, IntPtr.Zero); } openHandle(); int lastError = Marshal.GetLastWin32Error(); if (handle.IsInvalid && mode == FileMode.Create) { switch (lastError) { case NativeMethods.ERROR_ACCESS_DENIED: case NativeMethods.ERROR_SHARING_VIOLATION: if (lastError == NativeMethods.ERROR_ACCESS_DENIED && (GetFileAttributes(path) & FileAttributes.ReadOnly) != 0) { SetFileAttributes(path, FileAttributes.Normal); } DeleteFile(path); openHandle(); break; } } if (handle.IsInvalid) { switch (lastError) { case NativeMethods.ERROR_FILE_NOT_FOUND: case NativeMethods.ERROR_PATH_NOT_FOUND: return((Stream)null); default: throw ThrowLastWin32Error( path.Path, string.Format( CultureInfo.InvariantCulture, "Unable to open a handle to '{0}' as {1} with {2}.", path.Path, mode, accessMode)); } } var needToDisposeHandle = true; try { // Returning a special tracking stream that tracks improper resource de-allocations. var stream = new TrackingFileStream(handle, accessMode, bufferSize, isAsync: true, path.ToString()); needToDisposeHandle = false; return(stream); } finally { if (needToDisposeHandle) { handle.Dispose(); } } }
private static void RestoreFullCheckpointAsync(AbsolutePath checkpointFile, AbsolutePath extractedCheckpointDirectory) { // Extracting the checkpoint archieve ZipFile.ExtractToDirectory(checkpointFile.ToString(), extractedCheckpointDirectory.ToString()); }