Ben Copsey

Refactor to fix lots of bugs, especially locking issues

... ... @@ -50,6 +50,11 @@
- (void)buildPostBody
{
if (!postData && ! fileData) {
[super buildPostBody];
return;
}
NSMutableData *body = [[[NSMutableData alloc] init] autorelease];
// Set your own boundary string only if really obsessive. We don't bother to check if post data contains the boundary, since it's pretty unlikely that it does.
... ...
... ... @@ -10,6 +10,7 @@
// Portions are based on the ImageClient example from Apple:
// See: http://developer.apple.com/samplecode/ImageClient/listing37.html
#import <Cocoa/Cocoa.h>
@interface ASIHTTPRequest : NSOperation {
... ... @@ -93,18 +94,18 @@
int responseStatusCode;
//Size of the response
unsigned int contentLength;
unsigned long long contentLength;
//Size of the POST payload
unsigned int postLength;
unsigned long long postLength;
//The total amount of downloaded data
unsigned int totalBytesRead;
unsigned long long totalBytesRead;
//Last amount of data read (used for incrementing progress)
unsigned int lastBytesRead;
unsigned long long lastBytesRead;
//Last amount of data sent (used for incrementing progress)
unsigned int lastBytesSent;
unsigned long long lastBytesSent;
//Realm for authentication when credentials are required
NSString *authenticationRealm;
... ... @@ -112,6 +113,9 @@
//This lock will block the request until the delegate supplies authentication info
NSConditionLock *authenticationLock;
//This lock prevents the operation from being cancelled at an inopportune moment
NSLock *cancelledLock;
//Called on the delegate when the request completes successfully
SEL didFinishSelector;
... ... @@ -128,7 +132,7 @@
NSAutoreleasePool *pool;
// Will be YES when a HEAD request will handle the content-length before this request starts
BOOL useCachedContentLength;
BOOL shouldResetProgressIndicators;
// Used by HEAD requests when showAccurateProgress is YES to preset the content-length for this request
ASIHTTPRequest *mainRequest;
... ... @@ -177,9 +181,9 @@
// Called on main thread to update progress delegates
- (void)updateProgressIndicators;
- (void)resetUploadProgress:(NSNumber *)max;
- (void)resetUploadProgress:(unsigned long long)value;
- (void)updateUploadProgress;
- (void)resetDownloadProgress:(NSNumber *)max;
- (void)resetDownloadProgress:(unsigned long long)value;
- (void)updateDownloadProgress;
// Called when authorisation is needed, as we only find out we don't have permission to something when the upload is complete
... ... @@ -279,10 +283,10 @@
@property (assign) NSTimeInterval timeOutSeconds;
@property (retain) NSString *requestMethod;
@property (retain,setter=setPostBody:) NSData *postBody;
@property (assign) unsigned int contentLength;
@property (assign) unsigned int postLength;
@property (assign) BOOL useCachedContentLength;
@property (assign) unsigned long long contentLength;
@property (assign) unsigned long long postLength;
@property (assign) BOOL shouldResetProgressIndicators;
@property (retain) ASIHTTPRequest *mainRequest;
@property (assign) BOOL showAccurateProgress;
@property (assign,readonly) unsigned int totalBytesRead;
@property (assign,readonly) unsigned long long totalBytesRead;
@end
... ...
... ... @@ -33,7 +33,7 @@ static void ReadStreamClientCallBack(CFReadStreamRef readStream, CFStreamEventTy
}
// This lock prevents the operation from being cancelled while it is trying to update the progress, and vice versa
static NSLock *progressLock;
static NSRecursiveLock *progressLock;
@implementation ASIHTTPRequest
... ... @@ -41,9 +41,9 @@ static NSLock *progressLock;
#pragma mark init / dealloc
- (void)initialize
+ (void)initialize
{
progressLock = [[NSLock alloc] init];
progressLock = [[NSRecursiveLock alloc] init];
}
- (id)initWithURL:(NSURL *)newURL
... ... @@ -52,7 +52,7 @@ static NSLock *progressLock;
[self setRequestMethod:@"GET"];
lastBytesSent = 0;
showAccurateProgress = YES;
useCachedContentLength = NO;
shouldResetProgressIndicators = YES;
updatedProgress = NO;
mainRequest = nil;
username = nil;
... ... @@ -74,6 +74,7 @@ static NSLock *progressLock;
didFailSelector = @selector(requestFailed:);
delegate = nil;
url = [newURL retain];
cancelledLock = [[NSLock alloc] init];
return self;
}
... ... @@ -105,6 +106,7 @@ static NSLock *progressLock;
[receivedData release];
[responseHeaders release];
[requestMethod release];
[cancelledLock release];
[super dealloc];
}
... ... @@ -143,17 +145,15 @@ static NSLock *progressLock;
return complete;
}
- (void)cancel
{
[progressLock lock];
[self failWithProblem:@"The request was cancelled"];
[self cancelLoad];
complete = YES;
[super cancel];
[progressLock unlock];
}
- (int)totalBytesRead
{
return totalBytesRead;
}
// Call this method to get the recieved data as an NSString. Don't use for Binary data!
- (NSString *)dataString
... ... @@ -226,9 +226,9 @@ static NSLock *progressLock;
CFHTTPMessageSetHeaderFieldValue(request, (CFStringRef)header, (CFStringRef)[requestHeaders objectForKey:header]);
}
//NSData *d = (NSData *)CFHTTPMessageCopySerializedMessage(request);
//NSLog(@"%@",[[[NSString alloc] initWithBytes:[d bytes] length:[d length] encoding:NSUTF8StringEncoding] autorelease]);
// If this is a post request and we have data to send, add it to the request
if ([self postBody]) {
... ... @@ -243,6 +243,13 @@ static NSLock *progressLock;
// Start the request
- (void)loadRequest
{
[cancelledLock lock];
if ([self isCancelled]) {
[cancelledLock unlock];
return;
}
CFRunLoopAddCommonMode(CFRunLoopGetCurrent(),ASIHTTPRequestRunMode);
[authenticationLock release];
... ... @@ -258,7 +265,7 @@ static NSLock *progressLock;
}
lastBytesSent = 0;
if (!useCachedContentLength) {
if (shouldResetProgressIndicators) {
contentLength = 0;
}
[self setResponseHeaders:nil];
... ... @@ -267,6 +274,7 @@ static NSLock *progressLock;
// Create the stream for the request.
readStream = CFReadStreamCreateForStreamedHTTPRequest(kCFAllocatorDefault, request,readStream);
if (!readStream) {
[cancelledLock unlock];
[self failWithProblem:@"Unable to create read stream"];
return;
}
... ... @@ -276,6 +284,7 @@ static NSLock *progressLock;
if (!CFReadStreamSetClient(readStream, kNetworkEvents, ReadStreamClientCallBack, &ctxt)) {
CFRelease(readStream);
readStream = NULL;
[cancelledLock unlock];
[self failWithProblem:@"Unable to setup read stream"];
return;
}
... ... @@ -289,14 +298,23 @@ static NSLock *progressLock;
CFReadStreamUnscheduleFromRunLoop(readStream, CFRunLoopGetCurrent(), ASIHTTPRequestRunMode);
CFRelease(readStream);
readStream = NULL;
[cancelledLock unlock];
[self failWithProblem:@"Unable to start http connection"];
return;
}
[cancelledLock unlock];
if (uploadProgressDelegate) {
[self performSelectorOnMainThread:@selector(resetUploadProgress:) withObject:[NSNumber numberWithDouble:postLength] waitUntilDone:YES];
if (uploadProgressDelegate && shouldResetProgressIndicators) {
double amount = 1;
if (showAccurateProgress) {
amount = postLength;
}
[self resetUploadProgress:amount];
}
// Record when the request started, so we can timeout if nothing happens
[self setLastActivityTime:[NSDate date]];
... ... @@ -307,9 +325,11 @@ static NSLock *progressLock;
[pool release];
pool = [[NSAutoreleasePool alloc] init];
NSDate *now = [NSDate new];
// See if we need to timeout
if (lastActivityTime && timeOutSeconds > 0) {
if ([[NSDate date] timeIntervalSinceDate:lastActivityTime] > timeOutSeconds) {
if ([now timeIntervalSinceDate:lastActivityTime] > timeOutSeconds) {
[self failWithProblem:@"Request timed out"];
[self cancelLoad];
complete = YES;
... ... @@ -324,10 +344,12 @@ static NSLock *progressLock;
complete = YES;
break;
}
[self performSelectorOnMainThread:@selector(updateProgressIndicators) withObject:nil waitUntilDone:YES];
[self updateProgressIndicators];
//This thread should wait for 1/4 second for the stream to do something. We'll stop early if it does.
CFRunLoopRunInMode(ASIHTTPRequestRunMode,0.25,YES);
[now release];
}
[pool release];
... ... @@ -337,6 +359,7 @@ static NSLock *progressLock;
// Cancel loading and clean up
- (void)cancelLoad
{
[cancelledLock lock];
if (readStream) {
CFReadStreamClose(readStream);
CFReadStreamSetClient(readStream, kCFStreamEventNone, NULL, NULL);
... ... @@ -355,6 +378,7 @@ static NSLock *progressLock;
}
[self setResponseHeaders:nil];
[cancelledLock unlock];
}
... ... @@ -364,9 +388,9 @@ static NSLock *progressLock;
- (void)updateProgressIndicators
{
//Only update progress if this isn't a HEAD request used to preset the content-length
if (!mainRequest) {
if (showAccurateProgress || (complete && !updatedProgress)) {
[self updateUploadProgress];
[self updateDownloadProgress];
... ... @@ -411,17 +435,11 @@ static NSLock *progressLock;
}
- (void)resetUploadProgress:(NSNumber *)max
- (void)resetUploadProgress:(unsigned long long)value
{
[progressLock lock];
if ([self isCancelled]) {
[progressLock unlock];
return;
}
//We're using a progress queue or compatible controller to handle progress
if ([uploadProgressDelegate respondsToSelector:@selector(incrementUploadSizeBy:)]) {
int value = [max intValue];
SEL selector = @selector(incrementUploadSizeBy:);
NSMethodSignature *signature = [[uploadProgressDelegate class] instanceMethodSignatureForSelector:selector];
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
... ... @@ -437,20 +455,21 @@ static NSLock *progressLock;
- (void)updateUploadProgress
{
[progressLock lock];
[cancelledLock lock];
if ([self isCancelled]) {
[progressLock unlock];
return;
}
unsigned long long byteCount = [[(NSNumber *)CFReadStreamCopyProperty (readStream, kCFStreamPropertyHTTPRequestBytesWrittenCount) autorelease] unsignedLongLongValue];
[cancelledLock unlock];
if (byteCount > lastBytesSent) {
[self setLastActivityTime:[NSDate date]];
}
[self setLastActivityTime:[NSDate date]];
unsigned int byteCount = [[(NSNumber *)CFReadStreamCopyProperty (readStream, kCFStreamPropertyHTTPRequestBytesWrittenCount) autorelease] unsignedIntValue];
if (uploadProgressDelegate) {
//We're using a progress queue or compatible controller to handle progress
if ([uploadProgressDelegate respondsToSelector:@selector(incrementUploadProgressBy:)]) {
int value = 0;
unsigned long long value = 0;
if (showAccurateProgress) {
value = byteCount-lastBytesSent;
} else {
... ... @@ -473,22 +492,15 @@ static NSLock *progressLock;
}
lastBytesSent = byteCount;
[progressLock unlock];
}
- (void)resetDownloadProgress:(NSNumber *)max
- (void)resetDownloadProgress:(unsigned long long)value
{
[progressLock lock];
if ([self isCancelled]) {
[progressLock unlock];
return;
}
[progressLock lock];
//We're using a progress queue or compatible controller to handle progress
if ([downloadProgressDelegate respondsToSelector:@selector(incrementDownloadSizeBy:)]) {
int value = [max intValue];
SEL selector = @selector(incrementDownloadSizeBy:);
NSMethodSignature *signature = [[downloadProgressDelegate class] instanceMethodSignatureForSelector:selector];
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
... ... @@ -496,6 +508,7 @@ static NSLock *progressLock;
[invocation setSelector:selector];
[invocation setArgument:&value atIndex:2];
[invocation invoke];
} else {
[ASIHTTPRequest setProgress:0 forProgressIndicator:downloadProgressDelegate];
}
... ... @@ -504,62 +517,61 @@ static NSLock *progressLock;
- (void)updateDownloadProgress
{
[progressLock lock];
if ([self isCancelled]) {
[progressLock unlock];
return;
}
[self setLastActivityTime:[NSDate date]];
unsigned long long bytesReadSoFar = totalBytesRead;
//We won't update downlaod progress until we've examined the headers, since we might need to authenticate
if (downloadProgressDelegate && responseHeaders) {
//We won't update download progress until we've examined the headers, since we might need to authenticate
if (responseHeaders) {
if (bytesReadSoFar > lastBytesRead) {
[self setLastActivityTime:[NSDate date]];
}
if (downloadProgressDelegate) {
//We're using a progress queue or compatible controller to handle progress
if ([downloadProgressDelegate respondsToSelector:@selector(incrementDownloadProgressBy:)]) {
NSAutoreleasePool *thePool = [[NSAutoreleasePool alloc] init];
int value = 0;
if (showAccurateProgress) {
value = totalBytesRead-lastBytesRead;
} else {
value = 1;
updatedProgress = YES;
//We're using a progress queue or compatible controller to handle progress
if ([downloadProgressDelegate respondsToSelector:@selector(incrementDownloadProgressBy:)]) {
NSAutoreleasePool *thePool = [[NSAutoreleasePool alloc] init];
unsigned long long value = 0;
if (showAccurateProgress) {
value = bytesReadSoFar-lastBytesRead;
} else {
value = 1;
updatedProgress = YES;
}
SEL selector = @selector(incrementDownloadProgressBy:);
NSMethodSignature *signature = [[downloadProgressDelegate class] instanceMethodSignatureForSelector:selector];
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
[invocation setTarget:downloadProgressDelegate];
[invocation setSelector:selector];
[invocation setArgument:&value atIndex:2];
[invocation invoke];
[thePool release];
//We aren't using a queue, we should just set progress of the indicator to 0
} else if (contentLength > 0) {
[ASIHTTPRequest setProgress:(double)(bytesReadSoFar/contentLength) forProgressIndicator:downloadProgressDelegate];
}
SEL selector = @selector(incrementDownloadProgressBy:);
NSMethodSignature *signature = [[downloadProgressDelegate class] instanceMethodSignatureForSelector:selector];
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
[invocation setTarget:downloadProgressDelegate];
[invocation setSelector:selector];
[invocation setArgument:&value atIndex:2];
[invocation invoke];
[thePool release];
//We aren't using a queue, we should just set progress of the indicator to 0
} else if (contentLength > 0) {
[ASIHTTPRequest setProgress:(double)(totalBytesRead/contentLength) forProgressIndicator:downloadProgressDelegate];
}
lastBytesRead = totalBytesRead;
lastBytesRead = bytesReadSoFar;
}
[progressLock unlock];
}
-(void)removeUploadProgressSoFar
{
[progressLock lock];
if ([self isCancelled]) {
[progressLock unlock];
return;
}
//We're using a progress queue or compatible controller to handle progress
if ([uploadProgressDelegate respondsToSelector:@selector(incrementUploadProgressBy:)]) {
int value = 0-lastBytesSent;
SEL selector = @selector(incrementUploadProgressBy:);
if ([uploadProgressDelegate respondsToSelector:@selector(decrementUploadProgressBy:)]) {
unsigned long long value = 0-lastBytesSent;
SEL selector = @selector(decrementUploadProgressBy:);
NSMethodSignature *signature = [[uploadProgressDelegate class] instanceMethodSignatureForSelector:selector];
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
[invocation setTarget:uploadProgressDelegate];
... ... @@ -571,7 +583,6 @@ static NSLock *progressLock;
} else {
[ASIHTTPRequest setProgress:0 forProgressIndicator:uploadProgressDelegate];
}
[progressLock unlock];
}
... ... @@ -579,8 +590,9 @@ static NSLock *progressLock;
{
SEL selector;
[progressLock lock];
//Cocoa Touch: UIProgressView
// Cocoa Touch: UIProgressView
if ([indicator respondsToSelector:@selector(setProgress:)]) {
selector = @selector(setProgress:);
NSMethodSignature *signature = [[indicator class] instanceMethodSignatureForSelector:selector];
... ... @@ -590,26 +602,28 @@ static NSLock *progressLock;
[invocation setArgument:&progressFloat atIndex:2];
[invocation invokeWithTarget:indicator];
//If we're running in the main thread, update the progress straight away. Otherwise, it's not that urgent
[invocation performSelectorOnMainThread:@selector(invokeWithTarget:) withObject:indicator waitUntilDone:[NSThread isMainThread]];
//Cocoa: NSProgressIndicator
// Cocoa: NSProgressIndicator
} else if ([indicator respondsToSelector:@selector(setDoubleValue:)]) {
selector = @selector(setDoubleValue:);
NSMethodSignature *signature = [[indicator class] instanceMethodSignatureForSelector:selector];
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
[invocation setSelector:selector];
[invocation setArgument:&progress atIndex:2];
[invocation invokeWithTarget:indicator];
//Progress indicator is some other thing that we can't handle
} else {
return;
//If we're running in the main thread, update the progress straight away. Otherwise, it's not that urgent
[invocation performSelectorOnMainThread:@selector(invokeWithTarget:) withObject:indicator waitUntilDone:[NSThread isMainThread]];
}
[progressLock unlock];
}
#pragma mark handling request complete / failure
// Subclasses can override this method to process the result in the same thread
// If not overidden, it will call the didFinishSelector on the delegate, if one has been setup
- (void)requestFinished
... ... @@ -656,18 +670,15 @@ static NSLock *progressLock;
//We won't reset the download progress delegate if we got an authentication challenge
if (!isAuthenticationChallenge) {
//Only check the content length if we haven't already got one (may have been set by an ASINetworkQueue using a previous HEAD request)
if (!useCachedContentLength) {
//See if we got a Content-length header
NSString *cLength = [responseHeaders valueForKey:@"Content-Length"];
if (cLength) {
contentLength = CFStringGetDoubleValue((CFStringRef)cLength);
if (mainRequest) {
[mainRequest setContentLength:contentLength];
}
if (downloadProgressDelegate && showAccurateProgress) {
[self performSelectorOnMainThread:@selector(resetDownloadProgress:) withObject:[NSNumber numberWithDouble:contentLength] waitUntilDone:YES];
}
//See if we got a Content-length header
NSString *cLength = [responseHeaders valueForKey:@"Content-Length"];
if (cLength) {
contentLength = CFStringGetIntValue((CFStringRef)cLength);
if (mainRequest) {
[mainRequest setContentLength:contentLength];
}
if (downloadProgressDelegate && showAccurateProgress && shouldResetProgressIndicators) {
[self resetDownloadProgress:contentLength];
}
}
... ... @@ -940,11 +951,14 @@ static NSLock *progressLock;
[receivedData appendBytes:buffer length:bytesRead];
}
}
}
- (void)handleStreamComplete
{
//Try to read the headers (if this is a HEAD request handleBytesAvailable available may not be called)
if (!responseHeaders) {
... ... @@ -953,10 +967,10 @@ static NSLock *progressLock;
return;
}
}
[progressLock lock];
complete = YES;
[self updateProgressIndicators];
[self updateProgressIndicators];
if (readStream) {
CFReadStreamClose(readStream);
CFReadStreamSetClient(readStream, kCFStreamEventNone, NULL, NULL);
... ... @@ -969,8 +983,9 @@ static NSLock *progressLock;
if (downloadDestinationPath) {
[outputStream close];
}
[progressLock unlock];
[self requestFinished];
}
... ... @@ -1101,7 +1116,9 @@ static NSLock *progressLock;
@synthesize postBody;
@synthesize contentLength;
@synthesize postLength;
@synthesize useCachedContentLength;
@synthesize shouldResetProgressIndicators;
@synthesize mainRequest;
@synthesize totalBytesRead;
@synthesize showAccurateProgress;
@synthesize totalBytesRead;
@end
... ...
... ... @@ -109,8 +109,9 @@
ASIHTTPRequest *request = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease];
[request setDownloadProgressDelegate:self];
[request start];
BOOL success = (progress == 1);
STAssertTrue(success,@"Failed to properly increment download progress");
STAssertTrue(success,@"Failed to properly increment download progress %f != 1.0",progress);
}
... ... @@ -121,8 +122,9 @@
[request setPostBody:[NSMutableData dataWithLength:1024*32]];
[request setUploadProgressDelegate:self];
[request start];
BOOL success = (progress == 1);
STAssertTrue(success,@"Failed to properly increment upload progress");
STAssertTrue(success,@"Failed to properly increment upload progress %f != 1.0",progress);
}
... ...
... ... @@ -6,7 +6,7 @@
// Copyright 2008 All-Seeing Interactive. All rights reserved.
//
#import <Cocoa/Cocoa.h>
@interface ASINetworkQueue : NSOperationQueue {
... ... @@ -26,19 +26,19 @@
id uploadProgressDelegate;
// Total amount uploaded so far for all requests in this queue
unsigned int uploadProgressBytes;
unsigned long long uploadProgressBytes;
// Total amount to be uploaded for all requests in this queue - requests add to this figure as they work out how much data they have to transmit
unsigned int uploadProgressTotalBytes;
unsigned long long uploadProgressTotalBytes;
// Download progress indicator, probably an NSProgressIndicator or UIProgressView
id downloadProgressDelegate;
// Total amount downloaded so far for all requests in this queue
unsigned int downloadProgressBytes;
unsigned long long downloadProgressBytes;
// Total amount to be downloaded for all requests in this queue - requests add to this figure as they receive Content-Length headers
unsigned int downloadProgressTotalBytes;
unsigned long long downloadProgressTotalBytes;
// When YES, the queue will cancel all requests when a request fails. Default is YES
BOOL shouldCancelAllRequestsOnFailure;
... ... @@ -61,16 +61,19 @@
- (void)addHEADOperation:(NSOperation *)operation;
// Called at the start of a request to add on the size of this upload to the total
- (void)incrementUploadSizeBy:(int)bytes;
- (void)incrementUploadSizeBy:(unsigned long long)bytes;
// Called during a request when data is written to the upload stream to increment the progress indicator
- (void)incrementUploadProgressBy:(int)bytes;
- (void)incrementUploadProgressBy:(unsigned long long)bytes;
// Called at the start of a request to add on the size of this download to the total
- (void)incrementDownloadSizeBy:(int)bytes;
- (void)incrementDownloadSizeBy:(unsigned long long)bytes;
// Called during a request when data is received to increment the progress indicator
- (void)incrementDownloadProgressBy:(int)bytes;
- (void)incrementDownloadProgressBy:(unsigned long long)bytes;
// Called during a request when authorisation fails to cancel any progress so far
- (void)decrementUploadProgressBy:(unsigned long long)bytes;
// All ASINetworkQueues are paused when created so that total size can be calculated before the queue starts
// This method will start the queue
... ...
... ... @@ -34,6 +34,7 @@
showAccurateProgress = NO;
[self setMaxConcurrentOperationCount:4];
[self setSuspended:YES];
return self;
... ... @@ -59,9 +60,6 @@
uploadProgressTotalBytes = 0;
downloadProgressBytes = 0;
downloadProgressTotalBytes = 0;
[self setUploadProgressDelegate:nil];
[self setDownloadProgressDelegate:nil];
[self setDelegate:nil];
[super cancelAllOperations];
}
... ... @@ -103,6 +101,8 @@
if ([operation isKindOfClass:[ASIHTTPRequest class]]) {
ASIHTTPRequest *request = (ASIHTTPRequest *)operation;
[request setRequestMethod:@"HEAD"];
[request setQueuePriority:10];
[request setShowAccurateProgress:YES];
if (uploadProgressDelegate) {
[request setUploadProgressDelegate:self];
... ... @@ -133,12 +133,11 @@
//If this is a GET request and we want accurate progress, perform a HEAD request first to get the content-length
if ([[request requestMethod] isEqualToString:@"GET"]) {
ASIHTTPRequest *HEADRequest = [[[ASIHTTPRequest alloc] initWithURL:[request url]] autorelease];
[HEADRequest setRequestMethod:@"HEAD"];
[HEADRequest setQueuePriority:10];
[HEADRequest setMainRequest:request];
[self addHEADOperation:HEADRequest];
[request setUseCachedContentLength:YES];
//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
[request setShouldResetProgressIndicators:NO];
[request addDependency:HEADRequest];
//If we want to track uploading for this request accurately, we need to add the size of the post content to the total
... ... @@ -150,6 +149,9 @@
[request setShowAccurateProgress:showAccurateProgress];
if (uploadProgressDelegate) {
//For uploads requests, we always work out the total upload size before the queue starts, so we tell the request not to reset the progress indicator when starting each request
[request setShouldResetProgressIndicators:NO];
[request setUploadProgressDelegate:self];
} else {
[request setUploadProgressDelegate:NULL];
... ... @@ -173,7 +175,7 @@
if (requestDidFailSelector) {
[delegate performSelector:requestDidFailSelector withObject:request];
}
if (shouldCancelAllRequestsOnFailure) {
if (shouldCancelAllRequestsOnFailure && requestsCount > 0) {
[self cancelAllOperations];
}
}
... ... @@ -191,7 +193,7 @@
}
}
- (void)incrementUploadSizeBy:(int)bytes
- (void)incrementUploadSizeBy:(unsigned long long)bytes
{
if (!uploadProgressDelegate) {
return;
... ... @@ -200,7 +202,19 @@
[self incrementUploadProgressBy:0];
}
- (void)incrementUploadProgressBy:(int)bytes
- (void)decrementUploadProgressBy:(unsigned long long)bytes
{
if (!uploadProgressDelegate || uploadProgressTotalBytes == 0) {
return;
}
uploadProgressBytes -= bytes;
double progress = (uploadProgressBytes*1.0)/(uploadProgressTotalBytes*1.0);
[ASIHTTPRequest setProgress:progress forProgressIndicator:uploadProgressDelegate];
}
- (void)incrementUploadProgressBy:(unsigned long long)bytes
{
if (!uploadProgressDelegate || uploadProgressTotalBytes == 0) {
return;
... ... @@ -209,24 +223,26 @@
double progress = (uploadProgressBytes*1.0)/(uploadProgressTotalBytes*1.0);
[ASIHTTPRequest setProgress:progress forProgressIndicator:uploadProgressDelegate];
}
- (void)incrementDownloadSizeBy:(int)bytes
- (void)incrementDownloadSizeBy:(unsigned long long)bytes
{
if (!downloadProgressDelegate) {
return;
}
downloadProgressTotalBytes += bytes;
[self incrementDownloadProgressBy:0];
NSLog(@"download size is now: %qu",downloadProgressTotalBytes);
}
- (void)incrementDownloadProgressBy:(int)bytes
- (void)incrementDownloadProgressBy:(unsigned long long)bytes
{
if (!downloadProgressDelegate || downloadProgressTotalBytes == 0) {
return;
}
downloadProgressBytes += bytes;
//NSLog(@"%hu/%hu",downloadProgressBytes,downloadProgressTotalBytes);
//NSLog(@"%qu/%qu",downloadProgressBytes,downloadProgressTotalBytes);
double progress = (downloadProgressBytes*1.0)/(downloadProgressTotalBytes*1.0);
[ASIHTTPRequest setProgress:progress forProgressIndicator:downloadProgressDelegate];
}
... ...
... ... @@ -201,8 +201,6 @@
- (void)requestFailedCancellingOthers:(ASIHTTPRequest *)request
{
BOOL success = (request == requestThatShouldFail);
STAssertTrue(success,@"Wrong request failed");
complete = YES;
}
... ...