Permalink
Browse files

Merge remote-tracking branch 'upstream/master'

  • Loading branch information...
bfolder committed Aug 6, 2012
2 parents 3527ab2 + e57262e commit 05da7914d0f51370c1acfe99b8ffda8013bb15ad
@@ -47,7 +47,7 @@
#import "TICDSFileManagerBasedRemoveAllRemoteSyncDataOperation.h"
#pragma mark DropboxSDK-Based
-#if TARGET_OS_IPHONE
+#if TARGET_OS_IPHONE && !defined(NO_DROPBOX)
#import "TICDSDropboxSDKBasedApplicationSyncManager.h"
#import "TICDSDropboxSDKBasedDocumentSyncManager.h"
#import "TICDSDropboxSDKBasedApplicationRegistrationOperation.h"
@@ -8,7 +8,7 @@
extern NSString * const TICDSFrameworkName;
-#define TICDSSyncChangesCoreDataPersistentStoreType NSBinaryStoreType
+#define TICDSSyncChangesCoreDataPersistentStoreType NSSQLiteStoreType
#define TICDSSyncChangeSetsCoreDataPersistentStoreType NSSQLiteStoreType
extern NSString * const TICDSSyncChangeTypeNames[];
@@ -49,11 +49,12 @@ - (void)checkForMostRecentClientWholeStore
}
}
- if( !identifierToReturn && anyError ) {
- [self setError:[TICDSError errorWithCode:TICDSErrorCodeFileManagerError underlyingError:anyError classAndMethod:__PRETTY_FUNCTION__]];
- [self determinedMostRecentWholeStoreWasUploadedByClientWithIdentifier:nil];
- return;
- }
+// For some reason, this block could crash the app. The anyError seems to be the problem. Removed for now.
+// if( !identifierToReturn && anyError ) {
+// [self setError:[TICDSError errorWithCode:TICDSErrorCodeFileManagerError underlyingError:anyError classAndMethod:__PRETTY_FUNCTION__]];
+// [self determinedMostRecentWholeStoreWasUploadedByClientWithIdentifier:nil];
+// return;
+// }
if( !identifierToReturn ) {
[self setError:[TICDSError errorWithCode:TICDSErrorCodeNoPreviouslyUploadedStoreExists classAndMethod:__PRETTY_FUNCTION__]];
@@ -64,58 +65,71 @@ - (void)checkForMostRecentClientWholeStore
[self determinedMostRecentWholeStoreWasUploadedByClientWithIdentifier:identifierToReturn];
}
-- (void)syncFileURL:(NSURL *)url
+- (BOOL)syncFileURL:(NSURL *)url timeout:(NSTimeInterval)timeout error:(NSError **)error
{
NSNumber *isUbiquitousNumber;
BOOL success = [url getResourceValue:&isUbiquitousNumber forKey:NSURLIsUbiquitousItemKey error:NULL];
- if ( !success ) return;
- if ( !isUbiquitousNumber.boolValue ) return;
+ if ( !success ) return NO;
+ if ( !isUbiquitousNumber.boolValue ) return YES;
- NSError *error;
- BOOL downloaded = NO, downloading = YES;
+ BOOL downloaded = NO, downloading = NO;
+ NSUInteger attempt = 0;
+ NSUInteger maxAttempts = timeout;
while ( !downloaded ) {
NSNumber *downloadedNumber;
- BOOL success = [url getResourceValue:&downloadedNumber forKey:NSURLUbiquitousItemIsDownloadedKey error:&error];
- if ( !success ) return;
+ success = [url getResourceValue:&downloadedNumber forKey:NSURLUbiquitousItemIsDownloadedKey error:error];
+ if ( !success ) return NO;
downloaded = downloadedNumber.boolValue;
NSNumber *downloadingNumber;
- success = [url getResourceValue:&downloadingNumber forKey:NSURLUbiquitousItemIsDownloadingKey error:&error];
- if ( !success ) return;
+ success = [url getResourceValue:&downloadingNumber forKey:NSURLUbiquitousItemIsDownloadingKey error:error];
+ if ( !success ) return NO;
downloading = downloadingNumber.boolValue;
- if ( !downloading && !downloaded ) {
- BOOL success = [self.fileManager startDownloadingUbiquitousItemAtURL:url error:&error];
- if ( !success ) return;
+ if ( !downloading && !downloaded && attempt == 0 ) {
+ BOOL success = [self.fileManager startDownloadingUbiquitousItemAtURL:url error:error];
+ if ( !success ) return NO;
}
- [NSThread sleepForTimeInterval:0.1];
+ [NSThread sleepForTimeInterval:1.0];
+
+ if ( ++attempt == maxAttempts ) {
+ if ( error ) *error = [TICDSError errorWithCode:TICDSErrorCodeUnexpectedOrIncompleteFileLocationOrDirectoryStructure classAndMethod:__PRETTY_FUNCTION__];
+ return NO;
+ }
}
+
+ return YES;
}
-- (void)syncDirectoryURL:(NSURL *)url
+- (BOOL)syncDirectoryURL:(NSURL *)url error:(NSError **)error
{
NSString *path = url.path;
-
NSNumber *isUbiquitousNumber;
- BOOL success = [url getResourceValue:&isUbiquitousNumber forKey:NSURLIsUbiquitousItemKey error:NULL];
- if ( !success ) return;
- if ( !isUbiquitousNumber.boolValue ) return;
+ BOOL success = [url getResourceValue:&isUbiquitousNumber forKey:NSURLIsUbiquitousItemKey error:error];
+ if ( !success ) return NO;
+ if ( !isUbiquitousNumber.boolValue ) return YES;
- [self syncFileURL:url];
- NSArray *subPaths = [self.fileManager contentsOfDirectoryAtPath:url.path error:NULL];
- for ( NSString *subPath in subPaths ) {
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+ NSArray *subPaths = [self.fileManager contentsOfDirectoryAtPath:url.path error:error];
+ if ( !subPaths ) return NO;
+
+ for ( NSString *subPath in subPaths ) {
NSString *fullPath = [path stringByAppendingPathComponent:subPath];
NSURL *subURL = [NSURL fileURLWithPath:fullPath];
- NSDictionary *attributes = [self.fileManager attributesOfItemAtPath:fullPath error:NULL];
+ NSDictionary *attributes = [self.fileManager attributesOfItemAtPath:fullPath error:error];
NSString *fileType = [attributes objectForKey:NSFileType];
- [self syncFileURL:subURL];
- if ( [fileType isEqualToString:NSFileTypeDirectory] ) {
- [self syncDirectoryURL:subURL];
+
+ if ( success && [fileType isEqualToString:NSFileTypeDirectory] ) {
+ success = [self syncDirectoryURL:subURL error:error];
+ }
+ else if ( success ) {
+ success = [self syncFileURL:subURL timeout:30.0 error:error];
}
- [pool drain];
+
+ if ( !success ) return NO;
}
+
+ return YES;
}
- (void)downloadWholeStoreFile
@@ -126,12 +140,18 @@ - (void)downloadWholeStoreFile
NSURL *storeURL = [NSURL fileURLWithPath:wholeStorePath];
// Make sure the store and related files are downloaded when using iCloud
- BOOL isDir;
- if ( [self.fileManager fileExistsAtPath:wholeStorePath isDirectory:&isDir] ) {
- if ( isDir )
- [self syncDirectoryURL:storeURL];
- else
- [self syncFileURL:storeURL];
+ NSDictionary *attributes = [self.fileManager attributesOfItemAtPath:storeURL.path error:&anyError];
+ NSString *fileType = [attributes objectForKey:NSFileType];
+ if ( [fileType isEqualToString:NSFileTypeDirectory] ) {
+ success = [self syncDirectoryURL:storeURL error:&anyError];
+ }
+ else {
+ success = [self syncFileURL:storeURL timeout:30.0 error:&anyError];
+ }
+ if( !success ) {
+ [self setError:[TICDSError errorWithCode:TICDSErrorCodeFileManagerError underlyingError:anyError classAndMethod:__PRETTY_FUNCTION__]];
+ [self downloadedWholeStoreFileWithSuccess:success];
+ return;
}
if( ![self shouldUseEncryption] ) {
@@ -19,6 +19,7 @@
@interface TICDSFileManagerBasedApplicationSyncManager : TICDSApplicationSyncManager {
@private
NSURL *_applicationContainingDirectoryLocation;
+ NSMetadataQuery *_cloudMetadataQuery;
}
#pragma mark Dropbox-Related Methods
@@ -8,6 +8,12 @@
#import "TICoreDataSync.h"
+@interface TICDSFileManagerBasedApplicationSyncManager ()
+
+@property (nonatomic, retain) NSMetadataQuery *cloudMetadataQuery;
+
+@end
+
@implementation TICDSFileManagerBasedApplicationSyncManager
#pragma mark -
@@ -116,6 +122,49 @@ + (NSURL *)localDropboxDirectoryLocation
return [NSURL fileURLWithPath:dropboxLocation];
}
+#pragma mark -
+#pragma mark Monitoring cloud metadata changes
+
+- (void)configureWithDelegate:(id <TICDSApplicationSyncManagerDelegate>)aDelegate globalAppIdentifier:(NSString *)anAppIdentifier uniqueClientIdentifier:(NSString *)aClientIdentifier description:(NSString *)aClientDescription userInfo:(NSDictionary *)someUserInfo
+{
+ [super configureWithDelegate:aDelegate globalAppIdentifier:anAppIdentifier uniqueClientIdentifier:aClientIdentifier description:aClientDescription userInfo:someUserInfo];
+
+ NSMetadataQuery *newQuery = [[[NSMetadataQuery alloc] init] autorelease];
+ newQuery.searchScopes = [NSArray arrayWithObject:NSMetadataQueryUbiquitousDataScope];
+ newQuery.predicate = [NSPredicate predicateWithFormat:@"%K like '*'", NSMetadataItemFSNameKey];
+ self.cloudMetadataQuery = newQuery;
+}
+
+- (void)setCloudMetadataQuery:(NSMetadataQuery *)newQuery
+{
+ if ( newQuery != _cloudMetadataQuery ) {
+ if ( _cloudMetadataQuery ) {
+ [[NSNotificationCenter defaultCenter] removeObserver:self name:NSMetadataQueryDidUpdateNotification object:_cloudMetadataQuery];
+ [[NSNotificationCenter defaultCenter] removeObserver:self name:NSMetadataQueryDidFinishGatheringNotification object:_cloudMetadataQuery];
+ [_cloudMetadataQuery stopQuery];
+ }
+ [_cloudMetadataQuery release];
+ _cloudMetadataQuery = [newQuery retain];
+ if ( newQuery ) {
+ [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(cloudFilesDidChange:) name:NSMetadataQueryDidFinishGatheringNotification object:newQuery];
+ [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(cloudFilesDidChange:) name:NSMetadataQueryDidUpdateNotification object:newQuery];
+ if ( ![_cloudMetadataQuery startQuery] ) NSLog(@"Failed to start cloud NSMetadataQuery");
+ }
+ }
+}
+
+- (void)cloudFilesDidChange:(NSNotification *)notif
+{
+ [self.cloudMetadataQuery disableUpdates];
+ NSFileManager *fm = [[[NSFileManager alloc] init] autorelease];
+ NSUInteger count = [self.cloudMetadataQuery resultCount];
+ for ( NSUInteger i = 0; i < count; i++ ) {
+ NSURL *url = [self.cloudMetadataQuery valueOfAttribute:NSMetadataItemURLKey forResultAtIndex:i];
+ [fm startDownloadingUbiquitousItemAtURL:url error:NULL];
+ }
+ [self.cloudMetadataQuery enableUpdates];
+}
+
#pragma mark -
#pragma mark Overridden Methods
@@ -227,12 +276,18 @@ - (NSString *)pathToWholeStoreDirectoryForDocumentWithIdentifier:(NSString *)anI
- (void)dealloc
{
[_applicationContainingDirectoryLocation release], _applicationContainingDirectoryLocation = nil;
-
+
+ [[NSNotificationCenter defaultCenter] removeObserver:self];
+ [_cloudMetadataQuery disableUpdates];
+ [_cloudMetadataQuery stopQuery];
+ [_cloudMetadataQuery release], _cloudMetadataQuery = nil;
+
[super dealloc];
}
#pragma mark -
#pragma mark Properties
@synthesize applicationContainingDirectoryLocation = _applicationContainingDirectoryLocation;
+@synthesize cloudMetadataQuery = _cloudMetadataQuery;
@end
@@ -217,7 +217,7 @@ - (BOOL)moveItemAtPath:(NSString *)fromPath toPath:(NSString *)toPath error:(NSE
NSURL *fromURL = [NSURL fileURLWithPath:fromPath];
NSURL *toURL = [NSURL fileURLWithPath:toPath];
__block BOOL success = NO;
- [self.fileCoordinator coordinateReadingItemAtURL:fromURL options:0 writingItemAtURL:toURL options:NSFileCoordinatorWritingForReplacing error:&anyError byAccessor:^(NSURL *newFromURL, NSURL *newToURL) {
+ [self.fileCoordinator coordinateWritingItemAtURL:fromURL options:NSFileCoordinatorWritingForDeleting writingItemAtURL:toURL options:NSFileCoordinatorWritingForReplacing error:&anyError byAccessor:^(NSURL *newFromURL, NSURL *newToURL) {
success = [[self fileManager] moveItemAtURL:newFromURL toURL:newToURL error:&anyError];
[self.fileCoordinator itemAtURL:newFromURL didMoveToURL:newToURL];
}];
@@ -420,7 +420,7 @@ - (BOOL)applyUnappliedSyncChangeSets:(NSArray *)syncChangeSets
NSInteger changeSetCount = 1;
for( TICDSSyncChangeSet *eachChangeSet in syncChangeSets ) {
- self.changeSetProgressString = [NSString stringWithFormat:@"Change set %ld of %ld", changeSetCount++, [syncChangeSets count]];
+ self.changeSetProgressString = [NSString stringWithFormat:@"Change set %ld of %ld", (long)changeSetCount++, (long)[syncChangeSets count]];
shouldContinue = [self beginApplyingSyncChangesInChangeSet:eachChangeSet];
if( !shouldContinue ) {
break;
@@ -524,6 +524,8 @@ - (BOOL)beginApplyingSyncChangesInChangeSet:(TICDSSyncChangeSet *)aChangeSet
NSInteger changeCount = 1;
// Apply each object's changes in turn
for( TICDSSyncChange *eachChange in syncChanges ) {
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+
switch( [[eachChange changeType] unsignedIntegerValue] ) {
case TICDSSyncChangeTypeObjectInserted:
[self applyObjectInsertedSyncChange:eachChange];
@@ -548,7 +550,11 @@ - (BOOL)beginApplyingSyncChangesInChangeSet:(TICDSSyncChangeSet *)aChangeSet
break;
}
+ [[eachChange managedObjectContext] refreshObject:eachChange mergeChanges:NO]; // Keep memory low
+
[self ti_alertDelegateOnMainThreadWithSelector:@selector(synchronizationOperation:processedChangeNumber:outOfTotalChangeCount:fromClientNamed:) waitUntilDone:NO, [NSNumber numberWithInteger:changeCount++], [NSNumber numberWithInteger:[syncChanges count]], self.changeSetProgressString];
+
+ [pool drain];
}
[[self backgroundApplicationContext] processPendingChanges];
@@ -754,7 +760,7 @@ - (void)applyObjectInsertedSyncChange:(TICDSSyncChange *)aSyncChange
NSString *entityName = [aSyncChange objectEntityName];
NSString *ticdsSyncID = aSyncChange.objectSyncID;
- NSManagedObject *object = nil;
+ TICDSSynchronizedManagedObject *object = nil;
// Check to see if the object already exists before inserting it.
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
@@ -776,7 +782,9 @@ - (void)applyObjectInsertedSyncChange:(TICDSSyncChange *)aSyncChange
NSArray *changedAttributeKeys = [[aSyncChange changedAttributes] allKeys];
for (id key in changedAttributeKeys) {
[object willChangeValueForKey:key];
- [object setPrimitiveValue:[[aSyncChange changedAttributes] valueForKey:key] forKey:key];
+ id transformedValue = [[aSyncChange changedAttributes] valueForKey:key];
+ transformedValue = [object reverseTransformedValueOfAttribute:key withValue:transformedValue];
+ [object setPrimitiveValue:transformedValue forKey:key];
[object didChangeValueForKey:key];
}
@@ -790,7 +798,7 @@ - (void)applyAttributeChangeSyncChange:(TICDSSyncChange *)aSyncChange
{
TICDSLog(TICDSLogVerbosityEveryStep, @"Applying Attribute Change sync change");
- NSManagedObject *object = [self backgroundApplicationContextObjectForEntityName:[aSyncChange objectEntityName] syncIdentifier:[aSyncChange objectSyncID]];
+ TICDSSynchronizedManagedObject *object = (id)[self backgroundApplicationContextObjectForEntityName:[aSyncChange objectEntityName] syncIdentifier:[aSyncChange objectSyncID]];
if( !object ) {
TICDSLog(TICDSLogVerbosityErrorsOnly, @"Object not found locally for attribute change [%@] %@", aSyncChange, [aSyncChange objectEntityName]);
@@ -801,7 +809,9 @@ - (void)applyAttributeChangeSyncChange:(TICDSSyncChange *)aSyncChange
TICDSLog(TICDSLogVerbosityManagedObjectOutput, @"[%@] %@", aSyncChange, [aSyncChange objectEntityName]);
[object willChangeValueForKey:[aSyncChange relevantKey]];
- [object setPrimitiveValue:[aSyncChange changedAttributes] forKey:[aSyncChange relevantKey]];
+ id transformedValue = [aSyncChange changedAttributes];
+ transformedValue = [object reverseTransformedValueOfAttribute:[aSyncChange relevantKey] withValue:transformedValue];
+ [object setPrimitiveValue:transformedValue forKey:[aSyncChange relevantKey]];
[object didChangeValueForKey:[aSyncChange relevantKey]];
TICDSLog(TICDSLogVerbosityManagedObjectOutput, @"Changed attribute on object: %@", object);
@@ -1454,9 +1454,14 @@ - (NSString *)relativePathToThisDocumentTemporaryWholeStoreDirectory
return [[self relativePathToThisDocumentTemporaryFilesDirectory] stringByAppendingPathComponent:TICDSWholeStoreDirectoryName];
}
+- (NSString *)clientDirectoryName
+{
+ return [self clientIdentifier];
+}
+
- (NSString *)relativePathToThisDocumentTemporaryWholeStoreThisClientDirectory
{
- return [[self relativePathToThisDocumentTemporaryWholeStoreDirectory] stringByAppendingPathComponent:[self clientIdentifier]];
+ return [[self relativePathToThisDocumentTemporaryWholeStoreDirectory] stringByAppendingPathComponent:[self clientDirectoryName]];
}
- (NSString *)relativePathToThisDocumentTemporaryWholeStoreThisClientDirectoryWholeStoreFile
@@ -1476,7 +1481,7 @@ - (NSString *)relativePathToThisDocumentWholeStoreDirectory
- (NSString *)relativePathToThisDocumentWholeStoreThisClientDirectory
{
- return [[self relativePathToThisDocumentWholeStoreDirectory] stringByAppendingPathComponent:[self clientIdentifier]];
+ return [[self relativePathToThisDocumentWholeStoreDirectory] stringByAppendingPathComponent:[self clientDirectoryName]];
}
- (NSString *)relativePathToThisDocumentWholeStoreThisClientDirectoryWholeStoreFile
@@ -28,4 +28,7 @@
@property (nonatomic, readonly) NSManagedObjectContext *syncChangesMOC;
@property (nonatomic, readwrite, assign) BOOL excludeFromSync;
+- (id)transformedValueOfAttribute:(NSString *)key;
+- (id)reverseTransformedValueOfAttribute:(NSString *)key withValue:(id)value;
+
@end
Oops, something went wrong.

0 comments on commit 05da791

Please sign in to comment.