Revision 4a8699ab pithos-macos/PithosContainerNode.m
b/pithos-macos/PithosContainerNode.m | ||
---|---|---|
44 | 44 |
#import "ASIDownloadCache.h" |
45 | 45 |
#import "PithosUtilities.h" |
46 | 46 |
#import "PithosContainerNodeInfoController.h" |
47 |
#import "PithosActivityFacility.h" |
|
47 | 48 |
|
48 | 49 |
static NSImage *sharedIcon = nil; |
49 | 50 |
|
... | ... | |
132 | 133 |
containerRequest.delegate = self; |
133 | 134 |
containerRequest.didFinishSelector = @selector(containerRequestFinished:); |
134 | 135 |
containerRequest.didFailSelector = @selector(containerRequestFailed:); |
136 |
containerRequest.userInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys: |
|
137 |
[NSNumber numberWithUnsignedInteger:10], @"retries", |
|
138 |
nil]; |
|
135 | 139 |
if (!forcedRefresh) |
136 | 140 |
containerRequest.downloadCache = [ASIDownloadCache sharedCache]; |
137 | 141 |
[[PithosUtilities prepareRequest:containerRequest priority:NSOperationQueuePriorityVeryHigh] startAsynchronous]; |
... | ... | |
188 | 192 |
#pragma mark - |
189 | 193 |
#pragma mark ASIHTTPRequestDelegate |
190 | 194 |
|
191 |
- (void)containerRequestFinished:(ASIPithosContainerRequest *)request { |
|
192 |
NSLog(@"URL: %@", [containerRequest url]); |
|
193 |
NSLog(@"cached: %d", [containerRequest didUseCachedResponse]); |
|
194 |
|
|
195 |
if ((pithosContainer.blockHash == nil) || (pithosContainer.blockSize == 0)) { |
|
196 |
pithosContainer.blockHash = [containerRequest blockHash]; |
|
197 |
pithosContainer.blockSize = [containerRequest blockSize]; |
|
198 |
} |
|
199 |
|
|
200 |
NSArray *someObjects = [containerRequest objects]; |
|
201 |
if (objects == nil) { |
|
202 |
objects = [[NSMutableArray alloc] initWithArray:someObjects]; |
|
195 |
- (void)containerRequestFailed:(ASIPithosContainerRequest *)request { |
|
196 |
NSUInteger retries = [[containerRequest.userInfo objectForKey:@"retries"] unsignedIntegerValue]; |
|
197 |
if (retries > 0) { |
|
198 |
ASIPithosContainerRequest *newContainerRequest = (ASIPithosContainerRequest *)[PithosUtilities copyRequest:containerRequest]; |
|
199 |
[(NSMutableDictionary *)(newContainerRequest.userInfo)setObject:[NSNumber numberWithUnsignedInteger:(--retries)] forKey:@"retries"]; |
|
200 |
[containerRequest release]; |
|
201 |
containerRequest = newContainerRequest; |
|
202 |
[[PithosUtilities prepareRequest:containerRequest priority:NSOperationQueuePriorityVeryHigh] startAsynchronous]; |
|
203 | 203 |
} else { |
204 |
[objects addObjectsFromArray:someObjects]; |
|
204 |
NSString *message; |
|
205 |
NSError *error = [containerRequest error]; |
|
206 |
if (error) |
|
207 |
message = [NSString stringWithFormat:@"Container listing failed: %@", error]; |
|
208 |
else |
|
209 |
message = [NSString stringWithFormat:@"Container listing failed: (%d) %@", |
|
210 |
containerRequest.responseStatusCode, containerRequest.responseStatusMessage]; |
|
211 |
[[PithosActivityFacility defaultPithosActivityFacility] startAndEndActivityWithType:PithosActivityOther message:message]; |
|
212 |
[newChildren release]; |
|
213 |
newChildren = nil; |
|
214 |
[containerRequest release]; |
|
215 |
containerRequest = nil; |
|
216 |
[objects release]; |
|
217 |
objects = nil; |
|
218 |
forcedRefresh = NO; |
|
219 |
@synchronized(self) { |
|
220 |
freshness = PithosNodeStateRefreshNeeded; |
|
221 |
} |
|
205 | 222 |
} |
206 |
if ([someObjects count] < 10000) { |
|
207 |
if (!containerRequest.didUseCachedResponse || ([objects count] != [someObjects count]) || !children) { |
|
208 |
// Save new children |
|
209 |
NSLog(@"using newChildren"); |
|
210 |
newChildren = [[NSMutableArray alloc] init]; |
|
211 |
NSArray *objectNames = [objects valueForKey:@"name"]; |
|
212 |
NSMutableIndexSet *keptNodes = [NSMutableIndexSet indexSet]; |
|
213 |
BOOL isSubdirNode = ([self class] == [PithosSubdirNode class]); |
|
214 |
for (ASIPithosObject *object in objects) { |
|
215 |
if (!isSubdirNode || |
|
216 |
[object.name hasPrefix:[((PithosSubdirNode *)self).prefix stringByAppendingString:@"/"]]) { |
|
217 |
// The check above removes false objects due to trailing slash or same prefix |
|
218 |
if (object.subdir) { |
|
219 |
NSUInteger sameNameObjectIndex = [objectNames indexOfObject:[object.name substringToIndex:([object.name length] - 1)]]; |
|
220 |
if ((sameNameObjectIndex == NSNotFound) || |
|
221 |
![PithosUtilities isContentTypeDirectory:[[objects objectAtIndex:sameNameObjectIndex] contentType]]) { |
|
223 |
} |
|
224 |
|
|
225 |
- (void)containerRequestFinished:(ASIPithosContainerRequest *)request { |
|
226 |
NSLog(@"List container finished: %@", [containerRequest url]); |
|
227 |
NSLog(@"Cached: %d", [containerRequest didUseCachedResponse]); |
|
228 |
if (containerRequest.responseStatusCode == 200) { |
|
229 |
if ((pithosContainer.blockHash == nil) || (pithosContainer.blockSize == 0)) { |
|
230 |
pithosContainer.blockHash = [containerRequest blockHash]; |
|
231 |
pithosContainer.blockSize = [containerRequest blockSize]; |
|
232 |
} |
|
233 |
|
|
234 |
NSArray *someObjects = [containerRequest objects]; |
|
235 |
if (objects == nil) { |
|
236 |
objects = [[NSMutableArray alloc] initWithArray:someObjects]; |
|
237 |
} else { |
|
238 |
[objects addObjectsFromArray:someObjects]; |
|
239 |
} |
|
240 |
if ([someObjects count] < 10000) { |
|
241 |
if (!containerRequest.didUseCachedResponse || ([objects count] != [someObjects count]) || !children) { |
|
242 |
// Save new children |
|
243 |
NSLog(@"using newChildren"); |
|
244 |
newChildren = [[NSMutableArray alloc] init]; |
|
245 |
NSArray *objectNames = [objects valueForKey:@"name"]; |
|
246 |
NSMutableIndexSet *keptNodes = [NSMutableIndexSet indexSet]; |
|
247 |
BOOL isSubdirNode = ([self class] == [PithosSubdirNode class]); |
|
248 |
for (ASIPithosObject *object in objects) { |
|
249 |
if (!isSubdirNode || |
|
250 |
[object.name hasPrefix:[((PithosSubdirNode *)self).prefix stringByAppendingString:@"/"]]) { |
|
251 |
// The check above removes false objects due to trailing slash or same prefix |
|
252 |
if (object.subdir) { |
|
253 |
NSUInteger sameNameObjectIndex = [objectNames indexOfObject:[object.name substringToIndex:([object.name length] - 1)]]; |
|
254 |
if ((sameNameObjectIndex == NSNotFound) || |
|
255 |
![PithosUtilities isContentTypeDirectory:[[objects objectAtIndex:sameNameObjectIndex] contentType]]) { |
|
256 |
PithosSubdirNode *node = [[[PithosSubdirNode alloc] initWithPithosContainer:pithosContainer pithosObject:object] autorelease]; |
|
257 |
node.parent = self; |
|
258 |
node.shared = shared; |
|
259 |
node.sharingAccount = sharingAccount; |
|
260 |
if (children) { |
|
261 |
NSUInteger oldIndex = [children indexOfObject:node]; |
|
262 |
if (oldIndex != NSNotFound) { |
|
263 |
// Use the same pointer value, if possible |
|
264 |
node = [children objectAtIndex:oldIndex]; |
|
265 |
node.pithosContainer = pithosContainer; |
|
266 |
node.pithosObject = object; |
|
267 |
[keptNodes addIndex:oldIndex]; |
|
268 |
} |
|
269 |
} |
|
270 |
if (sharingAccount) |
|
271 |
node.pithosObject.allowedTo = [NSString stringWithString:@"read"]; |
|
272 |
[newChildren addObject:node]; |
|
273 |
} |
|
274 |
} else if ([PithosUtilities isContentTypeDirectory:object.contentType]) { |
|
222 | 275 |
PithosSubdirNode *node = [[[PithosSubdirNode alloc] initWithPithosContainer:pithosContainer pithosObject:object] autorelease]; |
223 | 276 |
node.parent = self; |
224 | 277 |
node.shared = shared; |
... | ... | |
233 | 286 |
[keptNodes addIndex:oldIndex]; |
234 | 287 |
} |
235 | 288 |
} |
236 |
if (sharingAccount) |
|
237 |
node.pithosObject.allowedTo = [NSString stringWithString:@"read"]; |
|
238 | 289 |
[newChildren addObject:node]; |
239 |
} |
|
240 |
} else if ([PithosUtilities isContentTypeDirectory:object.contentType]) { |
|
241 |
PithosSubdirNode *node = [[[PithosSubdirNode alloc] initWithPithosContainer:pithosContainer pithosObject:object] autorelease]; |
|
242 |
node.parent = self; |
|
243 |
node.shared = shared; |
|
244 |
node.sharingAccount = sharingAccount; |
|
245 |
if (children) { |
|
246 |
NSUInteger oldIndex = [children indexOfObject:node]; |
|
247 |
if (oldIndex != NSNotFound) { |
|
248 |
// Use the same pointer value, if possible |
|
249 |
node = [children objectAtIndex:oldIndex]; |
|
250 |
node.pithosContainer = pithosContainer; |
|
251 |
node.pithosObject = object; |
|
252 |
[keptNodes addIndex:oldIndex]; |
|
253 |
} |
|
254 |
} |
|
255 |
[newChildren addObject:node]; |
|
256 |
} else { |
|
257 |
PithosObjectNode *node = [[[PithosObjectNode alloc] initWithPithosContainer:pithosContainer pithosObject:object] autorelease]; |
|
258 |
node.parent = self; |
|
259 |
node.shared = shared; |
|
260 |
node.sharingAccount = sharingAccount; |
|
261 |
if (children) { |
|
262 |
NSUInteger oldIndex = [children indexOfObject:node]; |
|
263 |
if (oldIndex != NSNotFound) { |
|
264 |
// Use the same pointer value, if possible |
|
265 |
node = [children objectAtIndex:oldIndex]; |
|
266 |
node.pithosContainer = pithosContainer; |
|
267 |
node.pithosObject = object; |
|
268 |
[keptNodes addIndex:oldIndex]; |
|
290 |
} else { |
|
291 |
PithosObjectNode *node = [[[PithosObjectNode alloc] initWithPithosContainer:pithosContainer pithosObject:object] autorelease]; |
|
292 |
node.parent = self; |
|
293 |
node.shared = shared; |
|
294 |
node.sharingAccount = sharingAccount; |
|
295 |
if (children) { |
|
296 |
NSUInteger oldIndex = [children indexOfObject:node]; |
|
297 |
if (oldIndex != NSNotFound) { |
|
298 |
// Use the same pointer value, if possible |
|
299 |
node = [children objectAtIndex:oldIndex]; |
|
300 |
node.pithosContainer = pithosContainer; |
|
301 |
node.pithosObject = object; |
|
302 |
[keptNodes addIndex:oldIndex]; |
|
303 |
} |
|
269 | 304 |
} |
305 |
[newChildren addObject:node]; |
|
270 | 306 |
} |
271 |
[newChildren addObject:node]; |
|
272 | 307 |
} |
273 | 308 |
} |
309 |
[[children objectsAtIndexes: |
|
310 |
[[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, [children count])] indexesPassingTest:^(NSUInteger idx, BOOL *stop){ |
|
311 |
if ([keptNodes containsIndex:idx]) |
|
312 |
return NO; |
|
313 |
return YES; |
|
314 |
}]] makeObjectsPerformSelector:@selector(pithosNodeWillBeRemoved)]; |
|
315 |
} |
|
316 |
// Else cache was used and all results were fetched during this request, so existing children can be reused |
|
317 |
[containerRequest release]; |
|
318 |
containerRequest = nil; |
|
319 |
[objects release]; |
|
320 |
objects = nil; |
|
321 |
forcedRefresh = NO; |
|
322 |
@synchronized(self) { |
|
323 |
freshness = PithosNodeStateRefreshFinished; |
|
274 | 324 |
} |
275 |
[[children objectsAtIndexes: |
|
276 |
[[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, [children count])] indexesPassingTest:^(NSUInteger idx, BOOL *stop){ |
|
277 |
if ([keptNodes containsIndex:idx]) |
|
278 |
return NO; |
|
279 |
return YES; |
|
280 |
}]] makeObjectsPerformSelector:@selector(pithosNodeWillBeRemoved)]; |
|
325 |
// Notify observers that children are updated |
|
326 |
[[NSNotificationCenter defaultCenter] postNotificationName:childrenUpdatedNotificationName object:self]; |
|
327 |
} else { |
|
328 |
[containerRequest release]; |
|
329 |
// Do an additional request to fetch more objects |
|
330 |
containerRequest = [[ASIPithosContainerRequest listObjectsRequestWithContainerName:pithosContainer.name |
|
331 |
limit:0 |
|
332 |
marker:[[someObjects lastObject] name] |
|
333 |
prefix:prefix |
|
334 |
delimiter:@"/" |
|
335 |
path:nil |
|
336 |
meta:nil |
|
337 |
shared:shared |
|
338 |
until:nil] retain]; |
|
339 |
if (sharingAccount) |
|
340 |
[containerRequest setRequestUserFromDefaultTo:sharingAccount]; |
|
341 |
containerRequest.delegate = self; |
|
342 |
containerRequest.didFinishSelector = @selector(containerRequestFinished:); |
|
343 |
containerRequest.didFailSelector = @selector(containerRequestFailed:); |
|
344 |
containerRequest.userInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys: |
|
345 |
[NSNumber numberWithUnsignedInteger:10], @"retries", |
|
346 |
nil]; |
|
347 |
if (!forcedRefresh) |
|
348 |
containerRequest.downloadCache = [ASIDownloadCache sharedCache]; |
|
349 |
[[PithosUtilities prepareRequest:containerRequest priority:NSOperationQueuePriorityVeryHigh] startAsynchronous]; |
|
281 | 350 |
} |
282 |
// Else cache was used and all results were fetched during this request, so existing children can be reused |
|
351 |
} else if (containerRequest.responseStatusCode == 304) { |
|
352 |
// Container is not modified, so existing children can be reused |
|
283 | 353 |
[containerRequest release]; |
284 | 354 |
containerRequest = nil; |
285 | 355 |
[objects release]; |
... | ... | |
291 | 361 |
// Notify observers that children are updated |
292 | 362 |
[[NSNotificationCenter defaultCenter] postNotificationName:childrenUpdatedNotificationName object:self]; |
293 | 363 |
} else { |
294 |
[containerRequest release]; |
|
295 |
// Do an additional request to fetch more objects |
|
296 |
containerRequest = [[ASIPithosContainerRequest listObjectsRequestWithContainerName:pithosContainer.name |
|
297 |
limit:0 |
|
298 |
marker:[[someObjects lastObject] name] |
|
299 |
prefix:prefix |
|
300 |
delimiter:@"/" |
|
301 |
path:nil |
|
302 |
meta:nil |
|
303 |
shared:shared |
|
304 |
until:nil] retain]; |
|
305 |
if (sharingAccount) |
|
306 |
[containerRequest setRequestUserFromDefaultTo:sharingAccount]; |
|
307 |
containerRequest.delegate = self; |
|
308 |
if (!forcedRefresh) |
|
309 |
containerRequest.downloadCache = [ASIDownloadCache sharedCache]; |
|
310 |
[[PithosUtilities prepareRequest:containerRequest priority:NSOperationQueuePriorityVeryHigh] startAsynchronous]; |
|
311 |
} |
|
312 |
} |
|
313 |
|
|
314 |
- (void)containerRequestFailed:(ASIPithosContainerRequest *)request { |
|
315 |
[PithosUtilities httpRequestErrorAlertWithRequest:request]; |
|
316 |
[newChildren release]; |
|
317 |
newChildren = nil; |
|
318 |
[containerRequest release]; |
|
319 |
containerRequest = nil; |
|
320 |
[objects release]; |
|
321 |
objects = nil; |
|
322 |
forcedRefresh = NO; |
|
323 |
@synchronized(self) { |
|
324 |
freshness = PithosNodeStateRefreshNeeded; |
|
364 |
[self containerRequestFailed:containerRequest]; |
|
325 | 365 |
} |
326 | 366 |
} |
327 | 367 |
|
Also available in: Unified diff