self.storedLocalObjectStates = [NSMutableDictionary dictionary];
}
- queue = [[ASINetworkQueue alloc] init];
- queue.showAccurateProgress = YES;
- queue.shouldCancelAllRequestsOnFailure = NO;
- [queue go];
+ networkQueue = [[ASINetworkQueue alloc] init];
+ networkQueue.showAccurateProgress = YES;
+ networkQueue.shouldCancelAllRequestsOnFailure = NO;
+ [networkQueue go];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(applicationWillTerminate:)
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
- [queue cancelAllOperations];
- [queue release];
+ [networkQueue cancelAllOperations];
+ [networkQueue release];
[timer invalidate];
[timer release];
[tempTrashDirPath release];
}
#pragma mark -
+#pragma mark Background
+
+- (void)fileActionFailedAlert:(NSDictionary *)args {
+ [PithosUtilities fileActionFailedAlertWithTitle:[args objectForKey:@"title"]
+ message:[args objectForKey:@"message"]
+ error:[args objectForKey:@"error"]];
+}
+
+- (void)fileActionFailedAlertWithTitle:(NSString *)title
+ message:(NSString *)message
+ error:(NSError *)error {
+ NSMutableDictionary *args = [NSMutableDictionary dictionaryWithObjectsAndKeys:
+ title, @"title",
+ message, @"message",
+ nil];
+ if (error)
+ [args setObject:error forKey:@"error"];
+ [self performSelectorOnMainThread:@selector(fileActionFailedAlert:)
+ withObject:args
+ waitUntilDone:YES];
+}
+
+- (void)startAndEndActivity:(NSDictionary *)args {
+ [activityFacility startAndEndActivityWithType:[[args objectForKey:@"type"] intValue] message:[args objectForKey:@"message"]];
+}
+
+- (void)startAndEndActivityWithType:(PithosActivityType)type message:(NSString *)message {
+ NSDictionary *args = [NSDictionary dictionaryWithObjectsAndKeys:
+ [NSNumber numberWithInt:type], @"type",
+ message, @"message",
+ nil];
+ [self performSelectorOnMainThread:@selector(startAndEndActivity:)
+ withObject:args
+ waitUntilDone:YES];
+}
+
+- (void)updateActivity:(NSDictionary *)args {
+ NSNumber *totalBytesNumber = [args objectForKey:@"totalBytes"];
+ NSNumber *currentBytesNumber = [args objectForKey:@"currentBytes"];
+ if (totalBytesNumber && currentBytesNumber)
+ [activityFacility updateActivity:[args objectForKey:@"activity"]
+ withMessage:[args objectForKey:@"message"]
+ totalBytes:[totalBytesNumber unsignedIntegerValue]
+ currentBytes:[currentBytesNumber unsignedIntegerValue]];
+ else
+ [activityFacility updateActivity:[args objectForKey:@"activity"]
+ withMessage:[args objectForKey:@"message"]];
+}
+
+- (void)updateActivity:(PithosActivity *)activity
+ withMessage:(NSString *)message
+ totalBytes:(NSUInteger)totalBytes
+ currentBytes:(NSUInteger)currentBytes {
+ NSMutableDictionary *args = [NSMutableDictionary dictionaryWithObjectsAndKeys:
+ activity, @"activity",
+ [NSNumber numberWithUnsignedInteger:totalBytes], @"totalBytes",
+ [NSNumber numberWithUnsignedInteger:currentBytes], @"currentBytes",
+ nil];
+ if (message)
+ [args setObject:message forKey:@"message"];
+ [self performSelectorOnMainThread:@selector(updateActivity:)
+ withObject:args
+ waitUntilDone:YES];
+}
+
+- (void)updateActivity:(PithosActivity *)activity withMessage:(NSString *)message {
+ NSMutableDictionary *args = [NSMutableDictionary dictionaryWithObjectsAndKeys:
+ activity, @"activity",
+ nil];
+ if (message)
+ [args setObject:message forKey:@"message"];
+ [self performSelectorOnMainThread:@selector(updateActivity:)
+ withObject:args
+ waitUntilDone:YES];
+}
+
+- (void)endActivity:(NSDictionary *)args {
+ NSNumber *totalBytesNumber = [args objectForKey:@"totalBytes"];
+ NSNumber *currentBytesNumber = [args objectForKey:@"currentBytes"];
+ if (totalBytesNumber && currentBytesNumber)
+ [activityFacility endActivity:[args objectForKey:@"activity"]
+ withMessage:[args objectForKey:@"message"]
+ totalBytes:[totalBytesNumber unsignedIntegerValue]
+ currentBytes:[currentBytesNumber unsignedIntegerValue]];
+ else
+ [activityFacility endActivity:[args objectForKey:@"activity"]
+ withMessage:[args objectForKey:@"message"]];
+}
+
+- (void)endActivity:(PithosActivity *)activity
+ withMessage:(NSString *)message
+ totalBytes:(NSUInteger)totalBytes
+ currentBytes:(NSUInteger)currentBytes {
+ NSMutableDictionary *args = [NSMutableDictionary dictionaryWithObjectsAndKeys:
+ activity, @"activity",
+ [NSNumber numberWithUnsignedInteger:totalBytes], @"totalBytes",
+ [NSNumber numberWithUnsignedInteger:currentBytes], @"currentBytes",
+ nil];
+ if (message)
+ [args setObject:message forKey:@"message"];
+ [self performSelectorOnMainThread:@selector(endActivity:)
+ withObject:args
+ waitUntilDone:YES];
+}
+
+- (void)endActivity:(PithosActivity *)activity withMessage:(NSString *)message {
+ NSMutableDictionary *args = [NSMutableDictionary dictionaryWithObjectsAndKeys:
+ activity, @"activity",
+ nil];
+ if (message)
+ [args setObject:message forKey:@"message"];
+ [self performSelectorOnMainThread:@selector(endActivity:)
+ withObject:args
+ waitUntilDone:YES];
+}
+
+#pragma mark -
#pragma mark Observers
- (void)applicationWillTerminate:(NSNotification *)notification {
- (NSString *)pithosStateFilePath {
if (!pithosStateFilePath)
pithosStateFilePath = [[[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"PithosLocalObjectStates.archive"] retain];
- return [pithosStateFilePath copy];
+ return [[pithosStateFilePath copy] autorelease];
}
- (NSString *)tempDownloadsDirPath {
[userDefaults setObject:tempDownloadsDirPath forKey:@"PithosSyncTempDownloadsDirPath"];
[tempDownloadsDirPath retain];
}
- return [tempDownloadsDirPath copy];
+ return [[tempDownloadsDirPath copy] autorelease];
}
- (NSString *)tempTrashDirPath {
[userDefaults setObject:tempTrashDirPath forKey:@"PithosSyncTempTrashDirPath"];
[tempTrashDirPath retain];
}
- return [tempTrashDirPath copy];
+ return [[tempTrashDirPath copy] autorelease];
}
#pragma mark -
if (!syncOperationCount) {
if (!syncIncomplete) {
self.lastCompletedSync = [NSDate date];
- [activityFacility startAndEndActivityWithType:PithosActivityOther
- message:[NSString stringWithFormat:@"Sync: Completed %@", lastCompletedSync]];
+ [self startAndEndActivityWithType:PithosActivityOther
+ message:[NSString stringWithFormat:@"Sync: Completed %@", lastCompletedSync]];
}
[self emptyTempTrash];
}
until:nil
ifModifiedSince:lastModified];
containerRequest.delegate = self;
- containerRequest.didFinishSelector = @selector(listRequestFinished:);
- containerRequest.didFailSelector = @selector(listRequestFailed:);
+ containerRequest.didFinishSelector = @selector(performRequestFinishedDelegateInBackground:);
+ containerRequest.didFailSelector = @selector(performRequestFailedDelegateInBackground:);
PithosActivity *activity = [activityFacility startActivityWithType:PithosActivityOther
message:@"Sync: Getting server listing"];
containerRequest.userInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys:
@"Sync: Getting server listing (finished)", @"finishedActivityMessage",
[NSNumber numberWithInteger:NSOperationQueuePriorityVeryHigh], @"priority",
[NSNumber numberWithUnsignedInteger:10], @"retries",
+ NSStringFromSelector(@selector(listRequestFinished:)), @"didFinishSelector",
+ NSStringFromSelector(@selector(listRequestFailed:)), @"didFailSelector",
nil];
- [queue addOperation:[PithosUtilities prepareRequest:containerRequest priority:NSOperationQueuePriorityVeryHigh]];
+ [networkQueue addOperation:[PithosUtilities prepareRequest:containerRequest priority:NSOperationQueuePriorityVeryHigh]];
}
- (void)emptyTempTrash {
// NSArray *subPaths = [[NSFileManager defaultManager] subpathsOfDirectoryAtPath:trashDirPath error:&error];
NSArray *subPaths = [fileManager contentsOfDirectoryAtPath:trashDirPath error:&error];
if (error) {
- [PithosUtilities fileActionFailedAlertWithTitle:@"Directory Contents Error"
- message:[NSString stringWithFormat:@"Cannot get contents of directory at '%@'", containerDirectoryPath]
- error:error];
+ [self fileActionFailedAlertWithTitle:@"Directory Contents Error"
+ message:[NSString stringWithFormat:@"Cannot get contents of directory at '%@'", containerDirectoryPath]
+ error:error];
return;
}
if ([subPaths count]) {
// syncOperationCount = 1;
// [[NSWorkspace sharedWorkspace] recycleURLs:subURLs completionHandler:^(NSDictionary *newURLs, NSError *error) {
// if (error) {
-// [PithosUtilities fileActionFailedAlertWithTitle:@"Move to Trash Error"
-// message:@"Cannot move files to Trash"
-// error:error];
+// [self fileActionFailedAlertWithTitle:@"Move to Trash Error"
+// message:@"Cannot move files to Trash"
+// error:error];
// }
// syncOperationCount = 0;
// }];
NSString *subFilePath = [trashDirPath stringByAppendingPathComponent:subPath];
error = nil;
if (![fileManager removeItemAtPath:subFilePath error:&error] || error)
- [PithosUtilities fileActionFailedAlertWithTitle:@"Remove File Error"
- message:[NSString stringWithFormat:@"Cannot remove file at '%@'", subFilePath]
- error:error];
+ [self fileActionFailedAlertWithTitle:@"Remove File Error"
+ message:[NSString stringWithFormat:@"Cannot remove file at '%@'", subFilePath]
+ error:error];
}
}
}
if (fileExists && isDirectory) {
NSArray *subPaths = [fileManager subpathsOfDirectoryAtPath:filePath error:&error];
if (error) {
- [PithosUtilities fileActionFailedAlertWithTitle:@"Directory Contents Error"
- message:[NSString stringWithFormat:@"Cannot get contents of directory at '%@'", containerDirectoryPath]
- error:error];
+ [self fileActionFailedAlertWithTitle:@"Directory Contents Error"
+ message:[NSString stringWithFormat:@"Cannot get contents of directory at '%@'", containerDirectoryPath]
+ error:error];
return NO;
}
if (![fileManager createDirectoryAtPath:newDirPath withIntermediateDirectories:YES attributes:nil error:&error] || error) {
- [PithosUtilities fileActionFailedAlertWithTitle:@"Create Directory Error"
- message:[NSString stringWithFormat:@"Cannot create directory at '%@'", newDirPath]
- error:error];
+ [self fileActionFailedAlertWithTitle:@"Create Directory Error"
+ message:[NSString stringWithFormat:@"Cannot create directory at '%@'", newDirPath]
+ error:error];
return NO;
}
if (![fileManager moveItemAtPath:filePath toPath:newFilePath error:&error] || error) {
- [PithosUtilities fileActionFailedAlertWithTitle:@"Move File Error"
- message:[NSString stringWithFormat:@"Cannot move file at '%@' to '%@'",
- filePath, newFilePath]
- error:error];
+ [self fileActionFailedAlertWithTitle:@"Move File Error"
+ message:[NSString stringWithFormat:@"Cannot move file at '%@' to '%@'",
+ filePath, newFilePath]
+ error:error];
return NO;
}
PithosLocalObjectState *currentState = [currentLocalObjectStates objectForKey:filePath];
}
} else if (fileExists && !isDirectory) {
if (![fileManager createDirectoryAtPath:newDirPath withIntermediateDirectories:YES attributes:nil error:&error] || error) {
- [PithosUtilities fileActionFailedAlertWithTitle:@"Create Directory Error"
- message:[NSString stringWithFormat:@"Cannot create directory at '%@'", newDirPath]
- error:error];
+ [self fileActionFailedAlertWithTitle:@"Create Directory Error"
+ message:[NSString stringWithFormat:@"Cannot create directory at '%@'", newDirPath]
+ error:error];
return NO;
}
if (![fileManager moveItemAtPath:filePath toPath:newFilePath error:&error] || error) {
- [PithosUtilities fileActionFailedAlertWithTitle:@"Move File Error"
- message:[NSString stringWithFormat:@"Cannot move file at '%@' to '%@'",
- filePath, newFilePath]
- error:error];
+ [self fileActionFailedAlertWithTitle:@"Move File Error"
+ message:[NSString stringWithFormat:@"Cannot move file at '%@' to '%@'",
+ filePath, newFilePath]
+ error:error];
return NO;
}
PithosLocalObjectState *currentState = [currentLocalObjectStates objectForKey:filePath];
[fileManager fileExistsAtPath:localFilePath isDirectory:&isDirectory] && !isDirectory) {
if ([localFilePath hasPrefix:containerDirectoryPath]) {
if (![fileManager copyItemAtPath:localFilePath toPath:filePath error:&error] || error) {
- [PithosUtilities fileActionFailedAlertWithTitle:@"Copy File Error"
- message:[NSString stringWithFormat:@"Cannot copy file at '%@' to '%@'",
- localFilePath, filePath]
- error:error];
+ [self fileActionFailedAlertWithTitle:@"Copy File Error"
+ message:[NSString stringWithFormat:@"Cannot copy file at '%@' to '%@'",
+ localFilePath, filePath]
+ error:error];
} else {
return YES;
}
} else if (self.tempTrashDirPath && [localFilePath hasPrefix:self.tempTrashDirPath]) {
if (![fileManager moveItemAtPath:localFilePath toPath:filePath error:&error] || error) {
- [PithosUtilities fileActionFailedAlertWithTitle:@"Move File Error"
- message:[NSString stringWithFormat:@"Cannot move file at '%@' to '%@'",
- localFilePath, filePath]
- error:error];
+ [self fileActionFailedAlertWithTitle:@"Move File Error"
+ message:[NSString stringWithFormat:@"Cannot move file at '%@' to '%@'",
+ localFilePath, filePath]
+ error:error];
} else {
localState.filePath = filePath;
[currentLocalObjectStates setObject:localState forKey:filePath];
// Delete local object
NSLog(@"Sync::delete local object: %@", filePath);
if (!fileExists || [self moveToTempTrashFile:filePath]) {
- [activityFacility startAndEndActivityWithType:PithosActivityOther
- message:[NSString stringWithFormat:@"Sync: Deleting '%@' locally (finished)", object.name]];
+ [self startAndEndActivityWithType:PithosActivityOther
+ message:[NSString stringWithFormat:@"Sync: Deleting '%@' locally (finished)", object.name]];
[storedLocalObjectStates removeObjectForKey:object.name];
[self saveLocalState];
}
NSLog(@"Sync::local directory object doesn't exist: %@", filePath);
error = nil;
if (![fileManager createDirectoryAtPath:filePath withIntermediateDirectories:YES attributes:nil error:&error] || error) {
- [PithosUtilities fileActionFailedAlertWithTitle:@"Create Directory Error"
- message:[NSString stringWithFormat:@"Cannot create directory at '%@'", filePath]
- error:error];
+ [self fileActionFailedAlertWithTitle:@"Create Directory Error"
+ message:[NSString stringWithFormat:@"Cannot create directory at '%@'", filePath]
+ error:error];
} else {
directoryCreated = YES;
storedState.isDirectory = YES;
directoryCreated = YES;
}
if (directoryCreated)
- [activityFacility startAndEndActivityWithType:PithosActivityOther
- message:[NSString stringWithFormat:@"Sync: Creating directory '%@' locally (finished)", object.name]];
+ [self startAndEndActivityWithType:PithosActivityOther
+ message:[NSString stringWithFormat:@"Sync: Creating directory '%@' locally (finished)", object.name]];
} else if (object.bytes == 0) {
// Create local object with zero length
NSLog(@"Sync::create local zero length object: %@", filePath);
NSLog(@"Sync::local zero length object doesn't exist: %@", filePath);
error = nil;
if (![fileManager createFileAtPath:filePath contents:nil attributes:nil]) {
- [PithosUtilities fileActionFailedAlertWithTitle:@"Create File Error"
- message:[NSString stringWithFormat:@"Cannot create file at '%@'", filePath]
- error:error];
+ [self fileActionFailedAlertWithTitle:@"Create File Error"
+ message:[NSString stringWithFormat:@"Cannot create file at '%@'", filePath]
+ error:error];
} else {
fileCreated = YES;
storedState.hash = object.hash;
fileCreated = YES;
}
if (fileCreated)
- [activityFacility startAndEndActivityWithType:PithosActivityOther
- message:[NSString stringWithFormat:@"Sync: Downloading '%@' (100%%)", object.name]];
+ [self startAndEndActivityWithType:PithosActivityOther
+ message:[NSString stringWithFormat:@"Sync: Downloading '%@' (100%%)", object.name]];
} else if (storedState.filePath == nil) {
// Create new local object
// Check first if a local copy exists
if ([self findLocalCopyForObjectWithHash:object.hash forFile:filePath]) {
- [activityFacility startAndEndActivityWithType:PithosActivityOther
- message:[NSString stringWithFormat:@"Sync: Downloading '%@' (100%%)", object.name]];
+ [self startAndEndActivityWithType:PithosActivityOther
+ message:[NSString stringWithFormat:@"Sync: Downloading '%@' (100%%)", object.name]];
} else {
[self increaseSyncOperationCount];
__block ASIPithosObjectRequest *objectRequest = [PithosUtilities objectBlockDataRequestWithContainerName:containerName
blockIndex:0
blockSize:blockSize];
objectRequest.delegate = self;
- objectRequest.didFinishSelector = @selector(downloadObjectBlockFinished:);
- objectRequest.didFailSelector = @selector(requestFailed:);
+ objectRequest.didFinishSelector = @selector(performRequestFinishedDelegateInBackground:);
+ objectRequest.didFailSelector = @selector(performRequestFailedDelegateInBackground:);
PithosActivity *activity = [activityFacility startActivityWithType:PithosActivityDownload
message:[NSString stringWithFormat:@"Sync: Downloading '%@' (0%%)", object.name]
totalBytes:object.bytes
currentBytes:0];
+ [self updateActivity:activity withMessage:activity.message];
objectRequest.userInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys:
object, @"pithosObject",
[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, (NSUInteger)ceil((object.bytes +0.0)/(blockSize + 0.0)))], @"missingBlocks",
[NSString stringWithFormat:@"Sync: Downloading '%@' (100%%)", object.name], @"finishedActivityMessage",
[NSNumber numberWithInteger:NSOperationQueuePriorityNormal], @"priority",
[NSNumber numberWithUnsignedInteger:10], @"retries",
+ NSStringFromSelector(@selector(downloadObjectBlockFinished:)), @"didFinishSelector",
+ NSStringFromSelector(@selector(requestFailed:)), @"didFailSelector",
nil];
[objectRequest setBytesReceivedBlock:^(unsigned long long size, unsigned long long total){
[activityFacility updateActivity:activity
totalBytes:activity.totalBytes
currentBytes:(activity.currentBytes + size)];
}];
- [queue addOperation:[PithosUtilities prepareRequest:objectRequest priority:NSOperationQueuePriorityNormal]];
+ [networkQueue addOperation:[PithosUtilities prepareRequest:objectRequest priority:NSOperationQueuePriorityNormal]];
}
} else {
// Resume local object download
// Check first if a local copy exists
if ([self findLocalCopyForObjectWithHash:object.hash forFile:filePath]) {
- [activityFacility startAndEndActivityWithType:PithosActivityOther
- message:[NSString stringWithFormat:@"Sync: Downloading '%@' (100%%)", object.name]];
+ [self startAndEndActivityWithType:PithosActivityOther
+ message:[NSString stringWithFormat:@"Sync: Downloading '%@' (100%%)", object.name]];
// Delete incomplete temp download
error = nil;
if (![fileManager removeItemAtPath:storedState.filePath error:&error] || error) {
- [PithosUtilities fileActionFailedAlertWithTitle:@"Remove File Error"
- message:[NSString stringWithFormat:@"Cannot remove file at '%@'", storedState.filePath]
- error:error];
+ [self fileActionFailedAlertWithTitle:@"Remove File Error"
+ message:[NSString stringWithFormat:@"Cannot remove file at '%@'", storedState.filePath]
+ error:error];
}
} else {
[self increaseSyncOperationCount];
ASIPithosObjectRequest *objectRequest = [ASIPithosObjectRequest objectHashmapRequestWithContainerName:containerName
objectName:object.name];
objectRequest.delegate = self;
- objectRequest.didFinishSelector = @selector(downloadObjectHashMapFinished:);
- // The fail method for block download does exactly what we want
- objectRequest.didFailSelector = @selector(requestFailed:);
+ objectRequest.didFinishSelector = @selector(performRequestFinishedDelegateInBackground:);
+ objectRequest.didFailSelector = @selector(performRequestFailedDelegateInBackground:);
PithosActivity *activity = [activityFacility startActivityWithType:PithosActivityDownload
message:[NSString stringWithFormat:@"Sync: Downloading '%@' (0%%)", object.name]
totalBytes:object.bytes
currentBytes:0];
+ [self updateActivity:activity withMessage:activity.message];
objectRequest.userInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys:
object, @"pithosObject",
filePath, @"filePath",
[NSString stringWithFormat:@"Sync: Downloading '%@' (100%%)", object.name], @"finishedActivityMessage",
[NSNumber numberWithInteger:NSOperationQueuePriorityNormal], @"priority",
[NSNumber numberWithUnsignedInteger:10], @"retries",
+ NSStringFromSelector(@selector(downloadObjectHashMapFinished:)), @"didFinishSelector",
+ NSStringFromSelector(@selector(requestFailed:)), @"didFailSelector",
nil];
- [queue addOperation:[PithosUtilities prepareRequest:objectRequest priority:NSOperationQueuePriorityNormal]];
+ [networkQueue addOperation:[PithosUtilities prepareRequest:objectRequest priority:NSOperationQueuePriorityNormal]];
}
}
}
object:(ASIPithosObject *)object
localFilePath:(NSString *)filePath {
[self increaseSyncOperationCount];
+ NSFileManager *fileManager = [NSFileManager defaultManager];
+ BOOL isDirectory;
+ BOOL fileExists = [fileManager fileExistsAtPath:filePath isDirectory:&isDirectory];
if (currentState.isDirectory) {
// Create remote directory object
+ if (!fileExists || !isDirectory) {
+ // Local directory object deleted or changed to a file in the meantime, mark the sync cycle as incomplete and skip
+ syncIncomplete = YES;
+ [self decreaseSyncOperationCount];
+ return;
+ }
ASIPithosObjectRequest *objectRequest = [ASIPithosObjectRequest writeObjectDataRequestWithContainerName:containerName
objectName:object.name
eTag:nil
metadata:nil
data:[NSData data]];
objectRequest.delegate = self;
- objectRequest.didFinishSelector = @selector(uploadDirectoryObjectFinished:);
- objectRequest.didFailSelector = @selector(requestFailed:);
+ objectRequest.didFinishSelector = @selector(performRequestFinishedDelegateInBackground:);
+ objectRequest.didFailSelector = @selector(performRequestFailedDelegateInBackground:);
PithosActivity *activity = [activityFacility startActivityWithType:PithosActivityCreateDirectory
message:[NSString stringWithFormat:@"Sync: Creating directory '%@'", object.name]];
+ [self updateActivity:activity withMessage:activity.message];
objectRequest.userInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys:
object, @"pithosObject",
activity, @"activity",
[NSString stringWithFormat:@"Sync: Creating directory '%@' (finished)", object.name], @"finishedActivityMessage",
[NSNumber numberWithInteger:NSOperationQueuePriorityHigh], @"priority",
[NSNumber numberWithUnsignedInteger:10], @"retries",
+ NSStringFromSelector(@selector(uploadDirectoryObjectFinished:)), @"didFinishSelector",
+ NSStringFromSelector(@selector(requestFailed:)), @"didFailSelector",
nil];
- [queue addOperation:[PithosUtilities prepareRequest:objectRequest priority:NSOperationQueuePriorityHigh]];
+ [networkQueue addOperation:[PithosUtilities prepareRequest:objectRequest priority:NSOperationQueuePriorityHigh]];
} else if (!currentState.exists) {
// Delete remote object
+ if (fileExists) {
+ // Local object created in the meantime, just mark the sync cycle as incomplete, but do delete the server object
+ syncIncomplete = YES;
+ }
NSString *safeObjectName = [PithosUtilities safeObjectNameForContainerName:@"trash"
objectName:object.name];
if (safeObjectName) {
checkIfExists:NO];
if (objectRequest) {
objectRequest.delegate = self;
- objectRequest.didFinishSelector = @selector(moveObjectToTrashFinished:);
- objectRequest.didFailSelector = @selector(requestFailed:);
+ objectRequest.didFinishSelector = @selector(performRequestFinishedDelegateInBackground:);
+ objectRequest.didFailSelector = @selector(performRequestFailedDelegateInBackground:);
PithosActivity *activity = [activityFacility startActivityWithType:PithosActivityDelete
message:[NSString stringWithFormat:@"Sync: Moving to trash '%@'", object.name]];
+ [self updateActivity:activity withMessage:activity.message];
objectRequest.userInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys:
object, @"pithosObject",
activity, @"activity",
[NSString stringWithFormat:@"Sync: Moving to trash '%@' (finished)", object.name], @"finishedActivityMessage",
[NSNumber numberWithInteger:NSOperationQueuePriorityHigh], @"priority",
[NSNumber numberWithUnsignedInteger:10], @"retries",
+ NSStringFromSelector(@selector(moveObjectToTrashFinished:)), @"didFinishSelector",
+ NSStringFromSelector(@selector(requestFailed:)), @"didFailSelector",
nil];
- [queue addOperation:[PithosUtilities prepareRequest:objectRequest priority:NSOperationQueuePriorityHigh]];
+ [networkQueue addOperation:[PithosUtilities prepareRequest:objectRequest priority:NSOperationQueuePriorityHigh]];
} else {
syncIncomplete = YES;
[self decreaseSyncOperationCount];
}
} else {
// Upload file to remote object
+ if (!fileExists || isDirectory) {
+ // Local file object deleted or changed to a directory in the meantime, mark the sync cycle as incomplete and skip
+ syncIncomplete = YES;
+ [self decreaseSyncOperationCount];
+ return;
+ }
NSError *error = nil;
object.contentType = [PithosUtilities contentTypeOfFile:filePath error:&error];
if (object.contentType == nil)
sharingAccount:nil];
if (objectRequest) {
objectRequest.delegate = self;
- objectRequest.didFinishSelector = @selector(uploadObjectUsingHashMapFinished:);
- objectRequest.didFailSelector = @selector(requestFailed:);
+ objectRequest.didFinishSelector = @selector(performRequestFinishedDelegateInBackground:);
+ objectRequest.didFailSelector = @selector(performRequestFailedDelegateInBackground:);
PithosActivity *activity = [activityFacility startActivityWithType:PithosActivityUpload
message:[NSString stringWithFormat:@"Sync: Uploading '%@' (0%%)", object.name]
totalBytes:[[objectRequest.userInfo valueForKey:@"bytes"] unsignedIntegerValue]
currentBytes:0];
+ [self updateActivity:activity withMessage:activity.message];
[(NSMutableDictionary *)objectRequest.userInfo addEntriesFromDictionary:
[NSDictionary dictionaryWithObjectsAndKeys:
object, @"pithosObject",
[NSString stringWithFormat:@"Sync: Uploading '%@' (100%%)", object.name], @"finishedActivityMessage",
[NSNumber numberWithInteger:NSOperationQueuePriorityNormal], @"priority",
[NSNumber numberWithUnsignedInteger:10], @"retries",
+ NSStringFromSelector(@selector(uploadObjectUsingHashMapFinished:)), @"didFinishSelector",
+ NSStringFromSelector(@selector(requestFailed:)), @"didFailSelector",
nil]];
- [queue addOperation:[PithosUtilities prepareRequest:objectRequest priority:NSOperationQueuePriorityNormal]];
+ [networkQueue addOperation:[PithosUtilities prepareRequest:objectRequest priority:NSOperationQueuePriorityNormal]];
} else {
syncIncomplete = YES;
[self decreaseSyncOperationCount];
#pragma mark -
#pragma mark ASIHTTPRequestDelegate
+- (void)performRequestFinishedDelegateInBackground:(ASIPithosRequest *)request {
+ [self performSelectorInBackground:NSSelectorFromString([request.userInfo objectForKey:@"didFinishSelector"]) withObject:request];
+}
+
+- (void)performRequestFailedDelegateInBackground:(ASIPithosRequest *)request {
+ [self performSelectorInBackground:NSSelectorFromString([request.userInfo objectForKey:@"didFailSelector"]) withObject:request];
+}
+
- (void)listRequestFinished:(ASIPithosContainerRequest *)containerRequest {
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSLog(@"Sync::list request finished: %@", containerRequest.url);
if ((containerRequest.responseStatusCode == 200) || (containerRequest.responseStatusCode == 304)) {
if (containerRequest.responseStatusCode == 200) {
until:nil
ifModifiedSince:lastModified];
newContainerRequest.delegate = self;
- newContainerRequest.didFinishSelector = @selector(listRequestFinished:);
- newContainerRequest.didFailSelector = @selector(listRequestFailed:);
+ newContainerRequest.didFinishSelector = @selector(performRequestFinishedDelegateInBackground:);
+ newContainerRequest.didFailSelector = @selector(performRequestFailedDelegateInBackground:);
newContainerRequest.userInfo = newContainerRequest.userInfo;
[(NSMutableDictionary *)newContainerRequest.userInfo setObject:[NSNumber numberWithUnsignedInteger:10] forKey:@"retries"];
- [queue addOperation:[PithosUtilities prepareRequest:newContainerRequest priority:[[newContainerRequest.userInfo objectForKey:@"priority"] integerValue]]];
+ [networkQueue addOperation:[PithosUtilities prepareRequest:newContainerRequest priority:[[newContainerRequest.userInfo objectForKey:@"priority"] integerValue]]];
return;
}
}
- [activityFacility endActivity:[containerRequest.userInfo objectForKey:@"activity"]
- withMessage:[containerRequest.userInfo objectForKey:@"finishedActivityMessage"]];
+ [self endActivity:[containerRequest.userInfo objectForKey:@"activity"]
+ withMessage:[containerRequest.userInfo objectForKey:@"finishedActivityMessage"]];
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error = nil;
NSArray *subPaths = [fileManager subpathsOfDirectoryAtPath:containerDirectoryPath error:&error];
if (error) {
- [PithosUtilities fileActionFailedAlertWithTitle:@"Directory Contents Error"
- message:[NSString stringWithFormat:@"Cannot get contents of directory at '%@'", containerDirectoryPath]
- error:error];
- [activityFacility startAndEndActivityWithType:PithosActivityOther message:@"Sync: Failed to read contents of sync directory"];
+ [self fileActionFailedAlertWithTitle:@"Directory Contents Error"
+ message:[NSString stringWithFormat:@"Cannot get contents of directory at '%@'", containerDirectoryPath]
+ error:error];
+ [self startAndEndActivityWithType:PithosActivityOther message:@"Sync: Failed to read contents of sync directory"];
@synchronized(self) {
- // Since the local listing failed, the operation finished and the sync cycle is completeted unsuccesfully
+ // Since the local listing failed, the operation finished and the sync cycle is completeted unsuccessfully
syncOperationCount = 0;
if (newSyncRequested)
[self sync];
} else {
NSUInteger retries = [[containerRequest.userInfo objectForKey:@"retries"] unsignedIntegerValue];
if (retries > 0) {
- ASIPithosContainerRequest *newContainerRequest = (ASIPithosContainerRequest *)[PithosUtilities copyRequest:containerRequest];
+ ASIPithosContainerRequest *newContainerRequest = (ASIPithosContainerRequest *)[[PithosUtilities copyRequest:containerRequest] autorelease];
[(NSMutableDictionary *)(newContainerRequest.userInfo)setObject:[NSNumber numberWithUnsignedInteger:(--retries)] forKey:@"retries"];
- [queue addOperation:[PithosUtilities prepareRequest:newContainerRequest priority:[[newContainerRequest.userInfo objectForKey:@"priority"] integerValue]]];
+ [networkQueue addOperation:[PithosUtilities prepareRequest:newContainerRequest priority:[[newContainerRequest.userInfo objectForKey:@"priority"] integerValue]]];
} else {
- [activityFacility endActivity:[containerRequest.userInfo objectForKey:@"activity"]
- withMessage:[containerRequest.userInfo objectForKey:@"failedActivityMessage"]];
+ [self endActivity:[containerRequest.userInfo objectForKey:@"activity"]
+ withMessage:[containerRequest.userInfo objectForKey:@"failedActivityMessage"]];
@synchronized(self) {
// Since the server listing failed in all retries, the operation finished and the sync cycle is completeted unsuccesfully
syncOperationCount = 0;
}
}
}
+ [pool drain];
}
- (void)listRequestFailed:(ASIPithosContainerRequest *)containerRequest {
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
if ([containerRequest isCancelled]) {
- [activityFacility endActivity:[containerRequest.userInfo objectForKey:@"activity"]
- withMessage:[containerRequest.userInfo objectForKey:@"stoppedActivityMessage"]];
+ [self endActivity:[containerRequest.userInfo objectForKey:@"activity"]
+ withMessage:[containerRequest.userInfo objectForKey:@"stoppedActivityMessage"]];
[objects release];
objects = nil;
@synchronized(self) {
// If the server listing fails, the sync should start over, so just retrying is enough
NSUInteger retries = [[containerRequest.userInfo objectForKey:@"retries"] unsignedIntegerValue];
if (retries > 0) {
- ASIPithosContainerRequest *newContainerRequest = (ASIPithosContainerRequest *)[PithosUtilities copyRequest:containerRequest];
+ ASIPithosContainerRequest *newContainerRequest = (ASIPithosContainerRequest *)[[PithosUtilities copyRequest:containerRequest] autorelease];
[(NSMutableDictionary *)(newContainerRequest.userInfo)setObject:[NSNumber numberWithUnsignedInteger:(--retries)] forKey:@"retries"];
- [queue addOperation:[PithosUtilities prepareRequest:newContainerRequest priority:[[newContainerRequest.userInfo objectForKey:@"priority"] integerValue]]];
+ [networkQueue addOperation:[PithosUtilities prepareRequest:newContainerRequest priority:[[newContainerRequest.userInfo objectForKey:@"priority"] integerValue]]];
} else {
- [activityFacility endActivity:[containerRequest.userInfo objectForKey:@"activity"]
- withMessage:[containerRequest.userInfo objectForKey:@"failedActivityMessage"]];
+ [self endActivity:[containerRequest.userInfo objectForKey:@"activity"]
+ withMessage:[containerRequest.userInfo objectForKey:@"failedActivityMessage"]];
[objects release];
objects = nil;
@synchronized(self) {
[self sync];
}
}
+ [pool drain];
}
- (void)downloadObjectBlockFinished:(ASIPithosObjectRequest *)objectRequest {
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSLog(@"Sync::download object block finished: %@", objectRequest.url);
if (objectRequest.responseStatusCode == 206) {
ASIPithosObject *object = [objectRequest.userInfo objectForKey:@"pithosObject"];
NSString *downloadsDirPath = self.tempDownloadsDirPath;
if (!downloadsDirPath) {
- [activityFacility endActivity:activity
- withMessage:[objectRequest.userInfo objectForKey:@"failedActivityMessage"]];
+ [self endActivity:activity
+ withMessage:[objectRequest.userInfo objectForKey:@"failedActivityMessage"]];
@synchronized(self) {
syncIncomplete = YES;
[self decreaseSyncOperationCount];
NSString *tempFilePath = [fileManager stringWithFileSystemRepresentation:tempFileNameCString length:strlen(tempFileNameCString)];
free(tempFileNameCString);
if (fileDescriptor == -1) {
- [PithosUtilities fileActionFailedAlertWithTitle:@"Create Temporary File Error"
- message:[NSString stringWithFormat:@"Cannot create temporary file at '%@'", storedState.filePath]
- error:nil];
- [activityFacility endActivity:activity
- withMessage:[objectRequest.userInfo objectForKey:@"failedActivityMessage"]];
+ [self fileActionFailedAlertWithTitle:@"Create Temporary File Error"
+ message:[NSString stringWithFormat:@"Cannot create temporary file at '%@'", storedState.filePath]
+ error:nil];
+ [self endActivity:activity
+ withMessage:[objectRequest.userInfo objectForKey:@"failedActivityMessage"]];
@synchronized(self) {
syncIncomplete = YES;
[self decreaseSyncOperationCount];
NSString *filePath = [objectRequest.userInfo objectForKey:@"filePath"];
NSString *dirPath = [filePath stringByDeletingLastPathComponent];
if ([fileManager fileExistsAtPath:filePath] && ![self moveToTempTrashFile:filePath]) {
- [activityFacility endActivity:activity
- withMessage:[objectRequest.userInfo objectForKey:@"failedActivityMessage"]];
+ [self endActivity:activity
+ withMessage:[objectRequest.userInfo objectForKey:@"failedActivityMessage"]];
@synchronized(self) {
syncIncomplete = YES;
[self decreaseSyncOperationCount];
error = nil;
[fileManager createDirectoryAtPath:dirPath withIntermediateDirectories:YES attributes:nil error:nil];
if (error != nil) {
- [PithosUtilities fileActionFailedAlertWithTitle:@"Create Directory Error"
- message:[NSString stringWithFormat:@"Cannot create directory at '%@'", dirPath]
- error:error];
- [activityFacility endActivity:[objectRequest.userInfo objectForKey:@"activity"]
- withMessage:[objectRequest.userInfo objectForKey:@"failedActivityMessage"]];
+ [self fileActionFailedAlertWithTitle:@"Create Directory Error"
+ message:[NSString stringWithFormat:@"Cannot create directory at '%@'", dirPath]
+ error:error];
+ [self endActivity:[objectRequest.userInfo objectForKey:@"activity"]
+ withMessage:[objectRequest.userInfo objectForKey:@"failedActivityMessage"]];
@synchronized(self) {
syncIncomplete = YES;
[self decreaseSyncOperationCount];
error = nil;
[fileManager moveItemAtPath:storedState.filePath toPath:filePath error:&error];
if (error != nil) {
- [PithosUtilities fileActionFailedAlertWithTitle:@"Move File Error"
- message:[NSString stringWithFormat:@"Cannot move file at '%@' to '%@'", storedState.filePath, filePath]
- error:error];
- [activityFacility endActivity:activity
- withMessage:[objectRequest.userInfo objectForKey:@"failedActivityMessage"]];
+ [self fileActionFailedAlertWithTitle:@"Move File Error"
+ message:[NSString stringWithFormat:@"Cannot move file at '%@' to '%@'", storedState.filePath, filePath]
+ error:error];
+ [self endActivity:activity
+ withMessage:[objectRequest.userInfo objectForKey:@"failedActivityMessage"]];
@synchronized(self) {
syncIncomplete = YES;
[self decreaseSyncOperationCount];
}
return;
}
- [activityFacility endActivity:activity
- withMessage:[objectRequest.userInfo objectForKey:@"finishedActivityMessage"]
- totalBytes:activity.totalBytes
- currentBytes:activity.totalBytes];
+ [self endActivity:activity
+ withMessage:[objectRequest.userInfo objectForKey:@"finishedActivityMessage"]
+ totalBytes:activity.totalBytes
+ currentBytes:activity.totalBytes];
storedState.hash = object.hash;
storedState.filePath = nil;
return;
} else {
if (newSyncRequested) {
- [activityFacility endActivity:[objectRequest.userInfo objectForKey:@"activity"]
- withMessage:[objectRequest.userInfo objectForKey:@"stoppedActivityMessage"]];
+ [self endActivity:[objectRequest.userInfo objectForKey:@"activity"]
+ withMessage:[objectRequest.userInfo objectForKey:@"stoppedActivityMessage"]];
@synchronized(self) {
syncIncomplete = YES;
[self decreaseSyncOperationCount];
blockIndex:missingBlockIndex
blockSize:blockSize];
newObjectRequest.delegate = self;
- newObjectRequest.didFinishSelector = @selector(downloadObjectBlockFinished:);
- newObjectRequest.didFailSelector = @selector(downloadObjectBlockOrHashMapFailed:);
+ newObjectRequest.didFinishSelector = @selector(performRequestFinishedDelegateInBackground:);
+ newObjectRequest.didFailSelector = @selector(performRequestFailedDelegateInBackground:);
newObjectRequest.userInfo = objectRequest.userInfo;
[(NSMutableDictionary *)(newObjectRequest.userInfo) setObject:[NSNumber numberWithUnsignedInteger:missingBlockIndex] forKey:@"missingBlockIndex"];
[(NSMutableDictionary *)(newObjectRequest.userInfo) setObject:[NSNumber numberWithUnsignedInteger:10] forKey:@"retries"];
totalBytes:activity.totalBytes
currentBytes:(activity.currentBytes + size)];
}];
- [queue addOperation:[PithosUtilities prepareRequest:newObjectRequest priority:[[newObjectRequest.userInfo objectForKey:@"priority"] integerValue]]];
+ [networkQueue addOperation:[PithosUtilities prepareRequest:newObjectRequest priority:[[newObjectRequest.userInfo objectForKey:@"priority"] integerValue]]];
}
}
} else if (objectRequest.responseStatusCode == 412) {
// The object has changed on the server
- [activityFacility endActivity:[objectRequest.userInfo objectForKey:@"activity"]
- withMessage:[objectRequest.userInfo objectForKey:@"stoppedActivityMessage"]];
+ [self endActivity:[objectRequest.userInfo objectForKey:@"activity"]
+ withMessage:[objectRequest.userInfo objectForKey:@"stoppedActivityMessage"]];
@synchronized(self) {
syncIncomplete = YES;
[self decreaseSyncOperationCount];
} else {
[self requestFailed:objectRequest];
}
+ [pool drain];
}
- (void)downloadObjectHashMapFinished:(ASIPithosObjectRequest *)objectRequest {
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSLog(@"Sync::download object hashmap finished: %@", objectRequest.url);
if (objectRequest.responseStatusCode == 200) {
if (newSyncRequested) {
- [activityFacility endActivity:[objectRequest.userInfo objectForKey:@"activity"]
- withMessage:[objectRequest.userInfo objectForKey:@"stoppedActivityMessage"]];
+ [self endActivity:[objectRequest.userInfo objectForKey:@"activity"]
+ withMessage:[objectRequest.userInfo objectForKey:@"stoppedActivityMessage"]];
@synchronized(self) {
syncIncomplete = YES;
[self decreaseSyncOperationCount];
blockHash:blockHash
withHashes:[objectRequest hashes]];
NSUInteger missingBlockIndex = [missingBlocks firstIndex];
- [activityFacility endActivity:activity
- withMessage:[NSString stringWithFormat:@"Sync: Downloading '%@' (%.0f%%)",
- object.name,
- (100*(activity.totalBytes - [missingBlocks count]*blockSize + 0.0)/(activity.totalBytes + 0.0))]
- totalBytes:activity.totalBytes
- currentBytes:(activity.totalBytes - [missingBlocks count]*blockSize)];
+ [self endActivity:activity
+ withMessage:[NSString stringWithFormat:@"Sync: Downloading '%@' (%.0f%%)",
+ object.name,
+ (100*(activity.totalBytes - [missingBlocks count]*blockSize + 0.0)/(activity.totalBytes + 0.0))]
+ totalBytes:activity.totalBytes
+ currentBytes:(activity.totalBytes - [missingBlocks count]*blockSize)];
__block ASIPithosObjectRequest *newObjectRequest = [PithosUtilities objectBlockDataRequestWithContainerName:containerName
object:object
blockIndex:missingBlockIndex
blockSize:blockSize];
newObjectRequest.delegate = self;
- newObjectRequest.didFinishSelector = @selector(downloadObjectBlockFinished:);
- newObjectRequest.didFailSelector = @selector(downloadObjectBlockOrHashMapFailed:);
+ newObjectRequest.didFinishSelector = @selector(performRequestFinishedDelegateInBackground:);
+ newObjectRequest.didFailSelector = @selector(performRequestFailedDelegateInBackground:);
newObjectRequest.userInfo = objectRequest.userInfo;
[(NSMutableDictionary *)(newObjectRequest.userInfo) setObject:missingBlocks forKey:@"missingBlocks"];
[(NSMutableDictionary *)(newObjectRequest.userInfo) setObject:[NSNumber numberWithUnsignedInteger:missingBlockIndex] forKey:@"missingBlockIndex"];
[(NSMutableDictionary *)(newObjectRequest.userInfo) setObject:[NSNumber numberWithUnsignedInteger:10] forKey:@"retries"];
+ [(NSMutableDictionary *)(newObjectRequest.userInfo) setObject:NSStringFromSelector(@selector(downloadObjectBlockFinished:)) forKey:@"didFinishSelector"];
[newObjectRequest setBytesReceivedBlock:^(unsigned long long size, unsigned long long total){
[activityFacility updateActivity:activity
withMessage:[NSString stringWithFormat:@"Sync: Downloading '%@' (%.0f%%)",
totalBytes:activity.totalBytes
currentBytes:(activity.currentBytes + size)];
}];
- [queue addOperation:[PithosUtilities prepareRequest:newObjectRequest priority:[[newObjectRequest.userInfo objectForKey:@"priority"] integerValue]]];
+ [networkQueue addOperation:[PithosUtilities prepareRequest:newObjectRequest priority:[[newObjectRequest.userInfo objectForKey:@"priority"] integerValue]]];
}
} else {
[self requestFailed:objectRequest];
}
+ [pool drain];
}
- (void)uploadDirectoryObjectFinished:(ASIPithosObjectRequest *)objectRequest {
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSLog(@"Sync::upload directory object finished: %@", objectRequest.url);
if (objectRequest.responseStatusCode == 201) {
PithosLocalObjectState *storedState = [storedLocalObjectStates objectForKey:[[objectRequest.userInfo objectForKey:@"pithosObject"] name]];
storedState.isDirectory = YES;
[self saveLocalState];
- [activityFacility endActivity:[objectRequest.userInfo objectForKey:@"activity"]
- withMessage:[objectRequest.userInfo objectForKey:@"finishedActivityMessage"]];
+ [self endActivity:[objectRequest.userInfo objectForKey:@"activity"]
+ withMessage:[objectRequest.userInfo objectForKey:@"finishedActivityMessage"]];
@synchronized(self) {
[self decreaseSyncOperationCount];
if (newSyncRequested && !syncOperationCount)
} else {
[self requestFailed:objectRequest];
}
+ [pool drain];
}
- (void)moveObjectToTrashFinished:(ASIPithosObjectRequest *)objectRequest {
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSLog(@"Sync::move object to trash finished: %@", objectRequest.url);
if (objectRequest.responseStatusCode == 201) {
[storedLocalObjectStates removeObjectForKey:[[objectRequest.userInfo objectForKey:@"pithosObject"] name]];
[self saveLocalState];
- [activityFacility endActivity:[objectRequest.userInfo objectForKey:@"activity"]
- withMessage:[objectRequest.userInfo objectForKey:@"finishedActivityMessage"]];
+ [self endActivity:[objectRequest.userInfo objectForKey:@"activity"]
+ withMessage:[objectRequest.userInfo objectForKey:@"finishedActivityMessage"]];
@synchronized(self) {
[self decreaseSyncOperationCount];
if (newSyncRequested && !syncOperationCount)
} else {
[self requestFailed:objectRequest];
}
+ [pool drain];
}
- (void)uploadObjectUsingHashMapFinished:(ASIPithosObjectRequest *)objectRequest {
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSLog(@"Sync::upload using hashmap finished: %@", objectRequest.url);
ASIPithosObject *object = [objectRequest.userInfo objectForKey:@"pithosObject"];
PithosLocalObjectState *storedState = [storedLocalObjectStates objectForKey:object.name];
NSLog(@"Sync::object created: %@", objectRequest.url);
storedState.hash = [objectRequest eTag];
[self saveLocalState];
- [activityFacility endActivity:activity
- withMessage:[objectRequest.userInfo objectForKey:@"finishedActivityMessage"]
- totalBytes:totalBytes
- currentBytes:totalBytes];
+ [self endActivity:activity
+ withMessage:[objectRequest.userInfo objectForKey:@"finishedActivityMessage"]
+ totalBytes:totalBytes
+ currentBytes:totalBytes];
@synchronized(self) {
[self decreaseSyncOperationCount];
if (newSyncRequested && !syncOperationCount)
}
} else if (objectRequest.responseStatusCode == 409) {
if (newSyncRequested) {
- [activityFacility endActivity:activity
- withMessage:[objectRequest.userInfo objectForKey:@"stoppedActivityMessage"]];
+ [self endActivity:activity
+ withMessage:[objectRequest.userInfo objectForKey:@"stoppedActivityMessage"]];
@synchronized(self) {
syncIncomplete = YES;
[self decreaseSyncOperationCount];
NSUInteger iteration = [[objectRequest.userInfo objectForKey:@"iteration"] unsignedIntegerValue];
if (iteration == 0) {
NSLog(@"Sync::upload iteration limit reached: %@", objectRequest.url);
- [activityFacility endActivity:activity
- withMessage:[objectRequest.userInfo objectForKey:@"stoppedActivityMessage"]];
+ [self endActivity:activity
+ withMessage:[objectRequest.userInfo objectForKey:@"stoppedActivityMessage"]];
syncIncomplete = YES;
[self decreaseSyncOperationCount];
return;
withMissingHashesResponse:[objectRequest responseString]];
if (totalBytes >= [missingBlocks count]*blockSize)
currentBytes = totalBytes - [missingBlocks count]*blockSize;
- [activityFacility updateActivity:activity
- withMessage:[NSString stringWithFormat:@"Sync: Uploading '%@' (%.0f%%)", object.name, (100*(currentBytes + 0.0)/(totalBytes + 0.0))]
- totalBytes:totalBytes
- currentBytes:currentBytes];
+ [self updateActivity:activity
+ withMessage:[NSString stringWithFormat:@"Sync: Uploading '%@' (%.0f%%)", object.name, (100*(currentBytes + 0.0)/(totalBytes + 0.0))]
+ totalBytes:totalBytes
+ currentBytes:currentBytes];
NSUInteger missingBlockIndex = [missingBlocks firstIndex];
__block ASIPithosContainerRequest *newContainerRequest = [PithosUtilities updateContainerDataRequestWithContainerName:containerName
blockSize:blockSize
missingBlockIndex:missingBlockIndex
sharingAccount:nil];
newContainerRequest.delegate = self;
- newContainerRequest.didFinishSelector = @selector(uploadMissingBlockFinished:);
- newContainerRequest.didFailSelector = @selector(requestFailed:);
+ newContainerRequest.didFinishSelector = @selector(performRequestFinishedDelegateInBackground:);
+ newContainerRequest.didFailSelector = @selector(performRequestFailedDelegateInBackground:);
newContainerRequest.userInfo = objectRequest.userInfo;
[(NSMutableDictionary *)(newContainerRequest.userInfo) setObject:[NSNumber numberWithUnsignedInteger:(--iteration)] forKey:@"iteration"];
[(NSMutableDictionary *)(newContainerRequest.userInfo) setObject:[NSNumber numberWithUnsignedInteger:10] forKey:@"retries"];
[(NSMutableDictionary *)(newContainerRequest.userInfo) setObject:missingBlocks forKey:@"missingBlocks"];
[(NSMutableDictionary *)(newContainerRequest.userInfo) setObject:[NSNumber numberWithUnsignedInteger:missingBlockIndex] forKey:@"missingBlockIndex"];
+ [(NSMutableDictionary *)(newContainerRequest.userInfo) setObject:NSStringFromSelector(@selector(uploadMissingBlockFinished:)) forKey:@"didFinishSelector"];
[newContainerRequest setBytesSentBlock:^(unsigned long long size, unsigned long long total){
[activityFacility updateActivity:activity
withMessage:[NSString stringWithFormat:@"Sync: Uploading '%@' (%.0f%%)", object.name, (100*(activity.currentBytes + size + 0.0)/(activity.totalBytes + 0.0))]
totalBytes:activity.totalBytes
currentBytes:(activity.currentBytes + size)];
}];
- [queue addOperation:[PithosUtilities prepareRequest:newContainerRequest priority:[[newContainerRequest.userInfo objectForKey:@"priority"] integerValue]]];
+ [networkQueue addOperation:[PithosUtilities prepareRequest:newContainerRequest priority:[[newContainerRequest.userInfo objectForKey:@"priority"] integerValue]]];
}
} else {
[self requestFailed:objectRequest];
}
+ [pool drain];
}
- (void)uploadMissingBlockFinished:(ASIPithosContainerRequest *)containerRequest {
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSLog(@"Sync::upload of missing block finished: %@", containerRequest.url);
if (containerRequest.responseStatusCode == 202) {
ASIPithosObject *object = [containerRequest.userInfo objectForKey:@"pithosObject"];
hashes:&hashes
sharingAccount:nil];
newObjectRequest.delegate = self;
- newObjectRequest.didFinishSelector = @selector(uploadObjectUsingHashMapFinished:);
- newObjectRequest.didFailSelector = @selector(requestFailed:);
+ newObjectRequest.didFinishSelector = @selector(performRequestFinishedDelegateInBackground:);
+ newObjectRequest.didFailSelector = @selector(performRequestFailedDelegateInBackground:);
newObjectRequest.userInfo = containerRequest.userInfo;
[(NSMutableDictionary *)(newObjectRequest.userInfo) setObject:[NSNumber numberWithUnsignedInteger:10] forKey:@"retries"];
[(NSMutableDictionary *)(newObjectRequest.userInfo) removeObjectForKey:@"missingBlocks"];
[(NSMutableDictionary *)(newObjectRequest.userInfo) removeObjectForKey:@"missingBlockIndex"];
- [queue addOperation:[PithosUtilities prepareRequest:newObjectRequest priority:[[newObjectRequest.userInfo objectForKey:@"priority"] integerValue]]];
+ [(NSMutableDictionary *)(newObjectRequest.userInfo) setObject:NSStringFromSelector(@selector(uploadObjectUsingHashMapFinished:)) forKey:@"didFinishSelector"];
+ [networkQueue addOperation:[PithosUtilities prepareRequest:newObjectRequest priority:[[newObjectRequest.userInfo objectForKey:@"priority"] integerValue]]];
} else {
if (newSyncRequested) {
- [activityFacility endActivity:activity
- withMessage:[containerRequest.userInfo objectForKey:@"stoppedActivityMessage"]];
+ [self endActivity:activity
+ withMessage:[containerRequest.userInfo objectForKey:@"stoppedActivityMessage"]];
@synchronized(self) {
syncIncomplete = YES;
[self decreaseSyncOperationCount];
missingBlockIndex:missingBlockIndex
sharingAccount:nil];
newContainerRequest.delegate = self;
- newContainerRequest.didFinishSelector = @selector(uploadMissingBlockFinished:);
- newContainerRequest.didFailSelector = @selector(requestFailed:);
+ newContainerRequest.didFinishSelector = @selector(performRequestFinishedDelegateInBackground:);
+ newContainerRequest.didFailSelector = @selector(performRequestFailedDelegateInBackground:);
newContainerRequest.userInfo = containerRequest.userInfo;
[(NSMutableDictionary *)(newContainerRequest.userInfo) setObject:[NSNumber numberWithUnsignedInteger:10] forKey:@"retries"];
[(NSMutableDictionary *)(newContainerRequest.userInfo) setObject:[NSNumber numberWithUnsignedInteger:missingBlockIndex] forKey:@"missingBlockIndex"];
totalBytes:activity.totalBytes
currentBytes:(activity.currentBytes + size)];
}];
- [queue addOperation:[PithosUtilities prepareRequest:newContainerRequest priority:[[newContainerRequest.userInfo objectForKey:@"priority"] integerValue]]];
+ [networkQueue addOperation:[PithosUtilities prepareRequest:newContainerRequest priority:[[newContainerRequest.userInfo objectForKey:@"priority"] integerValue]]];
}
}
} else {
[self requestFailed:containerRequest];
}
+ [pool drain];
}
- (void)requestFailed:(ASIPithosRequest *)request {
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
if ([request isCancelled]) {
- [activityFacility endActivity:[request.userInfo objectForKey:@"activity"]
- withMessage:[request.userInfo objectForKey:@"stoppedActivityMessage"]];
+ [self endActivity:[request.userInfo objectForKey:@"activity"]
+ withMessage:[request.userInfo objectForKey:@"stoppedActivityMessage"]];
syncIncomplete = YES;
[self decreaseSyncOperationCount];
return;
}
if (newSyncRequested) {
- [activityFacility endActivity:[request.userInfo objectForKey:@"activity"]
- withMessage:[request.userInfo objectForKey:@"stoppedActivityMessage"]];
+ [self endActivity:[request.userInfo objectForKey:@"activity"]
+ withMessage:[request.userInfo objectForKey:@"stoppedActivityMessage"]];
@synchronized(self) {
syncIncomplete = YES;
[self decreaseSyncOperationCount];
}
NSUInteger retries = [[request.userInfo objectForKey:@"retries"] unsignedIntegerValue];
if (retries > 0) {
- ASIPithosRequest *newRequest = (ASIPithosRequest *)[PithosUtilities copyRequest:request];
+ ASIPithosRequest *newRequest = (ASIPithosRequest *)[[PithosUtilities copyRequest:request] autorelease];
[(NSMutableDictionary *)(newRequest.userInfo)setObject:[NSNumber numberWithUnsignedInteger:(--retries)] forKey:@"retries"];
- [queue addOperation:[PithosUtilities prepareRequest:newRequest priority:[[newRequest.userInfo objectForKey:@"priority"] integerValue]]];
+ [networkQueue addOperation:[PithosUtilities prepareRequest:newRequest priority:[[newRequest.userInfo objectForKey:@"priority"] integerValue]]];
} else {
- [activityFacility endActivity:[request.userInfo objectForKey:@"activity"]
- withMessage:[request.userInfo objectForKey:@"failedActivityMessage"]];
+ [self endActivity:[request.userInfo objectForKey:@"activity"]
+ withMessage:[request.userInfo objectForKey:@"failedActivityMessage"]];
syncIncomplete = YES;
[self decreaseSyncOperationCount];
}
+ [pool drain];
}