Minor cli edits and fix potential deadlock

This commit is contained in:
Mbucari 2023-07-02 16:42:45 -06:00
parent 29803c6ba0
commit 3be7d8e825
6 changed files with 27 additions and 26 deletions

View File

@ -14,7 +14,6 @@ namespace AaxDecrypter
public class NetworkFileStream : Stream, IUpdatable public class NetworkFileStream : Stream, IUpdatable
{ {
public event EventHandler Updated; public event EventHandler Updated;
public event EventHandler DownloadCompleted;
#region Public Properties #region Public Properties
@ -41,6 +40,9 @@ namespace AaxDecrypter
[JsonIgnore] [JsonIgnore]
public bool IsCancelled => _cancellationSource.IsCancellationRequested; public bool IsCancelled => _cancellationSource.IsCancellationRequested;
[JsonIgnore]
public Task DownloadTask { get; private set; }
private long _speedLimit = 0; private long _speedLimit = 0;
/// <summary>bytes per second</summary> /// <summary>bytes per second</summary>
public long SpeedLimit { get => _speedLimit; set => _speedLimit = value <= 0 ? 0 : Math.Max(value, MIN_BYTES_PER_SECOND); } public long SpeedLimit { get => _speedLimit; set => _speedLimit = value <= 0 ? 0 : Math.Max(value, MIN_BYTES_PER_SECOND); }
@ -52,7 +54,6 @@ namespace AaxDecrypter
private FileStream _readFile { get; } private FileStream _readFile { get; }
private CancellationTokenSource _cancellationSource { get; } = new(); private CancellationTokenSource _cancellationSource { get; } = new();
private EventWaitHandle _downloadedPiece { get; set; } private EventWaitHandle _downloadedPiece { get; set; }
private Task _backgroundDownloadTask { get; set; }
#endregion #endregion
@ -128,7 +129,7 @@ namespace AaxDecrypter
if (uriToSameFile.Host != Uri.Host) if (uriToSameFile.Host != Uri.Host)
throw new ArgumentException($"New uri to the same file must have the same host.\r\n Old Host :{Uri.Host}\r\nNew Host: {uriToSameFile.Host}"); throw new ArgumentException($"New uri to the same file must have the same host.\r\n Old Host :{Uri.Host}\r\nNew Host: {uriToSameFile.Host}");
if (_backgroundDownloadTask is not null) if (DownloadTask is not null)
throw new InvalidOperationException("Cannot change Uri after download has started."); throw new InvalidOperationException("Cannot change Uri after download has started.");
Uri = uriToSameFile; Uri = uriToSameFile;
@ -141,7 +142,7 @@ namespace AaxDecrypter
{ {
if (ContentLength != 0 && WritePosition == ContentLength) if (ContentLength != 0 && WritePosition == ContentLength)
{ {
_backgroundDownloadTask = Task.CompletedTask; DownloadTask = Task.CompletedTask;
return; return;
} }
@ -167,7 +168,8 @@ namespace AaxDecrypter
_downloadedPiece = new EventWaitHandle(false, EventResetMode.AutoReset); _downloadedPiece = new EventWaitHandle(false, EventResetMode.AutoReset);
//Download the file in the background. //Download the file in the background.
_backgroundDownloadTask = Task.Run(() => DownloadFile(networkStream), _cancellationSource.Token);
DownloadTask = Task.Run(() => DownloadFile(networkStream), _cancellationSource.Token);
} }
/// <summary> Download <see cref="Uri"/> to <see cref="SaveFilePath"/>.</summary> /// <summary> Download <see cref="Uri"/> to <see cref="SaveFilePath"/>.</summary>
@ -234,7 +236,6 @@ namespace AaxDecrypter
_writeFile.Close(); _writeFile.Close();
_downloadedPiece.Set(); _downloadedPiece.Set();
OnUpdate(); OnUpdate();
DownloadCompleted?.Invoke(this, null);
} }
} }
@ -256,7 +257,7 @@ namespace AaxDecrypter
{ {
get get
{ {
if (_backgroundDownloadTask is null) if (DownloadTask is null)
throw new InvalidOperationException($"Background downloader must first be started by calling {nameof(BeginDownloadingAsync)}"); throw new InvalidOperationException($"Background downloader must first be started by calling {nameof(BeginDownloadingAsync)}");
return ContentLength; return ContentLength;
} }
@ -280,7 +281,7 @@ namespace AaxDecrypter
public override int Read(byte[] buffer, int offset, int count) public override int Read(byte[] buffer, int offset, int count)
{ {
if (_backgroundDownloadTask is null) if (DownloadTask is null)
throw new InvalidOperationException($"Background downloader must first be started by calling {nameof(BeginDownloadingAsync)}"); throw new InvalidOperationException($"Background downloader must first be started by calling {nameof(BeginDownloadingAsync)}");
var toRead = Math.Min(count, Length - Position); var toRead = Math.Min(count, Length - Position);
@ -306,7 +307,7 @@ namespace AaxDecrypter
private void WaitToPosition(long requiredPosition) private void WaitToPosition(long requiredPosition)
{ {
while (WritePosition < requiredPosition while (WritePosition < requiredPosition
&& _backgroundDownloadTask?.IsCompleted is false && DownloadTask?.IsCompleted is false
&& !IsCancelled) && !IsCancelled)
{ {
_downloadedPiece.WaitOne(50); _downloadedPiece.WaitOne(50);
@ -326,7 +327,7 @@ namespace AaxDecrypter
if (disposing && !disposed) if (disposing && !disposed)
{ {
_cancellationSource.Cancel(); _cancellationSource.Cancel();
_backgroundDownloadTask?.GetAwaiter().GetResult(); DownloadTask?.GetAwaiter().GetResult();
_downloadedPiece?.Dispose(); _downloadedPiece?.Dispose();
_cancellationSource?.Dispose(); _cancellationSource?.Dispose();
_readFile.Dispose(); _readFile.Dispose();

View File

@ -26,11 +26,7 @@ namespace AaxDecrypter
protected override async Task<bool> Step_DownloadAndDecryptAudiobookAsync() protected override async Task<bool> Step_DownloadAndDecryptAudiobookAsync()
{ {
TaskCompletionSource completionSource = new(); await InputFileStream.DownloadTask;
InputFileStream.DownloadCompleted += (_, _) => completionSource.SetResult();
await completionSource.Task;
if (IsCanceled) if (IsCanceled)
return false; return false;

View File

@ -10,7 +10,7 @@ namespace LibationCli.Options
[Verb("search", HelpText = "Search for books in your library")] [Verb("search", HelpText = "Search for books in your library")]
internal class SearchOptions : OptionsBase internal class SearchOptions : OptionsBase
{ {
[Value(0, MetaName = "query", Required = true, HelpText = "Lucene query test to search")] [Value(0, MetaName = "query", Required = true, HelpText = "Lucene search string")]
public IEnumerable<string> Query { get; set; } public IEnumerable<string> Query { get; set; }
protected override Task ProcessAsync() protected override Task ProcessAsync()
@ -31,7 +31,7 @@ namespace LibationCli.Options
if (waitForNextBatch) if (waitForNextBatch)
{ {
Console.Write(nextPrompt); Console.Write(nextPrompt);
waitForNextBatch = Console.ReadKey().Key != ConsoleKey.Escape; waitForNextBatch = Console.ReadKey(intercept: true).Key != ConsoleKey.Escape;
ReplaceConsoleText(Console.Out, nextPrompt.Length, ""); ReplaceConsoleText(Console.Out, nextPrompt.Length, "");
Console.SetCursorPosition(0, Console.CursorTop); Console.SetCursorPosition(0, Console.CursorTop);
} }

View File

@ -17,7 +17,7 @@ namespace LibationCli
[Option(shortName: 'd', longName: "downloaded", Group = "Download Status", HelpText = "set download status to 'Downloaded'")] [Option(shortName: 'd', longName: "downloaded", Group = "Download Status", HelpText = "set download status to 'Downloaded'")]
public bool SetDownloaded { get; set; } public bool SetDownloaded { get; set; }
[Option(shortName: 'n', longName: "not-downloaded", Group = "Download Status", HelpText = "set download status to 'Downloaded'")] [Option(shortName: 'n', longName: "not-downloaded", Group = "Download Status", HelpText = "set download status to 'Not Downloaded'")]
public bool SetNotDownloaded { get; set; } public bool SetNotDownloaded { get; set; }
[Option("force", HelpText = "Set the download status regardless of whether the book's audio file can be found. Only one download status option may be used with this option.")] [Option("force", HelpText = "Set the download status regardless of whether the book's audio file can be found. Only one download status option may be used with this option.")]
@ -38,7 +38,7 @@ namespace LibationCli
if (Asins.Any()) if (Asins.Any())
{ {
var asins = Asins.Select(a => a.ToLower()).ToArray(); var asins = Asins.Select(a => a.TrimStart('[').TrimEnd(']').ToLower()).ToArray();
libraryBooks = libraryBooks.Where(lb => lb.Book.AudibleProductId.ToLower().In(asins)).ToList(); libraryBooks = libraryBooks.Where(lb => lb.Book.AudibleProductId.ToLower().In(asins)).ToList();
if (libraryBooks.Count == 0) if (libraryBooks.Count == 0)

View File

@ -51,16 +51,20 @@ namespace LibationCli
protected async Task RunAsync(Processable Processable) protected async Task RunAsync(Processable Processable)
{ {
var libraryBooks = DbContexts.GetLibrary_Flat_NoTracking().AsEnumerable(); var libraryBooks = DbContexts.GetLibrary_Flat_NoTracking();
if (Asins.Any()) if (Asins.Any())
{ {
var asinsLower = Asins.Select(a => a.ToLower()).ToArray(); var asinsLower = Asins.Select(a => a.TrimStart('[').TrimEnd(']').ToLower()).ToArray();
libraryBooks = libraryBooks.Where(lb => lb.Book.AudibleProductId.ToLower().In(asinsLower));
}
foreach (var libraryBook in Processable.GetValidLibraryBooks(libraryBooks)) foreach (var lb in libraryBooks.Where(lb => lb.Book.AudibleProductId.ToLower().In(asinsLower)))
await ProcessOneAsync(Processable, libraryBook, false); await ProcessOneAsync(Processable, lb, true);
}
else
{
foreach (var lb in Processable.GetValidLibraryBooks(libraryBooks))
await ProcessOneAsync(Processable, lb, false);
}
var done = "Done. All books have been processed"; var done = "Done. All books have been processed";
Console.WriteLine(done); Console.WriteLine(done);

View File

@ -21,7 +21,7 @@ namespace LibationCli
{ {
#if DEBUG #if DEBUG
string input = null; string input = "";
//input = " set-status -n --force B017V4IM1G"; //input = " set-status -n --force B017V4IM1G";
//input = " liberate B017V4IM1G"; //input = " liberate B017V4IM1G";