Skip to content

Commit

Permalink
feat(storage): Implement the StreamedCustomDataLoader
Browse files Browse the repository at this point in the history
  • Loading branch information
dr1rrb committed Oct 9, 2020
1 parent c65e55e commit e6a63ae
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 85 deletions.
36 changes: 23 additions & 13 deletions src/Uno.UWP/Storage/StreamedFileDataRequest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using Windows.ApplicationModel.Appointments;
using Windows.Foundation;
using Windows.Storage.Streams;
Expand All @@ -11,14 +12,14 @@ namespace Windows.Storage
{
public sealed partial class StreamedFileDataRequest : IOutputStream, IDisposable, IStreamedFileDataRequest
{
private readonly StreamedRandomAccessStream _owner;
private readonly StreamedCustomDataLoader _owner;
private readonly Stream _tempFile;
private readonly CancellationTokenSource _ct;

internal StreamedFileDataRequest(StreamedRandomAccessStream owner, Stream tempFile)
internal StreamedFileDataRequest(StreamedCustomDataLoader owner)
{
_owner = owner;
_tempFile = tempFile;
_tempFile = owner.File.OpenWeak(FileAccess.Write);
_ct = new CancellationTokenSource();
}

Expand All @@ -29,30 +30,39 @@ internal StreamedFileDataRequest(StreamedRandomAccessStream owner, Stream tempFi
public IAsyncOperationWithProgress<uint, uint> WriteAsync(IBuffer buffer)
=> new AsyncOperationWithProgress<uint, uint>(async (ct, op) =>
{
var write = _tempFile.WriteAsyncOperation(buffer);
write.Progress = (snd, p) => op.NotifyProgress(p);
try
{
await _tempFile.WriteAsync(buffer, ct);
await _tempFile.FlushAsync(ct); // We make sure to write the data to the disk before allow read to access it
}
catch (IOException e)
{
throw new OperationCanceledException("The download of this file has been cancelled", e);
}
var written = await write.AsTask(ct);
_owner.ReportDataWritten(buffer.Capacity);
// We make sure to write the data to the disk before allow read to access it
_tempFile.FlushAsync(ct);
//_owner.OnDataLoadProgress(written);
return written;
return buffer.Capacity;
});

public IAsyncOperation<bool> FlushAsync()
=> _tempFile.FlushAsyncOperation(); // This is actually useless as we flush on each Write.

public void FailAndClose(StreamedFileFailureMode failureMode)
{
//_owner.OnDataLoadCompleted(failureMode);
_ct.Dispose();
_tempFile.Dispose();
_owner.ReportLoadCompleted(failureMode);
}

public void Dispose()
{
_ct.Dispose();
//_owner.OnDataLoadCompleted(default);
_tempFile.Dispose();
_owner.ReportLoadCompleted();
}

~StreamedFileDataRequest()
=> Dispose();
}
}
72 changes: 0 additions & 72 deletions src/Uno.UWP/Storage/StreamedFileDataRequestedHandler.cs
Original file line number Diff line number Diff line change
@@ -1,80 +1,8 @@
#nullable enable

using System;
using System.IO;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Uno;
using Uno.Extensions;

namespace Windows.Storage
{
public delegate void StreamedFileDataRequestedHandler(StreamedFileDataRequest stream);

//internal static class StreamedFileDataRequestedHandlerHelper
//{
// public static StreamedFileDataRequestedHandler CreateFromUri(
// Uri uri,
// HttpMethod? method = null,
// HttpClient? client = null,
// ActionAsync<HttpResponseMessage?, Exception?>? onReady = null)
// {
// method ??= HttpMethod.Get;
// client ??= new HttpClient();

// return req => Task.Run(() => FetchAsync(req, uri, method, client, onReady, req.CancellationToken));
// }

// private static async Task FetchAsync(
// StreamedFileDataRequest req,
// Uri uri,
// HttpMethod method,
// HttpClient client,
// ActionAsync<HttpResponseMessage?, Exception?>? onReady,
// CancellationToken ct)
// {
// try
// {
// HttpResponseMessage response;
// try
// {
// var request = new HttpRequestMessage(method, uri);
// response = await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, ct);

// response.EnsureSuccessStatusCode();

// if (onReady is {})
// {
// await onReady(ct, response, null);
// }
// }
// catch (Exception e) when (onReady is {})
// {
// await onReady(ct, null, e);
// throw;
// }

// if (response.Content is { } content)
// {
// var responseStream = await content.ReadAsStreamAsync();
// await responseStream.CopyToAsync(req.AsStreamForWrite(), global::Windows.Storage.Streams.Buffer.DefaultCapacity, ct);
// }
// }
// catch (Exception e)
// {
// if (req.Log().IsEnabled(LogLevel.Warning))
// {
// req.Log().LogWarning("Failed to load content", e);
// }

// req.FailAndClose(StreamedFileFailureMode.Failed);
// }
// finally
// {
// req.Dispose();
// }
// }
//}
}
64 changes: 64 additions & 0 deletions src/Uno.UWP/Storage/Streams/StreamedCustomDataLoader.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
#nullable enable

using System;
using System.Linq;
using Windows.Foundation;

namespace Windows.Storage.Streams
{
internal class StreamedCustomDataLoader : IStreamedDataLoader
{
private uint _loaded;
private bool _isCompleted;
private StreamedFileFailureMode? _failure;

public StreamedCustomDataLoader(StreamedFileDataRequestedHandler handler, TemporaryFile? tempFile = null)
{
File = tempFile ?? new TemporaryFile();

handler(new StreamedFileDataRequest(this));
}

/// <inheritdoc />
public event TypedEventHandler<IStreamedDataLoader, object?>? DataUpdated;

/// <inheritdoc />
public TemporaryFile File { get; }

/// <inheritdoc />
public string? ContentType { get; } = RandomAccessStreamWithContentType.DefaultContentType;

/// <inheritdoc />
public void CheckState()
{
if (_failure.HasValue)
{
throw new InvalidOperationException($"The async load of the data has failed ('{_failure.Value}')");
}
}

/// <inheritdoc />
public bool CanRead(ulong position)
=> _isCompleted || position < _loaded;

internal void ReportDataWritten(uint length)
{
_loaded += length;
DataUpdated?.Invoke(this, default);
}

internal void ReportLoadCompleted(StreamedFileFailureMode? failure = null)
{
// Note: this is expected to be invoke more than once!

_failure ??= failure;

if (!_isCompleted)
{
_isCompleted = true;

DataUpdated?.Invoke(this, default);
}
}
}
}

0 comments on commit e6a63ae

Please sign in to comment.