Ben Copsey

More tweaks to progress tracking

Run synchronous requests in custom runloop mode again
@@ -266,7 +266,8 @@ extern unsigned long const ASIWWANBandwidthThrottleAmount; @@ -266,7 +266,8 @@ extern unsigned long const ASIWWANBandwidthThrottleAmount;
266 NSTimeInterval timeOutSeconds; 266 NSTimeInterval timeOutSeconds;
267 267
268 // Will be YES when a HEAD request will handle the content-length before this request starts 268 // Will be YES when a HEAD request will handle the content-length before this request starts
269 - BOOL shouldResetProgressIndicators; 269 + BOOL shouldResetUploadProgress;
  270 + BOOL shouldResetDownloadProgress;
270 271
271 // Used by HEAD requests when showAccurateProgress is YES to preset the content-length for this request 272 // Used by HEAD requests when showAccurateProgress is YES to preset the content-length for this request
272 ASIHTTPRequest *mainRequest; 273 ASIHTTPRequest *mainRequest;
@@ -385,6 +386,9 @@ extern unsigned long const ASIWWANBandwidthThrottleAmount; @@ -385,6 +386,9 @@ extern unsigned long const ASIWWANBandwidthThrottleAmount;
385 386
386 // An ID that uniquely identifies this request - primarily used for debugging persistent connections 387 // An ID that uniquely identifies this request - primarily used for debugging persistent connections
387 NSNumber *requestID; 388 NSNumber *requestID;
  389 +
  390 + // Will be ASIHTTPRequestRunLoopMode for synchronous requests, NSDefaultRunLoopMode for all other requests
  391 + NSString *runLoopMode;
388 } 392 }
389 393
390 #pragma mark init / dealloc 394 #pragma mark init / dealloc
@@ -466,10 +470,10 @@ extern unsigned long const ASIWWANBandwidthThrottleAmount; @@ -466,10 +470,10 @@ extern unsigned long const ASIWWANBandwidthThrottleAmount;
466 // Called when authorisation is needed, as we only find out we don't have permission to something when the upload is complete 470 // Called when authorisation is needed, as we only find out we don't have permission to something when the upload is complete
467 - (void)removeUploadProgressSoFar; 471 - (void)removeUploadProgressSoFar;
468 472
469 -// Called when we get a content-length header and shouldResetProgressIndicators is true 473 +// Called when we get a content-length header and shouldResetDownloadProgress is true
470 - (void)incrementDownloadSizeBy:(long long)length; 474 - (void)incrementDownloadSizeBy:(long long)length;
471 475
472 -// Called when a request starts and shouldResetProgressIndicators is true 476 +// Called when a request starts and shouldResetUploadProgress is true
473 // Also called (with a negative length) to remove the size of the underlying buffer used for uploading 477 // Also called (with a negative length) to remove the size of the underlying buffer used for uploading
474 - (void)incrementUploadSizeBy:(long long)length; 478 - (void)incrementUploadSizeBy:(long long)length;
475 479
@@ -723,7 +727,8 @@ extern unsigned long const ASIWWANBandwidthThrottleAmount; @@ -723,7 +727,8 @@ extern unsigned long const ASIWWANBandwidthThrottleAmount;
723 @property (retain) NSMutableData *postBody; 727 @property (retain) NSMutableData *postBody;
724 @property (assign,readonly) unsigned long long contentLength; 728 @property (assign,readonly) unsigned long long contentLength;
725 @property (assign) unsigned long long postLength; 729 @property (assign) unsigned long long postLength;
726 -@property (assign) BOOL shouldResetProgressIndicators; 730 +@property (assign) BOOL shouldResetDownloadProgress;
  731 +@property (assign) BOOL shouldResetUploadProgress;
727 @property (assign) ASIHTTPRequest *mainRequest; 732 @property (assign) ASIHTTPRequest *mainRequest;
728 @property (assign) BOOL showAccurateProgress; 733 @property (assign) BOOL showAccurateProgress;
729 @property (assign,readonly) unsigned long long totalBytesRead; 734 @property (assign,readonly) unsigned long long totalBytesRead;
This diff is collapsed. Click to expand it.
@@ -55,7 +55,7 @@ @@ -55,7 +55,7 @@
55 int requestsCount; 55 int requestsCount;
56 56
57 // When NO, this request will only update the progress indicator when it completes 57 // When NO, this request will only update the progress indicator when it completes
58 - // When YES, this request will update the progress indicator according to how much data it has recieved so far 58 + // When YES, this request will update the progress indicator according to how much data it has received so far
59 // When YES, the queue will first perform HEAD requests for all GET requests in the queue, so it can calculate the total download size before it starts 59 // When YES, the queue will first perform HEAD requests for all GET requests in the queue, so it can calculate the total download size before it starts
60 // NO means better performance, because it skips this step for GET requests, and it won't waste time updating the progress indicator until a request completes 60 // NO means better performance, because it skips this step for GET requests, and it won't waste time updating the progress indicator until a request completes
61 // Set to YES if the size of a requests in the queue varies greatly for much more accurate results 61 // Set to YES if the size of a requests in the queue varies greatly for much more accurate results
@@ -71,24 +71,12 @@ @@ -71,24 +71,12 @@
71 [self setRequestDidFailSelector:NULL]; 71 [self setRequestDidFailSelector:NULL];
72 [self setRequestDidFinishSelector:NULL]; 72 [self setRequestDidFinishSelector:NULL];
73 [self setQueueDidFinishSelector:NULL]; 73 [self setQueueDidFinishSelector:NULL];
74 - [self setTotalBytesToUpload:0];  
75 - [self setBytesUploadedSoFar:0];  
76 - [self setTotalBytesToDownload:0];  
77 - [self setBytesDownloadedSoFar:0];  
78 [self setSuspended:YES]; 74 [self setSuspended:YES];
79 } 75 }
80 76
81 77
82 - (void)go 78 - (void)go
83 { 79 {
84 - if (![self showAccurateProgress]) {  
85 - if ([self downloadProgressDelegate]) {  
86 - [self setTotalBytesToDownload:[self requestsCount]];  
87 - }  
88 - if ([self uploadProgressDelegate]) {  
89 - [self setTotalBytesToUpload:[self requestsCount]];  
90 - }  
91 - }  
92 [self setSuspended:NO]; 80 [self setSuspended:NO];
93 } 81 }
94 82
@@ -172,35 +160,33 @@ @@ -172,35 +160,33 @@
172 // If this is a GET request and we want accurate progress, perform a HEAD request first to get the content-length 160 // If this is a GET request and we want accurate progress, perform a HEAD request first to get the content-length
173 // We'll only do this before the queue is started 161 // We'll only do this before the queue is started
174 // If requests are added after the queue is started they will probably move the overall progress backwards anyway, so there's no value performing the HEAD requests first 162 // If requests are added after the queue is started they will probably move the overall progress backwards anyway, so there's no value performing the HEAD requests first
175 - // Instead, they'll update the total progress if and when they recieve a content-length header 163 + // Instead, they'll update the total progress if and when they receive a content-length header
176 - if ([[request requestMethod] isEqualToString:@"GET"] && [self isSuspended]) { 164 + if ([[request requestMethod] isEqualToString:@"GET"]) {
177 - ASIHTTPRequest *HEADRequest = [request HEADRequest]; 165 + if ([self isSuspended]) {
178 - [self addHEADOperation:HEADRequest]; 166 + ASIHTTPRequest *HEADRequest = [request HEADRequest];
179 - 167 + [self addHEADOperation:HEADRequest];
180 - if ([request shouldResetProgressIndicators]) { 168 + [request addDependency:HEADRequest];
181 - [self resetProgressDelegate:[request downloadProgressDelegate]]; 169 + if ([request shouldResetDownloadProgress]) {
182 - } 170 + [self resetProgressDelegate:[request downloadProgressDelegate]];
183 - 171 + [request setShouldResetDownloadProgress:NO];
184 - //Tell the request not to reset the progress indicator when it gets a content-length, as we will get the length from the HEAD request 172 + }
185 - [request setShouldResetProgressIndicators:NO];  
186 -  
187 - [request addDependency:HEADRequest];  
188 -  
189 - // If we want to track uploading for this request accurately, we need to add the size of the post content to the total  
190 - } else if (uploadProgressDelegate) {  
191 - [request buildPostBody];  
192 - [self setTotalBytesToUpload:[self totalBytesToUpload]+[request postLength]];  
193 -  
194 -  
195 - if ([request shouldResetProgressIndicators]) {  
196 - [self resetProgressDelegate:[request uploadProgressDelegate]];  
197 } 173 }
198 -  
199 - [request setShouldResetProgressIndicators:NO];  
200 } 174 }
  175 + [request buildPostBody];
  176 + [self request:nil incrementUploadSizeBy:[request postLength]];
  177 +
  178 +
  179 + } else {
  180 + [self request:nil incrementDownloadSizeBy:1];
  181 + [self request:nil incrementUploadSizeBy:1];
201 } 182 }
  183 + // Tell the request not to increment the upload size when it starts, as we've already added its length
  184 + if ([request shouldResetUploadProgress]) {
  185 + [self resetProgressDelegate:[request uploadProgressDelegate]];
  186 + [request setShouldResetUploadProgress:NO];
  187 + }
  188 +
202 [request setShowAccurateProgress:[self showAccurateProgress]]; 189 [request setShowAccurateProgress:[self showAccurateProgress]];
203 -  
204 190
205 [request setQueue:self]; 191 [request setQueue:self];
206 [super addOperation:request]; 192 [super addOperation:request];
@@ -21,17 +21,18 @@ @@ -21,17 +21,18 @@
21 - (void)setMaxValue:(double)newMax; 21 - (void)setMaxValue:(double)newMax;
22 #endif 22 #endif
23 23
24 -// Called when the request recieves some data - bytes is the length of that data 24 +// Called when the request receives some data - bytes is the length of that data
25 -// bytes may be less than zero if a request needs to remove its progress so far  
26 - (void)request:(ASIHTTPRequest *)request didReceiveBytes:(long long)bytes; 25 - (void)request:(ASIHTTPRequest *)request didReceiveBytes:(long long)bytes;
27 26
28 -// Called when the request sends some data. 27 +// Called when the request sends some data
29 // The first 32KB (128KB on older platforms) of data sent is not included in this amount because of limitations with the CFNetwork API 28 // The first 32KB (128KB on older platforms) of data sent is not included in this amount because of limitations with the CFNetwork API
  29 +// bytes may be less than zero if a request needs to remove upload progress (probably because the request needs to run again)
30 - (void)request:(ASIHTTPRequest *)request didSendBytes:(long long)bytes; 30 - (void)request:(ASIHTTPRequest *)request didSendBytes:(long long)bytes;
31 31
32 // Called when a request needs to change the length of the content to download 32 // Called when a request needs to change the length of the content to download
33 - (void)request:(ASIHTTPRequest *)request incrementDownloadSizeBy:(long long)newLength; 33 - (void)request:(ASIHTTPRequest *)request incrementDownloadSizeBy:(long long)newLength;
34 34
35 // Called when a request needs to change the length of the content to upload 35 // Called when a request needs to change the length of the content to upload
  36 +// newLength may be less than zero when a request needs to remove the size of the internal buffer from progress tracking
36 - (void)request:(ASIHTTPRequest *)request incrementUploadSizeBy:(long long)newLength; 37 - (void)request:(ASIHTTPRequest *)request incrementUploadSizeBy:(long long)newLength;
37 @end 38 @end
@@ -182,7 +182,10 @@ IMPORTANT @@ -182,7 +182,10 @@ IMPORTANT
182 BOOL success = (progress == 1.0); 182 BOOL success = (progress == 1.0);
183 GHAssertTrue(success,@"Failed to increment progress properly"); 183 GHAssertTrue(success,@"Failed to increment progress properly");
184 184
185 - [networkQueue cancelAllOperations]; 185 + [networkQueue reset];
  186 + [networkQueue setDownloadProgressDelegate:self];
  187 + [networkQueue setDelegate:self];
  188 + [networkQueue setQueueDidFinishSelector:@selector(queueFinished:)];
186 189
187 // This test will request gzipped content, but the content-length header we get on the HEAD request will be wrong, ASIHTTPRequest should fall back to simple progress 190 // This test will request gzipped content, but the content-length header we get on the HEAD request will be wrong, ASIHTTPRequest should fall back to simple progress
188 // This is to workaround an issue Apache has with HEAD requests for dynamically generated content when accepting gzip - it returns the content-length of a gzipped empty body 191 // This is to workaround an issue Apache has with HEAD requests for dynamically generated content when accepting gzip - it returns the content-length of a gzipped empty body
@@ -210,14 +213,13 @@ IMPORTANT @@ -210,14 +213,13 @@ IMPORTANT
210 [self setAddMoreRequestsQueue:[ASINetworkQueue queue]]; 213 [self setAddMoreRequestsQueue:[ASINetworkQueue queue]];
211 [[self addMoreRequestsQueue] setDownloadProgressDelegate:self]; 214 [[self addMoreRequestsQueue] setDownloadProgressDelegate:self];
212 [[self addMoreRequestsQueue] setDelegate:self]; 215 [[self addMoreRequestsQueue] setDelegate:self];
213 - [[self addMoreRequestsQueue] setShowAccurateProgress:NO]; 216 + [[self addMoreRequestsQueue] setShowAccurateProgress:YES];
214 [[self addMoreRequestsQueue]setQueueDidFinishSelector:@selector(addMoreRequestsQueueFinished:)]; 217 [[self addMoreRequestsQueue]setQueueDidFinishSelector:@selector(addMoreRequestsQueueFinished:)];
215 218
216 requestsFinishedCount = 0; 219 requestsFinishedCount = 0;
217 220
218 complete = NO; 221 complete = NO;
219 progress = 0; 222 progress = 0;
220 - [[self addMoreRequestsQueue] setShowAccurateProgress:YES];  
221 223
222 int i; 224 int i;
223 for (i=0; i<5; i++) { 225 for (i=0; i<5; i++) {
@@ -311,13 +313,18 @@ IMPORTANT @@ -311,13 +313,18 @@ IMPORTANT
311 [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.25]]; 313 [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.25]];
312 } 314 }
313 [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:1]]; 315 [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:1]];
314 - BOOL success = (progress > 0.95); 316 + BOOL success = (progress == 1.0f);
315 GHAssertTrue(success,@"Failed to increment progress properly"); 317 GHAssertTrue(success,@"Failed to increment progress properly");
316 318
317 //Now test again with accurate progress 319 //Now test again with accurate progress
318 complete = NO; 320 complete = NO;
319 progress = 0; 321 progress = 0;
320 - [networkQueue cancelAllOperations]; 322 + [networkQueue reset];
  323 + [networkQueue setUploadProgressDelegate:self];
  324 + [networkQueue setDelegate:self];
  325 + [networkQueue setShowAccurateProgress:NO];
  326 + [networkQueue setRequestDidFailSelector:@selector(uploadFailed:)];
  327 + [networkQueue setQueueDidFinishSelector:@selector(queueFinished:)];
321 [networkQueue setShowAccurateProgress:YES]; 328 [networkQueue setShowAccurateProgress:YES];
322 329
323 for (i=0; i<3; i++) { 330 for (i=0; i<3; i++) {
@@ -335,7 +342,7 @@ IMPORTANT @@ -335,7 +342,7 @@ IMPORTANT
335 [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.25]]; 342 [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.25]];
336 } 343 }
337 [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:1]]; 344 [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:1]];
338 - success = (progress > 0.95); 345 + success = (progress == 1.0f);
339 GHAssertTrue(success,@"Failed to increment progress properly"); 346 GHAssertTrue(success,@"Failed to increment progress properly");
340 347
341 } 348 }
@@ -709,7 +716,7 @@ IMPORTANT @@ -709,7 +716,7 @@ IMPORTANT
709 success = (amountDownloaded == 1036935); 716 success = (amountDownloaded == 1036935);
710 GHAssertTrue(success,@"Failed to complete the download"); 717 GHAssertTrue(success,@"Failed to complete the download");
711 718
712 - success = (progress > 0.95); 719 + success = (progress == 1.0f);
713 GHAssertTrue(success,@"Failed to increment progress properly"); 720 GHAssertTrue(success,@"Failed to increment progress properly");
714 721
715 722
@@ -1112,6 +1119,10 @@ IMPORTANT @@ -1112,6 +1119,10 @@ IMPORTANT
1112 1119
1113 - (void)testQueueFinishedCalledOnFailure 1120 - (void)testQueueFinishedCalledOnFailure
1114 { 1121 {
  1122 + [self performSelectorOnMainThread:@selector(runTestQueueFinishedCalledOnFailureTest) withObject:nil waitUntilDone:YES];
  1123 +}
  1124 +- (void)runTestQueueFinishedCalledOnFailureTest
  1125 +{
1115 complete = NO; 1126 complete = NO;
1116 ASINetworkQueue *networkQueue = [[ASINetworkQueue queue] retain]; 1127 ASINetworkQueue *networkQueue = [[ASINetworkQueue queue] retain];
1117 [networkQueue setDelegate:self]; 1128 [networkQueue setDelegate:self];
@@ -1136,7 +1147,9 @@ IMPORTANT @@ -1136,7 +1147,9 @@ IMPORTANT
1136 1147
1137 queueFinishedCallCount = 0; 1148 queueFinishedCallCount = 0;
1138 complete = NO; 1149 complete = NO;
1139 - [networkQueue reset]; 1150 +
  1151 + [networkQueue release];
  1152 + networkQueue = [[ASINetworkQueue queue] retain];
1140 [networkQueue setDelegate:self]; 1153 [networkQueue setDelegate:self];
1141 [networkQueue setQueueDidFinishSelector:@selector(queueFailureFinishCallOnce:)]; 1154 [networkQueue setQueueDidFinishSelector:@selector(queueFailureFinishCallOnce:)];
1142 [networkQueue setMaxConcurrentOperationCount:1]; 1155 [networkQueue setMaxConcurrentOperationCount:1];
@@ -1150,7 +1163,7 @@ IMPORTANT @@ -1150,7 +1163,7 @@ IMPORTANT
1150 1163
1151 dateStarted = [NSDate date]; 1164 dateStarted = [NSDate date];
1152 while (!complete) { 1165 while (!complete) {
1153 - [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.5]]; 1166 + [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:2.0f]];
1154 if ([dateStarted timeIntervalSinceNow] < -10) { 1167 if ([dateStarted timeIntervalSinceNow] < -10) {
1155 break; 1168 break;
1156 } 1169 }