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);
                }
            }
        }
Example #2
0
        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);
        }