Remote write
This commit is contained in:
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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>
|
||||
{
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user