Esempio n. 1
0
        /// <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."));
            }
        }
Esempio n. 2
0
        /// <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));
                }
            }
        }
Esempio n. 3
0
        /// <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);
                }
            }
        }
Esempio n. 4
0
        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();
        }
Esempio n. 5
0
        [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());
            }
        }
Esempio n. 6
0
        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());
                }
            }
        }
Esempio n. 7
0
        /// <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."));
            }
        }
Esempio n. 8
0
        /// <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);
                }
            }
        }
Esempio n. 9
0
        /// <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."));
            }
        }
Esempio n. 10
0
        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();
                }
            }
        }
Esempio n. 12
0
 private static void RestoreFullCheckpointAsync(AbsolutePath checkpointFile, AbsolutePath extractedCheckpointDirectory)
 {
     // Extracting the checkpoint archieve
     ZipFile.ExtractToDirectory(checkpointFile.ToString(), extractedCheckpointDirectory.ToString());
 }