Remote write

This commit is contained in:
2023-07-26 21:21:55 +02:00
parent 144745a558
commit d26401948a
25 changed files with 293 additions and 34 deletions

View File

@@ -1,12 +1,34 @@
using FileTime.Core.ContentAccess;
using FileTime.Core.Models;
using FileTime.Providers.LocalAdmin;
using Microsoft.Extensions.Logging;
namespace FileTime.Providers.Local;
public class LocalContentWriterFactory : IContentWriterFactory<ILocalContentProvider>
{
public Task<IContentWriter> CreateContentWriterAsync(IElement element)
private readonly IAdminContentAccessorFactory _adminContentAccessorFactory;
private readonly ILogger<LocalContentWriterFactory> _logger;
public LocalContentWriterFactory(
IAdminContentAccessorFactory adminContentAccessorFactory,
ILogger<LocalContentWriterFactory> logger)
{
return Task.FromResult((IContentWriter) new LocalContentWriter(File.OpenWrite(element.NativePath!.Path)));
_adminContentAccessorFactory = adminContentAccessorFactory;
_logger = logger;
}
public async Task<IContentWriter> CreateContentWriterAsync(IElement element)
{
try
{
return new LocalContentWriter(File.OpenWrite(element.NativePath!.Path));
}
catch (UnauthorizedAccessException e)
{
_logger.LogDebug(e, "Failed to write to element with path {Path}", element.NativePath);
var adminContentWriter = await _adminContentAccessorFactory.CreateContentWriterAsync(element.NativePath!);
return adminContentWriter;
}
}
}

View File

@@ -1,4 +1,5 @@
using FileTime.Providers.Remote;
using FileTime.Core.Models;
using FileTime.Providers.Remote;
namespace FileTime.Providers.LocalAdmin;
@@ -8,4 +9,5 @@ public interface IAdminContentAccessorFactory
Task<IRemoteItemCreator> CreateAdminItemCreatorAsync();
Task<IRemoteItemDeleter> CreateAdminItemDeleterAsync();
Task<IRemoteItemMover> CreateAdminItemMoverAsync();
Task<IRemoteContentWriter> CreateContentWriterAsync(NativePath nativePath);
}

View File

@@ -1,7 +1,9 @@
using System.Diagnostics;
using FileTime.Core.Models;
using FileTime.Providers.Remote;
using FileTime.Server.Common;
using InitableService;
using Microsoft.Extensions.DependencyInjection;
namespace FileTime.Providers.LocalAdmin;
@@ -13,7 +15,7 @@ public class AdminContentAccessorFactory : IAdminContentAccessorFactory
public AdminContentAccessorFactory(
IAdminElevationManager adminElevationManager,
IServiceProvider serviceProvider
)
)
{
_adminElevationManager = adminElevationManager;
_serviceProvider = serviceProvider;
@@ -27,19 +29,33 @@ public class AdminContentAccessorFactory : IAdminContentAccessorFactory
public async Task<IRemoteItemDeleter> CreateAdminItemDeleterAsync()
=> await CreateHelperAsync<IRemoteItemDeleter>();
public async Task<IRemoteItemMover> CreateAdminItemMoverAsync()
public async Task<IRemoteItemMover> CreateAdminItemMoverAsync()
=> await CreateHelperAsync<IRemoteItemMover>();
public async Task<IRemoteContentWriter> CreateContentWriterAsync(NativePath nativePath)
{
await _adminElevationManager.CreateAdminInstanceIfNecessaryAsync();
var connection = await _adminElevationManager.CreateConnectionAsync();
var contentWriter = _serviceProvider.GetInitableResolver(
connection,
_adminElevationManager.ProviderName,
nativePath,
Guid.NewGuid()
).GetRequiredService<IRemoteContentWriter>();
return contentWriter;
}
private async Task<T> CreateHelperAsync<T>()
where T : class, IInitable<IRemoteConnection, string>
{
await _adminElevationManager.CreateAdminInstanceIfNecessaryAsync();
var connection = await _adminElevationManager.CreateConnectionAsync();
Debug.Assert(connection != null);
var helper = _serviceProvider.GetInitableResolver(
connection,
connection,
_adminElevationManager.ProviderName)
.GetRequiredService<T>();
return helper;

View File

@@ -89,8 +89,6 @@ public class AdminElevationManager : IAdminElevationManager, INotifyPropertyChan
process.Start();
_adminProcess = process;
IsAdminInstanceRunning = true;
//TODO: timeout
while (!File.Exists(portFileName) || new FileInfo(portFileName).Length == 0)
await Task.Delay(10);
@@ -109,6 +107,8 @@ public class AdminElevationManager : IAdminElevationManager, INotifyPropertyChan
}
}
IsAdminInstanceRunning = true;
var connectionInfo = new ConnectionInfo
{
SignalRBaseUrl = $"http://localhost:{port}/RemoteHub"

View File

@@ -0,0 +1,12 @@
using FileTime.Core.ContentAccess;
using FileTime.Core.Models;
using FileTime.Server.Common;
using InitableService;
namespace FileTime.Providers.Remote;
public interface IRemoteContentWriter :
IContentWriter,
IInitable<IRemoteConnection, string, NativePath, Guid>
{
}

View File

@@ -0,0 +1,51 @@
using FileTime.Core.Models;
using FileTime.Server.Common;
namespace FileTime.Providers.Remote;
public class RemoteContentWriter : IRemoteContentWriter
{
private IRemoteConnection _remoteConnection = null!;
private string _remoteContentProviderId = null!;
private NativePath _nativePath = null!;
private string _transactionId = null!;
private bool _isRemoteWriterInitialized;
public void Init(
IRemoteConnection remoteConnection,
string remoteContentProviderId,
NativePath nativePath,
Guid transactionId)
{
_remoteConnection = remoteConnection;
_remoteContentProviderId = remoteContentProviderId;
_nativePath = nativePath;
_transactionId = transactionId.ToString();
}
public void Dispose()
{
if (!_isRemoteWriterInitialized) return;
_remoteConnection.CloseWriterAsync(_transactionId);
}
public int PreferredBufferSize => 10 * 1024;
public async Task WriteBytesAsync(byte[] data, int? index = null)
{
if (!_isRemoteWriterInitialized) await InitializeRemoteWriter(_nativePath);
await _remoteConnection.WriteBytesAsync(_transactionId, data, index);
}
public async Task FlushAsync()
{
if (!_isRemoteWriterInitialized) return;
await _remoteConnection.FlushWriterAsync(_transactionId);
}
private async Task InitializeRemoteWriter(NativePath nativePath)
{
_isRemoteWriterInitialized = true;
await _remoteConnection.InitializeRemoteWriter(_remoteContentProviderId, _transactionId, nativePath);
}
}

View File

@@ -11,6 +11,7 @@ public static class Startup
serviceCollection.TryAddTransient<IRemoteItemCreator, RemoteItemCreator>();
serviceCollection.TryAddTransient<IRemoteItemDeleter, RemoteItemDeleter>();
serviceCollection.TryAddTransient<IRemoteItemMover, RemoteItemMover>();
serviceCollection.TryAddTransient<IRemoteContentWriter, RemoteContentWriter>();
return serviceCollection;
}
}