From 315af41624d25b43d9b7048dccd4827ee34b568c Mon Sep 17 00:00:00 2001 From: anthony Date: Tue, 1 Feb 2022 09:54:28 +0000 Subject: [PATCH] Fix downloads being cut off early --- frontends/gnustep/DownloadManager.h | 2 + frontends/gnustep/DownloadManager.m | 57 ++++++++++++++++++++++++----- frontends/gnustep/tables/download.m | 1 - 3 files changed, 49 insertions(+), 11 deletions(-) diff --git a/frontends/gnustep/DownloadManager.h b/frontends/gnustep/DownloadManager.h index 20fc434fa..ae33f134a 100644 --- a/frontends/gnustep/DownloadManager.h +++ b/frontends/gnustep/DownloadManager.h @@ -14,6 +14,8 @@ struct download_context; BOOL completed; BOOL cancelled; NSUInteger size; + NSUInteger confirmedSize, sizeUntilNow; + NSLock *confirmedSizeLock; NSUInteger written; NSInteger index; NSDate *startDate; diff --git a/frontends/gnustep/DownloadManager.m b/frontends/gnustep/DownloadManager.m index 036698191..dfa1b0e7d 100644 --- a/frontends/gnustep/DownloadManager.m +++ b/frontends/gnustep/DownloadManager.m @@ -3,6 +3,11 @@ #import "desktop/download.h" #import "Preferences.h" +@interface DownloadItem(Private) +-(void) completeAndNotifyManager; +-(void) notifyManager; +@end + @implementation DownloadItem -(id)initWithManager: (DownloadManager*)aManager destination: (NSURL*)aDestination size: (NSInteger)aSize index: (NSUInteger)anIndex ctx: (struct download_context*)aCtx { @@ -10,6 +15,8 @@ error = nil; index = anIndex; written = 0; + confirmedSize = 0; + confirmedSizeLock = [[NSLock alloc] init]; completed = NO; size = aSize; startDate = [[NSDate date] retain]; @@ -29,12 +36,15 @@ return self; } +// TODO: - Why isn't this releasing? -(void)dealloc { + NSLog(@"DownloadItem dealloc!!"); runThread = NO; [destination release]; [outputStream close]; [outputStream release]; [startDate release]; + [confirmedSizeLock release]; if (error) { [error release]; } @@ -56,11 +66,11 @@ } -(BOOL)appendToDownload: (NSData*)data { + sizeUntilNow += [data length]; if (downloadThread == nil) { NSLog(@"Error: expected download thread to be initialized"); return NO; } - [data retain]; [self performSelector: @selector(reallyWriteData:) onThread: downloadThread withObject: data waitUntilDone: NO modes: [NSArray arrayWithObject: NSDefaultRunLoopMode]]; @@ -68,9 +78,15 @@ } -(void)reallyWriteData: (NSData*)data { - NSUInteger len = [data length]; - NSUInteger writtenNow = [outputStream write: [data bytes] maxLength: len]; - written += writtenNow; + NSUInteger toWrite = [data length]; + NSInteger thisWrite; + const uint8_t *start = [data bytes]; + while (toWrite > 0) { + thisWrite = [outputStream write: start maxLength: toWrite]; + start += thisWrite; + toWrite -= thisWrite; + } + written += [data length]; // Unless im misunderstanding download_context_get_total_length appears to return // a too-small non-zero value for download size when called so... size = MAX(written, size); @@ -81,6 +97,25 @@ waitUntilDone: NO]; } lastWrite = time; + + // Check if we're complete. + BOOL done; + [confirmedSizeLock lock]; + done = confirmedSize > 0 && written >= confirmedSize; + [confirmedSizeLock unlock]; + if (done) { + [self performSelectorOnMainThread: @selector(completeAndNotifyManager) + withObject: nil waitUntilDone: NO]; + } +} +-(void)completeAndNotifyManager { + completed = YES; + runThread = NO; + [outputStream close]; + [[manager delegate] downloadManager: manager didUpdateItem: self]; + if ([[Preferences defaultPreferences] removeDownloadsOnComplete]) { + [manager removeDownloadsAtIndexes: [NSIndexSet indexSetWithIndex: index]]; + } } -(void)notifyManager { [[manager delegate] downloadManager: manager didUpdateItem: self]; @@ -104,12 +139,14 @@ } -(void)complete { - [outputStream close]; - completed = YES; - [[manager delegate] downloadManager: manager didUpdateItem: self]; - if ([[Preferences defaultPreferences] removeDownloadsOnComplete]) { - [manager removeDownloadsAtIndexes: [NSIndexSet indexSetWithIndex: index]]; - } + NSLog(@"Complete called..."); + // Having set this non-0, our download thread will know to complete. + [confirmedSizeLock lock]; + confirmedSize = sizeUntilNow; + [confirmedSizeLock unlock]; + // Trigger a write just to trigger the completion check if there's no data + // pending write. + [self appendToDownload: [NSData data]]; } -(BOOL)isComplete { diff --git a/frontends/gnustep/tables/download.m b/frontends/gnustep/tables/download.m index 336d2cc92..ad9d56acf 100644 --- a/frontends/gnustep/tables/download.m +++ b/frontends/gnustep/tables/download.m @@ -110,7 +110,6 @@ static struct gui_download_window *gnustep_download_create(struct download_conte // ?? static nserror gnustep_download_data(struct gui_download_window *dw, const char *data, unsigned int size) { - NSLog(@"gnustep_download_data"); BOOL success = [(id)dw appendToDownload: [NSData dataWithBytesNoCopy: (void*)data length: size freeWhenDone: NO]]; if (success) {