Skip to content

Commit

Permalink
fix issue with clearing loading queue prematurely
Browse files Browse the repository at this point in the history
  • Loading branch information
norsez committed Aug 22, 2012
1 parent cbda243 commit 97608e9
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 41 deletions.
16 changes: 0 additions & 16 deletions Classes/BDMultiDownloader.h
Expand Up @@ -98,23 +98,7 @@
*/ */
@property (nonatomic, assign) BOOL pause; @property (nonatomic, assign) BOOL pause;


/**
Call this method to cancel all pending completion blocks and receive
their original connections. These returned connections are specific to this class.
They can be re-added back to the connection queue with -queueConnections:.
@return requests whose completions haven't been executed.
*/
- (NSArray*)removePendingConnections;


/**
Queue a list of requests to the connection queue.
The input requests must be NSURLConnection list returned
from -removePendingConnections.
@param connections a list of NSURLConnection returned from -removePendingConnections
*/
- (void)queueConnections:(NSArray*)connections;






Expand Down
93 changes: 68 additions & 25 deletions Classes/BDMultiDownloader.m
Expand Up @@ -21,7 +21,7 @@
// prior written permission. // prior written permission.
// //
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
Expand All @@ -37,6 +37,11 @@
#define kIntervalDefaultTimeout 60 #define kIntervalDefaultTimeout 60
#define kMaxNumberOfThreads 25 #define kMaxNumberOfThreads 25
#define kMaxCache 10 * 1024 * 1000 #define kMaxCache 10 * 1024 * 1000

#define BDMDKeyRequest @"BDMDKeyRequest"
#define BDMDKeyCompletion @"BDMDKeyCompletion"


NSString* const BDMultiDownloaderMethodPOST = @"POST"; NSString* const BDMultiDownloaderMethodPOST = @"POST";


@interface BDURLConnection : NSURLConnection{ @interface BDURLConnection : NSURLConnection{
Expand All @@ -47,6 +52,7 @@ @interface BDURLConnection : NSURLConnection{
@property (nonatomic, assign) long long expectedLength; @property (nonatomic, assign) long long expectedLength;
@property (nonatomic, strong) NSString *MIMEType; @property (nonatomic, strong) NSString *MIMEType;
@property (nonatomic, strong) NSString *suggestedFilename; @property (nonatomic, strong) NSString *suggestedFilename;
@property (nonatomic, strong) NSURLRequest* originalRequest;
- (id)copyWithZone:(NSZone*)zone; - (id)copyWithZone:(NSZone*)zone;
@end @end


Expand All @@ -60,6 +66,7 @@ - (id)copyWithZone:(NSZone *)zone
@synthesize expectedLength; @synthesize expectedLength;
@synthesize progress; @synthesize progress;
@synthesize suggestedFilename; @synthesize suggestedFilename;
@synthesize originalRequest;
@end @end




Expand Down Expand Up @@ -191,9 +198,8 @@ - (void)dequeueWithPath:(NSString *)path
if (searchResults.count > 0) { if (searchResults.count > 0) {
BDURLConnection *connection = [searchResults objectAtIndex:0]; BDURLConnection *connection = [searchResults objectAtIndex:0];
[connection cancel]; [connection cancel];
[_loadingQueue removeObject:connection.originalRequest]; [self _removeConnection:connection];
[_currentConnectionsData removeObjectForKey:connection];
[_requestCompletions removeObjectForKey:connection];
} }
} }


Expand Down Expand Up @@ -222,20 +228,23 @@ - (NSUInteger)numberOfItemsInQueue


- (void)launchNextConnection - (void)launchNextConnection
{ {
//DLog(@"launchNextConnection…");
if (self.pause){ if (self.pause){
return; return;
} }


if (_currentConnections.count >= self.maximumNumberOfThreads) { if (_currentConnections.count >= self.maximumNumberOfThreads) {
////DLog(@"Threads at Max. Abort."); // DLog(@"Threads at Max. Abort.");
return; return;
} }


if (self.numberOfItemsInQueue==0) { if (self.numberOfItemsInQueue==0) {
////DLog(@"Nothing in queue."); // DLog(@"Nothing in queue.");
return; return;
} }


// DLog(@"still in queue: %d", self.numberOfItemsInQueue);

NSURLRequest *request = [_loadingQueue objectAtIndex:0]; NSURLRequest *request = [_loadingQueue objectAtIndex:0];
[_loadingQueue removeObjectAtIndex:0]; [_loadingQueue removeObjectAtIndex:0];


Expand All @@ -251,6 +260,7 @@ - (void)launchNextConnection
} }


BDURLConnection *conn = [[BDURLConnection alloc] initWithRequest:request delegate:self]; BDURLConnection *conn = [[BDURLConnection alloc] initWithRequest:request delegate:self];
conn.originalRequest = request;
conn.suggestedFilename = request.URL.lastPathComponent; conn.suggestedFilename = request.URL.lastPathComponent;
[_currentConnections addObject:conn]; [_currentConnections addObject:conn];


Expand Down Expand Up @@ -296,21 +306,46 @@ - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
self.onDownloadProgressWithProgressAndSuggestedFilename(conn.progress, conn.suggestedFilename); self.onDownloadProgressWithProgressAndSuggestedFilename(conn.progress, conn.suggestedFilename);
} }
} }

- (void)_removeConnection:(BDURLConnection*)conn
{

__block NSUInteger indexToRemove = NSNotFound;
[_loadingQueue enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
NSURLRequest *req = obj;
if ([req.URL.absoluteString isEqualToString:conn.originalRequest.URL.absoluteString]){
indexToRemove = idx;
*stop = YES;
}
}];



if (indexToRemove!=NSNotFound) {
[_loadingQueue removeObjectAtIndex:indexToRemove];
}

[_currentConnections removeObject:conn];
[_currentConnectionsData removeObjectForKey:conn];
[_requestCompletions removeObjectForKey:conn];


}

- (void)connectionDidFinishLoading:(NSURLConnection *)connection - (void)connectionDidFinishLoading:(NSURLConnection *)connection
{ {
if (self.onNetworkActivity) { if (self.onNetworkActivity) {
self.onNetworkActivity(NO); self.onNetworkActivity(NO);
} }


[_currentConnections removeObject:connection];
NSData *data = [_currentConnectionsData objectForKey:connection]; NSData *data = [_currentConnectionsData objectForKey:connection];
BDURLConnection *conn = (BDURLConnection*) connection; BDURLConnection *conn = (BDURLConnection*) connection;
NSString *requestKey = conn.originalRequest.requestId; NSString *requestKey = conn.originalRequest.requestId;
if (data.length > 0){ if (data.length > 0){
[_dataCache setObject:data forKey:requestKey cost:data.length]; [_dataCache setObject:data forKey:requestKey cost:data.length];
} }
[_currentConnectionsData removeObjectForKey:connection]; [self _removeConnection:conn];
[_loadingQueue removeObject:conn.originalRequest];
void(^completion)(NSData*) = [(BDURLConnection*)connection completionWithDownloadedData]; void(^completion)(NSData*) = [(BDURLConnection*)connection completionWithDownloadedData];


if (completion) { if (completion) {
Expand All @@ -322,7 +357,9 @@ - (void)connectionDidFinishLoading:(NSURLConnection *)connection
completion(data); completion(data);
} }


} }

// DLog(@"still in queue %d", self.numberOfItemsInQueue);


[self launchNextConnection]; [self launchNextConnection];
} }
Expand All @@ -333,17 +370,14 @@ -(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)erro
self.onNetworkActivity(NO); self.onNetworkActivity(NO);
} }


[_currentConnections removeObject:connection]; [self _removeConnection:(BDURLConnection*)connection];
[_currentConnectionsData removeObjectForKey:connection];
[_loadingQueue removeObject:connection.originalRequest];

if ([error.domain isEqualToString:NSURLErrorDomain] ) { if ([error.domain isEqualToString:NSURLErrorDomain] ) {
[self clearQueue]; [self clearQueue];
if (self.onNetworkError) { if (self.onNetworkError) {
self.onNetworkError(error); self.onNetworkError(error);
} }
} }

// DLog(@"still in queue %d", self.numberOfItemsInQueue);
[self launchNextConnection]; [self launchNextConnection];


} }
Expand Down Expand Up @@ -380,24 +414,33 @@ - (void)setPause:(BOOL)pause
} }
} }


- (NSArray *)removePendingConnections - (NSArray *)_removePendingRequestsAndCompletions
{ {
self.pause = YES; self.pause = YES;
NSArray *result = [_currentConnections copy]; NSArray *result = [NSArray array];
for (BDURLConnection *conn in _currentConnections) {
NSURLRequest *req = conn.originalRequest;
if (req) {
id completion = [_requestCompletions objectForKey:conn.originalRequest.requestId];

NSDictionary *requestAndCompletion = [NSDictionary dictionaryWithObjectsAndKeys:
req, BDMDKeyRequest,
completion, BDMDKeyCompletion,
nil];
result = [result arrayByAddingObject:requestAndCompletion];
}
}
[self clearQueue]; [self clearQueue];
self.pause = NO; self.pause = NO;
return result; return result;
} }


- (void)queueConnections:(NSArray *)connections - (void)_queueRequestsWithCompletions:(NSArray*)requestsAndCompletions
{ {
for (BDURLConnection *conn in connections){ for (NSDictionary * info in requestsAndCompletions){
if(![conn isKindOfClass:[BDURLConnection class]]){ NSURLRequest *r = [info objectForKey:BDMDKeyRequest];
//not our kind of connection, skip void(^completion)(NSData*) = [info objectForKey:BDMDKeyCompletion];
continue; [self queueURLRequest:r completion:completion];
}
NSURLRequest * request = conn.originalRequest;
[self queueURLRequest:request completion:conn.completionWithDownloadedData];
} }
} }


Expand Down

0 comments on commit 97608e9

Please sign in to comment.