Merge lp:~mikemc/ubuntuone-ios-files/use-asset-ids-everywhere into lp:ubuntuone-ios-files
- use-asset-ids-everywhere
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | dobey |
Approved revision: | 102 |
Merged at revision: | 102 |
Proposed branch: | lp:~mikemc/ubuntuone-ios-files/use-asset-ids-everywhere |
Merge into: | lp:ubuntuone-ios-files |
Prerequisite: | lp:~mikemc/ubuntuone-ios-files/quiet-crashlytics |
Diff against target: |
709 lines (+175/-143) 14 files modified
Files/U1AssetRepresenationDataProvider.h (+2/-3) Files/U1AssetRepresenationDataProvider.m (+11/-4) Files/U1AutoUploadOperation.h (+1/-2) Files/U1AutoUploadOperation.m (+20/-23) Files/U1AutoUploadsManager.m (+33/-31) Files/U1FilesClient.h (+2/-2) Files/U1FilesClient.m (+44/-45) Files/U1FilesService.h (+3/-2) Files/U1FilesService.m (+13/-3) Files/U1FolderViewController.m (+1/-3) Files/U1MagicUploadDataProvider.h (+2/-2) Files/U1MagicUploadDataProvider.m (+12/-5) Files/U1UploadOperation.h (+2/-4) Files/U1UploadOperation.m (+29/-14) |
To merge this branch: | bzr merge lp:~mikemc/ubuntuone-ios-files/use-asset-ids-everywhere |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
dobey (community) | Approve | ||
Review via email: mp+164779@code.launchpad.net |
Commit message
- Simplify concurrent operation interfaces
Description of the change
- Simplify concurrent operation interfaces
Pass asset IDs instead of non-threadsafe asset objects to NSOperation subclasses to ease verifying the thread-safety of accesses.
In some cases it was OK to pass the asset objects, as they may have been created on the same thread that the operation accesses them on, but the operation itself is intended to be concurrent and it should be OK to assume that you can run an NSoperation object anywhere without thread safety issues - you shouldn't have to carefully inspect the operation code every time you change how you run it.
dobey (dobey) wrote : | # |
Oh, this one also seems to have some conflicts.
Mike McCracken (mikemc) wrote : | # |
101 and 102 are reapplications of the changes without the criss-cross merge that confused LP
dobey (dobey) : | # |
Ubuntu One Auto Pilot (otto-pilot) wrote : | # |
The prerequisite https:/
Preview Diff
1 | === modified file 'Files/U1AssetRepresenationDataProvider.h' |
2 | --- Files/U1AssetRepresenationDataProvider.h 2011-12-07 22:53:01 +0000 |
3 | +++ Files/U1AssetRepresenationDataProvider.h 2013-05-24 22:42:26 +0000 |
4 | @@ -1,5 +1,5 @@ |
5 | // |
6 | -// Copyright 2011 Canonical Ltd. |
7 | +// Copyright 2011-2013 Canonical Ltd. |
8 | // |
9 | // This program is free software: you can redistribute it and/or modify it |
10 | // under the terms of the GNU Affero General Public License version 3, |
11 | @@ -17,7 +17,6 @@ |
12 | |
13 | #import "U1FilesService.h" |
14 | |
15 | - |
16 | @interface U1AssetRepresenationDataProvider : NSObject <U1UploadDataProvider> |
17 | -@property (retain) NSURL *assetURL; |
18 | +@property (retain) NSManagedObjectID *assetID; |
19 | @end |
20 | |
21 | === modified file 'Files/U1AssetRepresenationDataProvider.m' |
22 | --- Files/U1AssetRepresenationDataProvider.m 2012-08-07 14:23:31 +0000 |
23 | +++ Files/U1AssetRepresenationDataProvider.m 2013-05-24 22:42:26 +0000 |
24 | @@ -1,5 +1,5 @@ |
25 | // |
26 | -// Copyright 2011 Canonical Ltd. |
27 | +// Copyright 2011-2013 Canonical Ltd. |
28 | // |
29 | // This program is free software: you can redistribute it and/or modify it |
30 | // under the terms of the GNU Affero General Public License version 3, |
31 | @@ -18,13 +18,15 @@ |
32 | #import <AssetsLibrary/AssetsLibrary.h> |
33 | #import <MobileCoreServices/MobileCoreServices.h> |
34 | |
35 | +#import "U1Asset.h" |
36 | +#import "U1DataRepository.h" |
37 | |
38 | @implementation U1AssetRepresenationDataProvider |
39 | { |
40 | ALAssetsLibrary *library; |
41 | } |
42 | |
43 | -@synthesize assetURL; |
44 | +@synthesize assetID; |
45 | |
46 | - (id)init; |
47 | { |
48 | @@ -37,7 +39,6 @@ |
49 | |
50 | - (void)dealloc; |
51 | { |
52 | - [assetURL release]; |
53 | [library release]; |
54 | [super dealloc]; |
55 | } |
56 | @@ -49,7 +50,13 @@ |
57 | |
58 | - (void)prepareDataStreamWithBlock:(void(^)(NSInputStream *dataStream, NSString *mimeType, NSUInteger length, NSError *error))block; |
59 | { |
60 | - [library assetForURL:self.assetURL resultBlock:^(ALAsset *asset) { |
61 | + __block NSURL *url; |
62 | + [[U1DataRepository sharedDataRepository] dispatchBlockWithManagedObjectContext:^(NSManagedObjectContext *context) { |
63 | + U1Asset *asset = (U1Asset *)[context objectWithID:self.assetID]; |
64 | + url = [NSURL URLWithString:asset.url]; |
65 | + }]; |
66 | + |
67 | + [library assetForURL:url resultBlock:^(ALAsset *asset) { |
68 | |
69 | if (asset == nil) |
70 | { |
71 | |
72 | === modified file 'Files/U1AutoUploadOperation.h' |
73 | --- Files/U1AutoUploadOperation.h 2012-08-07 14:23:19 +0000 |
74 | +++ Files/U1AutoUploadOperation.h 2013-05-24 22:42:26 +0000 |
75 | @@ -1,5 +1,5 @@ |
76 | // |
77 | -// Copyright 2011 Canonical Ltd. |
78 | +// Copyright 2011-2013 Canonical Ltd. |
79 | // |
80 | // This program is free software: you can redistribute it and/or modify it |
81 | // under the terms of the GNU Affero General Public License version 3, |
82 | @@ -20,7 +20,6 @@ |
83 | @class U1FolderNode; |
84 | |
85 | @interface U1AutoUploadOperation : NSOperation |
86 | -@property (retain) NSURL *assetURL; |
87 | @property (retain) NSManagedObjectID *assetID; |
88 | @property (retain) NSManagedObjectID *folderID; |
89 | @property (retain) NSString *filename; |
90 | |
91 | === modified file 'Files/U1AutoUploadOperation.m' |
92 | --- Files/U1AutoUploadOperation.m 2013-05-24 22:42:26 +0000 |
93 | +++ Files/U1AutoUploadOperation.m 2013-05-24 22:42:26 +0000 |
94 | @@ -34,7 +34,7 @@ |
95 | |
96 | @implementation U1AutoUploadOperation |
97 | |
98 | -@synthesize executing, finished, assetURL, assetID, folderID, filename, priority; |
99 | +@synthesize executing, finished, assetID, folderID, filename, priority; |
100 | |
101 | - (BOOL)isConcurrent; |
102 | { |
103 | @@ -69,7 +69,6 @@ |
104 | |
105 | - (void)dealloc |
106 | { |
107 | - [assetURL release]; |
108 | [filename release]; |
109 | [assetID release]; |
110 | [folderID release]; |
111 | @@ -78,33 +77,31 @@ |
112 | |
113 | - (void)beginUpload; |
114 | { |
115 | - U1DataRepository *dataRepository = [U1DataRepository sharedDataRepository]; |
116 | - [dataRepository dispatchBlockWithMainContext:^(NSManagedObjectContext *context) { |
117 | - |
118 | - U1Asset *asset = (id)[context objectWithID:self.assetID]; |
119 | - U1FolderNode *folder = (id)[context objectWithID:self.folderID]; |
120 | - |
121 | - [[U1FilesClient sharedFilesClient] uploadAssetURL:self.assetURL toFolder:folder withResourceName:self.filename withPriority:self.priority progressBlock:^(long long bytesUploaded, long long totalBytes) { |
122 | - |
123 | - } completionBlockOnMainQueue:^(U1FileNode *fileNode, NSError *error) { |
124 | - if (error != nil) |
125 | - { |
126 | - NSLog(@"U1AutoUploadOperation: auto-upload failed: %@", error); |
127 | - } |
128 | - else |
129 | - { |
130 | - NSLog(@"U1AutoUploadOperation successfully uploaded asset:\n%@", asset); |
131 | + |
132 | + [[U1FilesClient sharedFilesClient] uploadAssetWithID:self.assetID withPriority:self.priority progressBlock:^(long long bytesUploaded, long long totalBytes) { |
133 | + |
134 | + } completionBlockOnMainQueue:^(U1FileNode *fileNode, NSError *error) { |
135 | + if (error != nil) |
136 | + { |
137 | + NSLog(@"U1AutoUploadOperation: auto-upload failed: %@", error); |
138 | + } |
139 | + else |
140 | + { |
141 | + [[U1DataRepository sharedDataRepository] dispatchBlockWithMainContext:^(NSManagedObjectContext *context) { |
142 | + U1Asset *asset = (U1Asset *)[context objectWithID:self.assetID]; |
143 | + NSLog(@"U1AutoUploadOperation done with asset:\n%@", asset); |
144 | + |
145 | asset.generation = asset.fileNode.generation; |
146 | NSError *err = NULL; |
147 | - BOOL success = [dataRepository save:&err]; |
148 | + BOOL success = [context save:&err]; |
149 | if(!success){ |
150 | CLS_LOG(@"U1AutoUploadOperation: failed to save to repository: %@", err); |
151 | } |
152 | - } |
153 | - [self finishExecuting]; |
154 | - }]; |
155 | - |
156 | + }]; |
157 | + } |
158 | + [self finishExecuting]; |
159 | }]; |
160 | + |
161 | } |
162 | |
163 | @end |
164 | |
165 | === modified file 'Files/U1AutoUploadsManager.m' |
166 | --- Files/U1AutoUploadsManager.m 2013-05-24 22:42:26 +0000 |
167 | +++ Files/U1AutoUploadsManager.m 2013-05-24 22:42:26 +0000 |
168 | @@ -371,25 +371,23 @@ |
169 | // examine u1asset on main queue, as it was fetched there: |
170 | dispatch_async(dispatch_get_main_queue(), ^{ |
171 | |
172 | - [self.filesClient uploadAssetURL:imageURL |
173 | - toFolder:u1asset.fileNode.parent |
174 | - withResourceName:u1asset.filename |
175 | - withPriority:NSOperationQueuePriorityVeryHigh |
176 | - progressBlock:^(long long bytesUploaded, long long totalBytes) {} |
177 | - completionBlockOnMainQueue:^(U1FileNode *updatedNode, NSError *error){ |
178 | - if(error != nil){ |
179 | - NSLog(@"error in upload for restarted auto-upload: %@", error); |
180 | - }else{ |
181 | - |
182 | - u1asset.generation = updatedNode.generation; |
183 | - |
184 | - NSError *err = NULL; |
185 | - BOOL success = [dataRepository save:&err]; |
186 | - if(!success){ |
187 | - CLS_LOG(@"U1AutoUploadOperation: failed to save to repository: %@", err); |
188 | - } |
189 | - } |
190 | - }]; |
191 | + [self.filesClient uploadAssetWithID:[u1asset objectID] |
192 | + withPriority:NSOperationQueuePriorityVeryHigh |
193 | + progressBlock:^(long long bytesUploaded, long long totalBytes) {} |
194 | + completionBlockOnMainQueue:^(U1FileNode *updatedNode, NSError *error){ |
195 | + if(error != nil){ |
196 | + NSLog(@"error in upload for restarted auto-upload: %@", error); |
197 | + }else{ |
198 | + |
199 | + u1asset.generation = updatedNode.generation; |
200 | + |
201 | + NSError *err = NULL; |
202 | + BOOL success = [dataRepository save:&err]; |
203 | + if(!success){ |
204 | + CLS_LOG(@"U1AutoUploadOperation: failed to save to repository: %@", err); |
205 | + } |
206 | + } |
207 | + }]; |
208 | }); |
209 | } |
210 | } failureBlock:^(NSError *error) { |
211 | @@ -417,18 +415,22 @@ |
212 | return nil; |
213 | } |
214 | |
215 | - if ((![self isPending:assetToUpload.filename]) && (assetToUpload.generation == nil)) |
216 | - { |
217 | - // Let's create an operation! |
218 | - U1AutoUploadOperation *operation = [[U1AutoUploadOperation alloc] init]; |
219 | - operation.assetURL = [NSURL URLWithString:assetToUpload.url]; |
220 | - operation.assetID = [assetToUpload objectID]; |
221 | - operation.folderID = [self.remoteUploadFolder objectID]; |
222 | - operation.filename = assetToUpload.filename; |
223 | - operation.priority = NSOperationQueuePriorityNormal; |
224 | - return [operation autorelease]; |
225 | - } |
226 | - return nil; |
227 | + if([self isPending:assetToUpload.filename]){ |
228 | + return nil; |
229 | + } |
230 | + |
231 | + if(assetToUpload.generation != nil){ |
232 | + return nil; |
233 | + } |
234 | + |
235 | + NSLog(@"creating an autoupload op for asset ID %@", [assetToUpload objectID]); |
236 | + U1AutoUploadOperation *operation = [[U1AutoUploadOperation alloc] init]; |
237 | + operation.assetID = [assetToUpload objectID]; |
238 | + operation.folderID = [self.remoteUploadFolder objectID]; |
239 | + operation.filename = assetToUpload.filename; |
240 | + operation.priority = NSOperationQueuePriorityNormal; |
241 | + return [operation autorelease]; |
242 | + |
243 | } |
244 | |
245 | - (int)numberOfAssets; |
246 | |
247 | === modified file 'Files/U1FilesClient.h' |
248 | --- Files/U1FilesClient.h 2013-04-03 23:10:33 +0000 |
249 | +++ Files/U1FilesClient.h 2013-05-24 22:42:26 +0000 |
250 | @@ -1,5 +1,5 @@ |
251 | // |
252 | -// Copyright 2011 Canonical Ltd. |
253 | +// Copyright 2011-2013 Canonical Ltd. |
254 | // |
255 | // This program is free software: you can redistribute it and/or modify it |
256 | // under the terms of the GNU Affero General Public License version 3, |
257 | @@ -38,7 +38,7 @@ |
258 | - (id)fetchFileWithResourcePath:(NSString*)nodePath completionBlock:(void(^)(U1Node *node, NSError *error))completionBlock; |
259 | - (id)renameNode:(U1Node*)node toName:(NSString*)newName completionBlockOnMainQueue:(void(^)(U1Node *node, NSError *error))completionBlock; |
260 | - (id)deleteNode:(U1Node*)node completionBlock:(void(^)(NSError *error))completionBlock; |
261 | -- (id)uploadAssetURL:(NSURL*)assetURL toFolder:(U1FolderNode*)folderNode withResourceName:(NSString*)resourceName withPriority:(NSOperationQueuePriority)priority progressBlock:(void(^)(long long bytesUploaded, long long totalBytes))progressBlock completionBlockOnMainQueue:(void(^)(U1FileNode *updatedNode, NSError *error))completionBlock; |
262 | +- (id)uploadAssetWithID:(NSManagedObjectID*)assetID withPriority:(NSOperationQueuePriority)priority progressBlock:(void(^)(long long bytesUploaded, long long totalBytes))progressBlock completionBlockOnMainQueue:(void(^)(U1FileNode *updatedNode, NSError *error))completionBlock; |
263 | - (id)publishNode:(U1FileNode*)node completionBlockOnMainQueue:(void(^)(U1FileNode *node, NSError *error))completionBlock; |
264 | - (id)unpublishNode:(U1FileNode*)node completionBlockOnMainQueue:(void(^)(U1FileNode *node, NSError *error))completionBlock; |
265 | - (id)createFolderNamed:(NSString*)name inFolder:(U1FolderNode*)folderNode completionBlockOnMainQueue:(void(^)(U1FolderNode *newFolderNode, NSError *error))completionBlock; |
266 | |
267 | === modified file 'Files/U1FilesClient.m' |
268 | --- Files/U1FilesClient.m 2013-05-24 22:42:26 +0000 |
269 | +++ Files/U1FilesClient.m 2013-05-24 22:42:26 +0000 |
270 | @@ -22,6 +22,7 @@ |
271 | #import "Reachability.h" |
272 | |
273 | #import "U1AccountManager.h" |
274 | +#import "U1Asset.h" |
275 | #import "U1DataRepository.h" |
276 | #import "U1FilesService.h" |
277 | #import "U1FileNode.h" |
278 | @@ -386,37 +387,22 @@ |
279 | }]; |
280 | } |
281 | |
282 | -- (id)uploadAssetURL:(NSURL*)assetURL toFolder:(U1FolderNode *)folderNode withResourceName:(NSString *)resourceName withPriority:(NSOperationQueuePriority)priority progressBlock:(void (^)(long long, long long))progressBlock completionBlockOnMainQueue:(void (^)(U1FileNode *, NSError *))completionBlock; |
283 | +- (id)uploadAssetWithID:(NSManagedObjectID*)assetID withPriority:(NSOperationQueuePriority)priority progressBlock:(void (^)(long long, long long))progressBlock completionBlockOnMainQueue:(void (^)(U1FileNode *, NSError *))completionBlock; |
284 | { |
285 | - NSString *resourcePath = [folderNode.resourcePath stringByAppendingPathComponent:resourceName]; |
286 | - U1FileNode *node = (id)[self.dataRepository nodeWithResourcePath:resourcePath]; // node will be from main context , on main Q |
287 | - if (!node) |
288 | - { |
289 | - [self.dataRepository dispatchBlockWithMainContext:^(NSManagedObjectContext *context) { |
290 | - U1FileNode *newNode = [U1FileNode insertInManagedObjectContext:context]; |
291 | - newNode.resourcePath = resourcePath; |
292 | - newNode.kind = @"file"; |
293 | - newNode.contentPath = [folderNode.contentPath stringByAppendingPathComponent:resourceName]; |
294 | - newNode.parent = folderNode; |
295 | - NSError *err; |
296 | - if(![context save:&err]){ |
297 | - CLS_LOG(@"Error saving new file node for upload to main context: %@", err); |
298 | - } |
299 | - }]; |
300 | - node = (id)[self.dataRepository nodeWithResourcePath:resourcePath]; |
301 | - } |
302 | + |
303 | |
304 | U1UploadOperation *operation = [[U1UploadOperation alloc] init]; |
305 | __block typeof(operation) operationRef = [operation retain]; |
306 | |
307 | - operation.assetURL = assetURL; |
308 | - operation.fileNode = node; |
309 | + operation.assetID = assetID; |
310 | operation.progressBlock = ^(long long sent, long long total) { |
311 | |
312 | dispatch_async(dispatch_get_main_queue(), ^{ |
313 | |
314 | + U1Asset *asset = (U1Asset *)[[self.dataRepository mainContext] objectWithID:assetID]; |
315 | + |
316 | NSDictionary *userInfo = [NSDictionary dictionaryWithObjectsAndKeys: |
317 | - operationRef.fileNode, @"node", |
318 | + asset.fileNode, @"node", |
319 | operationRef.fileInfo, @"fileInfo", |
320 | nil]; |
321 | [[NSNotificationCenter defaultCenter] postNotificationName:U1FilesClientNodeStatusChangedNotification object:self userInfo:userInfo]; |
322 | @@ -431,10 +417,13 @@ |
323 | [operation setQueuePriority:priority]; |
324 | [operation setCompletionBlock:^{ |
325 | dispatch_async(dispatch_get_main_queue(), ^(void) { |
326 | + |
327 | if (operationRef.error == nil) // or the error is somehow unrecoverable (e.g., over quota) |
328 | { |
329 | + U1Asset *asset = (U1Asset *)[[self.dataRepository mainContext] objectWithID:assetID]; |
330 | + |
331 | [[NSNotificationCenter defaultCenter] postNotificationName:@"imageUploaded" object:nil]; |
332 | - completionBlock(operationRef.fileNode, nil); |
333 | + completionBlock(asset.fileNode, nil); |
334 | } |
335 | else |
336 | { |
337 | @@ -576,13 +565,16 @@ |
338 | - (BOOL)isPending:(U1FileNode *)fileNode; |
339 | { |
340 | __block BOOL isPending = NO; |
341 | - |
342 | - [[self.uploadsQueue operations] enumerateObjectsUsingBlock:^(U1UploadOperation *operation, NSUInteger idx, BOOL *stop) { |
343 | - if (operation.fileNode == fileNode) |
344 | - { |
345 | - isPending = YES; |
346 | - *stop = YES; |
347 | - } |
348 | + [self.dataRepository dispatchBlockWithManagedObjectContext:^(NSManagedObjectContext *context) { |
349 | + |
350 | + [[self.uploadsQueue operations] enumerateObjectsUsingBlock:^(U1UploadOperation *operation, NSUInteger idx, BOOL *stop) { |
351 | + U1Asset *asset = (U1Asset *)[context objectWithID:operation.assetID]; |
352 | + if (asset.fileNode == fileNode) |
353 | + { |
354 | + isPending = YES; |
355 | + *stop = YES; |
356 | + } |
357 | + }]; |
358 | }]; |
359 | |
360 | return isPending; |
361 | @@ -591,30 +583,37 @@ |
362 | - (BOOL)isUploading:(U1FileNode *)fileNode; |
363 | { |
364 | __block BOOL isUploading = NO; |
365 | - |
366 | - [[self.uploadsQueue operations] enumerateObjectsUsingBlock:^(U1UploadOperation *operation, NSUInteger idx, BOOL *stop) { |
367 | - if (operation.fileNode == fileNode && [operation isExecuting]) |
368 | - { |
369 | - isUploading = YES; |
370 | - *stop = YES; |
371 | - } |
372 | + [self.dataRepository dispatchBlockWithManagedObjectContext:^(NSManagedObjectContext *context) { |
373 | + |
374 | + [[self.uploadsQueue operations] enumerateObjectsUsingBlock:^(U1UploadOperation *operation, NSUInteger idx, BOOL *stop) { |
375 | + U1Asset *asset = (U1Asset *)[context objectWithID:operation.assetID]; |
376 | + |
377 | + if (asset.fileNode == fileNode && [operation isExecuting]) |
378 | + { |
379 | + isUploading = YES; |
380 | + *stop = YES; |
381 | + } |
382 | + }]; |
383 | }]; |
384 | - |
385 | + |
386 | return isUploading; |
387 | } |
388 | |
389 | - (U1LocalFileInfo*)fileInfoForNode:(U1FileNode*)fileNode; |
390 | { |
391 | - // TODO: |
392 | __block U1UploadOperation *uploadOperation = nil; |
393 | - [[self.uploadsQueue operations] enumerateObjectsUsingBlock:^(U1UploadOperation *operation, NSUInteger idx, BOOL *stop) { |
394 | - if (operation.fileNode == fileNode) |
395 | - { |
396 | - uploadOperation = operation; |
397 | - *stop = YES; |
398 | - } |
399 | + [self.dataRepository dispatchBlockWithManagedObjectContext:^(NSManagedObjectContext *context) { |
400 | + |
401 | + [[self.uploadsQueue operations] enumerateObjectsUsingBlock:^(U1UploadOperation *operation, NSUInteger idx, BOOL *stop) { |
402 | + U1Asset *asset = (U1Asset *)[context objectWithID:operation.assetID]; |
403 | + |
404 | + if (asset.fileNode == fileNode) |
405 | + { |
406 | + uploadOperation = operation; |
407 | + *stop = YES; |
408 | + } |
409 | + }]; |
410 | }]; |
411 | - |
412 | return uploadOperation.fileInfo; |
413 | } |
414 | |
415 | |
416 | === modified file 'Files/U1FilesService.h' |
417 | --- Files/U1FilesService.h 2013-04-03 23:10:33 +0000 |
418 | +++ Files/U1FilesService.h 2013-05-24 22:42:26 +0000 |
419 | @@ -1,5 +1,5 @@ |
420 | // |
421 | -// Copyright 2011 Canonical Ltd. |
422 | +// Copyright 2011-2013 Canonical Ltd. |
423 | // |
424 | // This program is free software: you can redistribute it and/or modify it |
425 | // under the terms of the GNU Affero General Public License version 3, |
426 | @@ -19,6 +19,7 @@ |
427 | |
428 | |
429 | @protocol U1UploadDataProvider <NSObject> |
430 | +@property (retain) NSManagedObjectID *assetID; |
431 | - (void)prepareDataStreamWithBlock:(void(^)(NSInputStream *dataStream, NSString *mimeType, NSUInteger length, NSError *error))block; |
432 | - (BOOL)isMagic; |
433 | @end |
434 | @@ -33,7 +34,7 @@ |
435 | - (id)infoForNodeAtResourcePath:(NSString*)resourcePath includeChildren:(BOOL)includeChildren completionBlockOnMainQueue:(void(^)(NSDictionary *node, NSError *error))completionBlock; |
436 | - (id)infoForNode:(U1Node*)node includeChildren:(BOOL)includeChildren completionBlockOnMainQueue:(void(^)(NSDictionary *node, NSError *error))completionBlock; |
437 | - (id)contentForNode:(U1FileNode*)node progressBlock:(void(^)(long long bytesReceived, long long bytesExpected))progressBlock completionBlock:(void(^)(NSURL *contentURL))completionBlock; |
438 | -- (id)uploadContentData:(id<U1UploadDataProvider>)contentData forNode:(U1FileNode*)node progressBlock:(void(^)(long long bytesUploaded, long long totalBytes))progressBlock completionBlockOnMainQueue:(void(^)(NSDictionary *updatedNodeInfo, NSError *error))completionBlock; |
439 | +- (id)uploadContentData:(id<U1UploadDataProvider>)contentData progressBlock:(void(^)(long long bytesUploaded, long long totalBytes))progressBlock completionBlockOnMainQueue:(void(^)(NSDictionary *updatedNodeInfo, NSError *error))completionBlock; |
440 | - (id)moveNodeAtResourcePath:(NSString*)resourcePath toPath:(NSString*)newPath withCompletionBlockOnMainQueue:(void(^)(NSDictionary *nodeInfo, NSError *error))completionBlock; |
441 | - (id)deleteNodeAtResourcePath:(NSString*)resourcePath completionBlockOnMainQueue:(void(^)(NSError *error))completionBlock; |
442 | - (id)publishNode:(U1FileNode*)node completionBlockOnMainQueue:(void(^)(U1FileNode *node, NSError *error))completionBlock; |
443 | |
444 | === modified file 'Files/U1FilesService.m' |
445 | --- Files/U1FilesService.m 2013-05-24 22:42:26 +0000 |
446 | +++ Files/U1FilesService.m 2013-05-24 22:42:26 +0000 |
447 | @@ -21,6 +21,8 @@ |
448 | #import "U1Logging.h" |
449 | |
450 | #import "U1AccountManager.h" |
451 | +#import "U1Asset.h" |
452 | +#import "U1DataRepository.h" |
453 | #import "U1FileNode.h" |
454 | #import "U1HTTPRequestOperation.h" |
455 | #import "U1Node.h" |
456 | @@ -170,15 +172,22 @@ |
457 | return nil; |
458 | } |
459 | |
460 | -- (id)uploadContentData:(id<U1UploadDataProvider>)contentData forNode:(U1FileNode*)node progressBlock:(void(^)(long long bytesUploaded, long long totalBytes))progressBlock completionBlockOnMainQueue:(void(^)(NSDictionary *updatedNodeInfo, NSError *error))completionBlock; |
461 | +- (id)uploadContentData:(id<U1UploadDataProvider>)contentData progressBlock:(void(^)(long long bytesUploaded, long long totalBytes))progressBlock completionBlockOnMainQueue:(void(^)(NSDictionary *updatedNodeInfo, NSError *error))completionBlock; |
462 | { |
463 | - NSString *resourcePath = node.resourcePath; |
464 | + __block NSString *resourcePath; |
465 | + [[U1DataRepository sharedDataRepository] dispatchBlockWithManagedObjectContext:^(NSManagedObjectContext *context) { |
466 | + U1Asset *asset = (U1Asset *)[context objectWithID:contentData.assetID]; |
467 | + NSAssert(asset.fileNode != nil, @"Attempting to upload asset with nil fileNode. Asset is %@ ", asset); |
468 | + resourcePath = [asset.fileNode.resourcePath retain]; |
469 | + }]; |
470 | + |
471 | NSURL *requestURL = [contentData isMagic] ? [self URLForNode:resourcePath includeChildren:NO] : [self contentURLForNode:resourcePath]; |
472 | |
473 | [contentData prepareDataStreamWithBlock:^(NSInputStream *dataStream, NSString *mimeType, NSUInteger length, NSError *error) { |
474 | |
475 | if (error) |
476 | { |
477 | + NSLog(@"in uploadContentData, got error '%@' from contentData provider %@", error, contentData); |
478 | dispatch_async(dispatch_get_main_queue(), ^{ |
479 | completionBlock(nil, error); |
480 | }); |
481 | @@ -192,7 +201,8 @@ |
482 | completionBlock(results, error); |
483 | }]; |
484 | }]; |
485 | - |
486 | + |
487 | + [resourcePath autorelease]; |
488 | return nil; |
489 | } |
490 | |
491 | |
492 | === modified file 'Files/U1FolderViewController.m' |
493 | --- Files/U1FolderViewController.m 2013-05-24 22:42:26 +0000 |
494 | +++ Files/U1FolderViewController.m 2013-05-24 22:42:26 +0000 |
495 | @@ -215,9 +215,7 @@ |
496 | |
497 | if (u1asset.generation == nil) // Prevent duplicate uploading to the same folder |
498 | { |
499 | - [self.filesClient uploadAssetURL:[NSURL URLWithString:[u1asset url]] |
500 | - toFolder:self.node |
501 | - withResourceName:filename |
502 | + [self.filesClient uploadAssetWithID:[u1asset objectID] |
503 | withPriority:NSOperationQueuePriorityVeryHigh |
504 | progressBlock:^(long long bytesUploaded, long long totalBytes) {} |
505 | completionBlockOnMainQueue:^(U1FileNode *updatedNode, NSError *error) { |
506 | |
507 | === modified file 'Files/U1MagicUploadDataProvider.h' |
508 | --- Files/U1MagicUploadDataProvider.h 2012-08-02 17:36:41 +0000 |
509 | +++ Files/U1MagicUploadDataProvider.h 2013-05-24 22:42:26 +0000 |
510 | @@ -1,5 +1,5 @@ |
511 | // |
512 | -// Copyright 2012 Canonical Ltd. |
513 | +// Copyright 2012-2013 Canonical Ltd. |
514 | // |
515 | // This program is free software: you can redistribute it and/or modify it |
516 | // under the terms of the GNU Affero General Public License version 3, |
517 | @@ -18,5 +18,5 @@ |
518 | #import "U1FilesService.h" |
519 | |
520 | @interface U1MagicUploadDataProvider : NSObject <U1UploadDataProvider> |
521 | -@property (retain) NSURL *assetURL; |
522 | +@property (retain) NSManagedObjectID *assetID; |
523 | @end |
524 | |
525 | === modified file 'Files/U1MagicUploadDataProvider.m' |
526 | --- Files/U1MagicUploadDataProvider.m 2013-02-15 19:40:11 +0000 |
527 | +++ Files/U1MagicUploadDataProvider.m 2013-05-24 22:42:26 +0000 |
528 | @@ -1,5 +1,5 @@ |
529 | // |
530 | -// Copyright 2012 Canonical Ltd. |
531 | +// Copyright 2012-2013 Canonical Ltd. |
532 | // |
533 | // This program is free software: you can redistribute it and/or modify it |
534 | // under the terms of the GNU Affero General Public License version 3, |
535 | @@ -18,13 +18,15 @@ |
536 | #import <CommonCrypto/CommonDigest.h> |
537 | #import <AssetsLibrary/AssetsLibrary.h> |
538 | |
539 | - |
540 | +#import "U1Asset.h" |
541 | +#import "U1DataRepository.h" |
542 | + |
543 | @implementation U1MagicUploadDataProvider |
544 | { |
545 | ALAssetsLibrary *library; |
546 | } |
547 | |
548 | -@synthesize assetURL; |
549 | +@synthesize assetID; |
550 | |
551 | - (id)init; |
552 | { |
553 | @@ -37,7 +39,6 @@ |
554 | |
555 | - (void)dealloc; |
556 | { |
557 | - [assetURL release]; |
558 | [library release]; |
559 | [super dealloc]; |
560 | } |
561 | @@ -49,7 +50,13 @@ |
562 | |
563 | - (void)prepareDataStreamWithBlock:(void(^)(NSInputStream *dataStream, NSString *mimeType, NSUInteger length, NSError *error))block; |
564 | { |
565 | - [library assetForURL:self.assetURL resultBlock:^(ALAsset *asset) { |
566 | + __block U1Asset *u1asset; |
567 | + [[U1DataRepository sharedDataRepository] dispatchBlockWithManagedObjectContext:^(NSManagedObjectContext *context) { |
568 | + u1asset = (U1Asset *)[context objectWithID:self.assetID]; |
569 | + }]; |
570 | + NSURL *url = [NSURL URLWithString:u1asset.url]; |
571 | + |
572 | + [library assetForURL:url resultBlock:^(ALAsset *asset) { |
573 | |
574 | if (asset == nil) |
575 | { |
576 | |
577 | === modified file 'Files/U1UploadOperation.h' |
578 | --- Files/U1UploadOperation.h 2012-08-07 14:22:21 +0000 |
579 | +++ Files/U1UploadOperation.h 2013-05-24 22:42:26 +0000 |
580 | @@ -1,5 +1,5 @@ |
581 | // |
582 | -// Copyright 2011 Canonical Ltd. |
583 | +// Copyright 2011-2013 Canonical Ltd. |
584 | // |
585 | // This program is free software: you can redistribute it and/or modify it |
586 | // under the terms of the GNU Affero General Public License version 3, |
587 | @@ -18,15 +18,13 @@ |
588 | #import "U1FilesClient.h" |
589 | |
590 | @class U1Asset; |
591 | -@class U1FileNode; |
592 | @class U1FolderNode; |
593 | @class U1LocalFileInfo; |
594 | |
595 | |
596 | @interface U1UploadOperation : NSOperation |
597 | |
598 | -@property (retain) NSURL *assetURL; |
599 | -@property (nonatomic, retain) U1FileNode *fileNode; |
600 | +@property (nonatomic, retain) NSManagedObjectID *assetID; |
601 | @property (retain) NSString *mimetype; |
602 | @property (retain) NSError *error; |
603 | @property (copy) void (^progressBlock)(long long, long long); |
604 | |
605 | === modified file 'Files/U1UploadOperation.m' |
606 | --- Files/U1UploadOperation.m 2013-05-24 22:42:26 +0000 |
607 | +++ Files/U1UploadOperation.m 2013-05-24 22:42:26 +0000 |
608 | @@ -37,7 +37,7 @@ |
609 | |
610 | @implementation U1UploadOperation |
611 | |
612 | -@synthesize executing, finished, assetURL, fileNode, mimetype, error, progressBlock, fileInfo; |
613 | +@synthesize executing, finished, assetID, mimetype, error, progressBlock, fileInfo; |
614 | |
615 | - (id)init; |
616 | { |
617 | @@ -91,12 +91,11 @@ |
618 | fileInfo.uploading = YES; |
619 | |
620 | U1MagicUploadDataProvider *dataProvider = [[[U1MagicUploadDataProvider alloc] init] autorelease]; |
621 | - dataProvider.assetURL = self.assetURL; |
622 | + dataProvider.assetID = self.assetID; |
623 | |
624 | [filesService uploadContentData:dataProvider |
625 | - forNode:self.fileNode |
626 | progressBlock:^(long long uploaded, long long totalLength) {} |
627 | - completionBlockOnMainQueue:^(NSDictionary *updatedNodeInfo, NSError *magicUploadError) { |
628 | + completionBlockOnMainQueue:^(NSDictionary *updatedNodeInfo, NSError *magicUploadError) { |
629 | |
630 | if (magicUploadError != nil) |
631 | { |
632 | @@ -104,14 +103,15 @@ |
633 | { |
634 | self.error = magicUploadError; |
635 | // Asset is gone, delete U1Asset and potentially the Node, and stop running |
636 | - // do this on the main context because self.fileNode was fetched there. |
637 | + |
638 | U1DataRepository *dataRepository = [U1DataRepository sharedDataRepository]; |
639 | [dataRepository dispatchBlockWithMainContext:^(NSManagedObjectContext *context) { |
640 | - U1Asset *assetToBeDeleted = self.fileNode.asset; |
641 | + U1Asset *assetToBeDeleted = (U1Asset*)[context objectWithID:self.assetID]; |
642 | + U1FileNode *fileNodeToBeDeleted = assetToBeDeleted.fileNode; |
643 | [context deleteObject:assetToBeDeleted]; |
644 | - if (self.fileNode.generation == nil) |
645 | + if (fileNodeToBeDeleted.generation == nil) |
646 | { |
647 | - [context deleteObject:self.fileNode]; |
648 | + [context deleteObject:fileNodeToBeDeleted]; |
649 | } |
650 | NSError *saveError; |
651 | if(![context save:&saveError]){ |
652 | @@ -123,11 +123,12 @@ |
653 | } |
654 | else |
655 | { |
656 | + NSLog(@"magic uploadError != nil and domain isn't nonexistentAsset, it's %@, code %d", magicUploadError.domain, magicUploadError.code); |
657 | // Magic upload failed, try a standard upload |
658 | U1AssetRepresenationDataProvider *newDataProvider = [[[U1AssetRepresenationDataProvider alloc] init] autorelease]; |
659 | - newDataProvider.assetURL = self.assetURL; |
660 | + newDataProvider.assetID = self.assetID; |
661 | |
662 | - [filesService uploadContentData:newDataProvider forNode:self.fileNode progressBlock:^(long long uploaded, long long totalLength) { |
663 | + [filesService uploadContentData:newDataProvider progressBlock:^(long long uploaded, long long totalLength) { |
664 | dispatch_async(dispatch_get_main_queue(), ^{ |
665 | [self.fileInfo setUploadPercentage:((double)uploaded / (double)totalLength)]; |
666 | }); |
667 | @@ -145,7 +146,14 @@ |
668 | [self.fileInfo setUploading:NO]; |
669 | [self.fileInfo setUploaded:YES]; |
670 | |
671 | - [self.fileNode updatePropertiesFromJSONDictionary:updatedNodeInfo]; |
672 | + [[U1DataRepository sharedDataRepository] dispatchBlockWithMainContext:^(NSManagedObjectContext *context) { |
673 | + U1Asset *asset = (U1Asset *)[context objectWithID:self.assetID]; |
674 | + [asset.fileNode updatePropertiesFromJSONDictionary:updatedNodeInfo]; |
675 | + NSError *saveError; |
676 | + if(![context save:&saveError]){ |
677 | + CLS_LOG(@"error saving updated properties for successfully uploaded node: err=%@", saveError); |
678 | + } |
679 | + }]; |
680 | [self finishExecuting]; |
681 | }]; |
682 | } |
683 | @@ -156,7 +164,16 @@ |
684 | [self.fileInfo setUploading:NO]; |
685 | [self.fileInfo setUploaded:YES]; |
686 | |
687 | - [self.fileNode updatePropertiesFromJSONDictionary:updatedNodeInfo]; |
688 | + [[U1DataRepository sharedDataRepository] dispatchBlockWithMainContext:^(NSManagedObjectContext *context) { |
689 | + U1Asset *asset = (U1Asset *)[context objectWithID:self.assetID]; |
690 | + [asset.fileNode updatePropertiesFromJSONDictionary:updatedNodeInfo]; |
691 | + NSError *saveError; |
692 | + if(![context save:&saveError]){ |
693 | + CLS_LOG(@"error saving updated properties for successfully magic-uploaded node: err=%@", saveError); |
694 | + } |
695 | + NSLog(@"successfully magic-uploaded and saved updated info for asset:\n%@", asset); |
696 | + |
697 | + }]; |
698 | [self finishExecuting]; |
699 | } |
700 | }]; |
701 | @@ -165,8 +182,6 @@ |
702 | |
703 | - (void)dealloc |
704 | { |
705 | - [assetURL release]; |
706 | - [fileNode release]; |
707 | [mimetype release]; |
708 | [error release]; |
709 | [progressBlock release]; |
6 -// Copyright 2011 Canonical Ltd.
7 +// Copyright 2013 Canonical Ltd.
2011-2013 instead, and more of same changes.