Remove stream-like functionality from ContentReader/Writer
Use streams instead
This commit is contained in:
@@ -5,44 +5,14 @@ namespace FileTime.Providers.Local;
|
||||
public class LocalContentReader : IContentReader
|
||||
{
|
||||
private readonly FileStream _readerStream;
|
||||
private readonly BinaryReader _binaryReader;
|
||||
private bool _disposed;
|
||||
|
||||
public int PreferredBufferSize => 1024 * 1024;
|
||||
public long? Position { get; private set; }
|
||||
|
||||
public LocalContentReader(FileStream readerStream)
|
||||
{
|
||||
_readerStream = readerStream;
|
||||
_binaryReader = new BinaryReader(_readerStream);
|
||||
}
|
||||
|
||||
public Task<byte[]> ReadBytesAsync(int bufferSize, int? offset = null)
|
||||
{
|
||||
var max = bufferSize > 0 && bufferSize < PreferredBufferSize ? bufferSize : PreferredBufferSize;
|
||||
|
||||
if (offset != null)
|
||||
{
|
||||
if (Position == null) Position = 0;
|
||||
var buffer = new byte[max];
|
||||
var bytesRead = _binaryReader.Read(buffer, offset.Value, max);
|
||||
Position += bytesRead;
|
||||
|
||||
if (buffer.Length != bytesRead)
|
||||
{
|
||||
Array.Resize(ref buffer, bytesRead);
|
||||
}
|
||||
return Task.FromResult(buffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
return Task.FromResult(_binaryReader.ReadBytes(max));
|
||||
}
|
||||
}
|
||||
|
||||
public void SetPosition(long position) => Position = position;
|
||||
|
||||
public Stream AsStream() => _binaryReader.BaseStream;
|
||||
public Stream GetStream() => _readerStream;
|
||||
|
||||
~LocalContentReader()
|
||||
{
|
||||
@@ -62,7 +32,6 @@ public class LocalContentReader : IContentReader
|
||||
if (disposing)
|
||||
{
|
||||
_readerStream.Dispose();
|
||||
_binaryReader.Dispose();
|
||||
}
|
||||
}
|
||||
_disposed = true;
|
||||
|
||||
@@ -5,36 +5,14 @@ namespace FileTime.Providers.Local;
|
||||
public class LocalContentWriter : IContentWriter
|
||||
{
|
||||
private readonly FileStream _writerStream;
|
||||
private readonly BinaryWriter _binaryWriter;
|
||||
private bool _disposed;
|
||||
public int PreferredBufferSize => 1024 * 1024;
|
||||
|
||||
public LocalContentWriter(FileStream writerStream)
|
||||
{
|
||||
_writerStream = writerStream;
|
||||
_binaryWriter = new BinaryWriter(_writerStream);
|
||||
}
|
||||
|
||||
public Task WriteBytesAsync(byte[] data, int? index = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
if (index != null)
|
||||
{
|
||||
_binaryWriter.Write(data, index.Value, data.Length);
|
||||
}
|
||||
else
|
||||
{
|
||||
_binaryWriter.Write(data);
|
||||
}
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task FlushAsync(CancellationToken cancellationToken = default)
|
||||
{
|
||||
_binaryWriter.Flush();
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Stream AsStream() => _binaryWriter.BaseStream;
|
||||
public Stream GetStream() => _writerStream;
|
||||
|
||||
~LocalContentWriter()
|
||||
{
|
||||
@@ -54,7 +32,6 @@ public class LocalContentWriter : IContentWriter
|
||||
if (disposing)
|
||||
{
|
||||
_writerStream.Dispose();
|
||||
_binaryWriter.Dispose();
|
||||
}
|
||||
}
|
||||
_disposed = true;
|
||||
|
||||
@@ -5,7 +5,7 @@ namespace FileTime.Providers.Remote;
|
||||
|
||||
public interface IRemoteContentProvider : IContentProvider
|
||||
{
|
||||
Task<IRemoteConnection> GetRemoteConnectionAsync();
|
||||
ValueTask<IRemoteConnection> GetRemoteConnectionAsync();
|
||||
string RemoteProviderName { get; }
|
||||
Task InitializeChildren();
|
||||
}
|
||||
58
src/Providers/FileTime.Providers.Remote/ProxyStream.cs
Normal file
58
src/Providers/FileTime.Providers.Remote/ProxyStream.cs
Normal file
@@ -0,0 +1,58 @@
|
||||
namespace FileTime.Providers.Remote;
|
||||
|
||||
internal sealed class ProxyStream : Stream
|
||||
{
|
||||
private readonly RemoteContentWriter _remoteContentWriter;
|
||||
|
||||
public ProxyStream(RemoteContentWriter remoteContentWriter)
|
||||
{
|
||||
_remoteContentWriter = remoteContentWriter;
|
||||
}
|
||||
|
||||
public override void Flush() => InitializeRemoteWriterAndRun(() => _remoteContentWriter.FlushAsync());
|
||||
|
||||
public override int Read(byte[] buffer, int offset, int count)
|
||||
=> InitializeRemoteWriterAndRun(() => _remoteContentWriter.ReadAsync(buffer, offset, count));
|
||||
|
||||
public override long Seek(long offset, SeekOrigin origin)
|
||||
=> InitializeRemoteWriterAndRun(() => _remoteContentWriter.SeekAsync(offset, origin));
|
||||
|
||||
public override void SetLength(long value) => InitializeRemoteWriterAndRun(() => _remoteContentWriter.SetLengthAsync(value));
|
||||
|
||||
public override void Write(byte[] buffer, int offset, int count) => InitializeRemoteWriterAndRun(() => _remoteContentWriter.WriteAsync(buffer, offset, count));
|
||||
|
||||
public override bool CanRead => InitializeRemoteWriterAndRun(() => _remoteContentWriter.CanReadAsync());
|
||||
|
||||
public override bool CanSeek => InitializeRemoteWriterAndRun(() => _remoteContentWriter.CanSeekAsync());
|
||||
|
||||
public override bool CanWrite => InitializeRemoteWriterAndRun(() => _remoteContentWriter.CanWriteAsync());
|
||||
|
||||
public override long Length => InitializeRemoteWriterAndRun(() => _remoteContentWriter.GetLengthAsync());
|
||||
|
||||
public override long Position
|
||||
{
|
||||
get => InitializeRemoteWriterAndRun(() => _remoteContentWriter.GetPositionAsync());
|
||||
set => InitializeRemoteWriterAndRun(() => _remoteContentWriter.SetPositionAsync(value));
|
||||
}
|
||||
|
||||
private void InitializeRemoteWriterAndRun(Func<Task> func)
|
||||
{
|
||||
var task = Task.Run(async () =>
|
||||
{
|
||||
await _remoteContentWriter.InitializeRemoteWriterAsync();
|
||||
await func();
|
||||
});
|
||||
task.Wait();
|
||||
}
|
||||
|
||||
private T InitializeRemoteWriterAndRun<T>(Func<Task<T>> func)
|
||||
{
|
||||
var task = Task.Run(async () =>
|
||||
{
|
||||
await _remoteContentWriter.InitializeRemoteWriterAsync();
|
||||
return await func();
|
||||
});
|
||||
task.Wait();
|
||||
return task.Result;
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,7 @@ namespace FileTime.Providers.Remote;
|
||||
public sealed class RemoteContentProvider : ContentProviderBase, IRemoteContentProvider
|
||||
{
|
||||
private readonly IServiceProvider _serviceProvider;
|
||||
private readonly Func<Task<IRemoteConnection>> _remoteConnectionProvider;
|
||||
private readonly Func<ValueTask<IRemoteConnection>> _remoteConnectionProvider;
|
||||
private readonly SemaphoreSlim _initializeSemaphore = new(1, 1);
|
||||
private bool _initialized;
|
||||
|
||||
@@ -20,7 +20,7 @@ public sealed class RemoteContentProvider : ContentProviderBase, IRemoteContentP
|
||||
public RemoteContentProvider(
|
||||
ITimelessContentProvider timelessContentProvider,
|
||||
IServiceProvider serviceProvider,
|
||||
Func<Task<IRemoteConnection>> remoteConnectionProvider,
|
||||
Func<ValueTask<IRemoteConnection>> remoteConnectionProvider,
|
||||
string remoteName,
|
||||
string name)
|
||||
: base(name, timelessContentProvider)
|
||||
@@ -30,8 +30,7 @@ public sealed class RemoteContentProvider : ContentProviderBase, IRemoteContentP
|
||||
_remoteConnectionProvider = remoteConnectionProvider;
|
||||
}
|
||||
|
||||
public async Task<IRemoteConnection> GetRemoteConnectionAsync()
|
||||
=> await _remoteConnectionProvider();
|
||||
public ValueTask<IRemoteConnection> GetRemoteConnectionAsync() => _remoteConnectionProvider();
|
||||
|
||||
public async Task InitializeChildren()
|
||||
{
|
||||
|
||||
@@ -30,25 +30,78 @@ public class RemoteContentWriter : IContentWriter, IInitable<IRemoteContentProvi
|
||||
Task.Run(async () => await (await _remoteContentProvider.GetRemoteConnectionAsync()).CloseWriterAsync(_transactionId));
|
||||
}
|
||||
|
||||
public int PreferredBufferSize => 10 * 1024 * 1024;
|
||||
public Stream GetStream() => new ProxyStream(this);
|
||||
|
||||
public async Task WriteBytesAsync(byte[] data, int? index = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
if (!_isRemoteWriterInitialized) await InitializeRemoteWriter(_nativePath);
|
||||
await (await _remoteContentProvider.GetRemoteConnectionAsync()).WriteBytesAsync(_transactionId, data, index, cancellationToken);
|
||||
}
|
||||
|
||||
public async Task FlushAsync(CancellationToken cancellationToken = default)
|
||||
{
|
||||
if (!_isRemoteWriterInitialized) return;
|
||||
await (await _remoteContentProvider.GetRemoteConnectionAsync()).FlushWriterAsync(_transactionId, cancellationToken);
|
||||
}
|
||||
|
||||
public Stream AsStream() => new ContentAccessStream(this);
|
||||
|
||||
private async Task InitializeRemoteWriter(NativePath nativePath)
|
||||
public async Task InitializeRemoteWriterAsync()
|
||||
{
|
||||
if (_isRemoteWriterInitialized) return;
|
||||
_isRemoteWriterInitialized = true;
|
||||
await (await _remoteContentProvider.GetRemoteConnectionAsync()).InitializeRemoteWriter(_remoteContentProviderId, _transactionId, nativePath);
|
||||
await (await _remoteContentProvider.GetRemoteConnectionAsync()).InitializeRemoteWriter(_remoteContentProviderId, _transactionId, _nativePath);
|
||||
}
|
||||
|
||||
public async Task FlushAsync()
|
||||
{
|
||||
await InitializeRemoteWriterAsync();
|
||||
await (await _remoteContentProvider.GetRemoteConnectionAsync()).FlushAsync(_transactionId);
|
||||
}
|
||||
|
||||
public async Task<int> ReadAsync(byte[] buffer, int offset, int count)
|
||||
{
|
||||
await InitializeRemoteWriterAsync();
|
||||
return await (await _remoteContentProvider.GetRemoteConnectionAsync()).ReadAsync(_transactionId, buffer, offset, count);
|
||||
}
|
||||
|
||||
public async Task<long> SeekAsync(long offset, SeekOrigin origin)
|
||||
{
|
||||
await InitializeRemoteWriterAsync();
|
||||
return await (await _remoteContentProvider.GetRemoteConnectionAsync()).SeekAsync(_transactionId, offset, origin);
|
||||
}
|
||||
|
||||
public async Task SetLengthAsync(long value)
|
||||
{
|
||||
await InitializeRemoteWriterAsync();
|
||||
await (await _remoteContentProvider.GetRemoteConnectionAsync()).SetLengthAsync(_transactionId, value);
|
||||
}
|
||||
|
||||
public async Task WriteAsync(byte[] buffer, int offset, int count)
|
||||
{
|
||||
await InitializeRemoteWriterAsync();
|
||||
await (await _remoteContentProvider.GetRemoteConnectionAsync()).WriteAsync(_transactionId, buffer, offset, count);
|
||||
}
|
||||
|
||||
public async Task<bool> CanReadAsync()
|
||||
{
|
||||
await InitializeRemoteWriterAsync();
|
||||
return await (await _remoteContentProvider.GetRemoteConnectionAsync()).CanReadAsync(_transactionId);
|
||||
}
|
||||
|
||||
public async Task<bool> CanSeekAsync()
|
||||
{
|
||||
await InitializeRemoteWriterAsync();
|
||||
return await (await _remoteContentProvider.GetRemoteConnectionAsync()).CanSeekAsync(_transactionId);
|
||||
}
|
||||
|
||||
public async Task<bool> CanWriteAsync()
|
||||
{
|
||||
await InitializeRemoteWriterAsync();
|
||||
return await (await _remoteContentProvider.GetRemoteConnectionAsync()).CanWriteAsync(_transactionId);
|
||||
}
|
||||
|
||||
public async Task<long> GetLengthAsync()
|
||||
{
|
||||
await InitializeRemoteWriterAsync();
|
||||
return await (await _remoteContentProvider.GetRemoteConnectionAsync()).GetLengthAsync(_transactionId);
|
||||
}
|
||||
|
||||
public async Task<long> GetPositionAsync()
|
||||
{
|
||||
await InitializeRemoteWriterAsync();
|
||||
return await (await _remoteContentProvider.GetRemoteConnectionAsync()).GetPositionAsync(_transactionId);
|
||||
}
|
||||
|
||||
public async Task SetPositionAsync(long position)
|
||||
{
|
||||
await InitializeRemoteWriterAsync();
|
||||
await (await _remoteContentProvider.GetRemoteConnectionAsync()).SetPositionAsync(_transactionId, position);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user