private Result Read(U8Span path, bool allowMissingMetaFile) { lock (Locker) { FileSystemClient fs = Server.GetFsClient(); Result rc = fs.OpenFile(out FileHandle handle, path, OpenMode.Read); if (rc.IsFailure()) { if (ResultFs.PathNotFound.Includes(rc)) { if (allowMissingMetaFile) { Count = 0; return(Result.Success); } return(ResultBcat.NotFound.LogConverted(rc)); } return(rc); } try { Count = 0; int header = 0; // Verify the header value rc = fs.ReadFile(out long bytesRead, handle, 0, SpanHelpers.AsByteSpan(ref header)); if (rc.IsFailure()) { return(rc); } if (bytesRead != sizeof(int) || header != MetaFileHeaderValue) { return(ResultBcat.InvalidDeliveryCacheStorageFile.Log()); } // Read all the directory entries Span <byte> buffer = MemoryMarshal.Cast <DeliveryCacheDirectoryMetaEntry, byte>(Entries); rc = fs.ReadFile(out bytesRead, handle, 4, buffer); if (rc.IsFailure()) { return(rc); } Count = (int)((uint)bytesRead / Unsafe.SizeOf <DeliveryCacheDirectoryMetaEntry>()); return(Result.Success); } finally { fs.CloseFile(handle); } } }
public static Result CopyFileWithProgress(FileSystemClient fs, U8Span sourcePath, U8Span destPath, IProgressReport logger = null) { Result rc = fs.OpenFile(out FileHandle sourceHandle, sourcePath, OpenMode.Read); if (rc.IsFailure()) { return(rc); } try { rc = fs.OpenFile(out FileHandle destHandle, destPath, OpenMode.Write | OpenMode.AllowAppend); if (rc.IsFailure()) { return(rc); } try { const int maxBufferSize = 1024 * 1024; rc = fs.GetFileSize(out long fileSize, sourceHandle); if (rc.IsFailure()) { return(rc); } int bufferSize = (int)Math.Min(maxBufferSize, fileSize); byte[] buffer = ArrayPool <byte> .Shared.Rent(bufferSize); try { for (long offset = 0; offset < fileSize; offset += bufferSize) { int toRead = (int)Math.Min(fileSize - offset, bufferSize); Span <byte> buf = buffer.AsSpan(0, toRead); rc = fs.ReadFile(out long _, sourceHandle, offset, buf); if (rc.IsFailure()) { return(rc); } rc = fs.WriteFile(destHandle, offset, buf, WriteOption.None); if (rc.IsFailure()) { return(rc); } logger?.ReportAdd(toRead); } } finally { ArrayPool <byte> .Shared.Return(buffer); } rc = fs.FlushFile(destHandle); if (rc.IsFailure()) { return(rc); } } finally { if (destHandle.IsValid) { fs.CloseFile(destHandle); } } } finally { if (sourceHandle.IsValid) { fs.CloseFile(sourceHandle); } } return(Result.Success); }