Statistics
| Branch: | Tag: | Revision:

root / pithos-macos / PithosContainerNode.m @ 7da4ebcc

History | View | Annotate | Download (28.2 kB)

1
//
2
//  PithosContainerNode.m
3
//  pithos-macos
4
//
5
// Copyright 2011-2012 GRNET S.A. All rights reserved.
6
//
7
// Redistribution and use in source and binary forms, with or
8
// without modification, are permitted provided that the following
9
// conditions are met:
10
// 
11
//   1. Redistributions of source code must retain the above
12
//      copyright notice, this list of conditions and the following
13
//      disclaimer.
14
// 
15
//   2. Redistributions in binary form must reproduce the above
16
//      copyright notice, this list of conditions and the following
17
//      disclaimer in the documentation and/or other materials
18
//      provided with the distribution.
19
// 
20
// THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
21
// OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
22
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
24
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
27
// USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28
// AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31
// POSSIBILITY OF SUCH DAMAGE.
32
// 
33
// The views and conclusions contained in the software and
34
// documentation are those of the authors and should not be
35
// interpreted as representing official policies, either expressed
36
// or implied, of GRNET S.A.
37

    
38
#import "PithosContainerNode.h"
39
#import "PithosObjectNode.h"
40
#import "PithosSubdirNode.h"
41
#import "ASIPithos.h"
42
#import "ASIPithosContainerRequest.h"
43
#import "ASIPithosContainer.h"
44
#import "ASIPithosObject.h"
45
#import "ASIDownloadCache.h"
46
#import "PithosUtilities.h"
47
#import "PithosContainerNodeInfoController.h"
48
#import "PithosActivityFacility.h"
49

    
50
static NSImage *sharedIcon = nil;
51

    
52
@implementation PithosContainerNode
53
@synthesize pithos, pithosContainer, prefix;
54
@synthesize policyVersioning, policyQuota;
55

    
56
+ (void)initialize {
57
	if (self == [PithosContainerNode class])
58
        sharedIcon = [[[NSWorkspace sharedWorkspace] iconForFileType:NSFileTypeForHFSTypeCode(kGenericHardDiskIcon)] retain];
59
}
60

    
61
#pragma mark -
62
#pragma mark Object Lifecycle
63

    
64
- (id)initWithPithos:(ASIPithos *)aPithos pithosContainer:(ASIPithosContainer *)aPithosContainer icon:(NSImage *)anIcon {
65
    if ((self = [super init])) {
66
        self.pithos = aPithos;
67
        self.pithosContainer = aPithosContainer;
68
        prefix = nil;
69
        self.icon = anIcon;
70
        self.childrenUpdatedNotificationName = [NSString stringWithString:@"PithosContainerNodeChildrenUpdated"];
71
    }
72
    return self;
73
}
74

    
75
- (id)initWithPithos:(ASIPithos *)aPithos pithosContainer:(ASIPithosContainer *)aPithosContainer {
76
    return [self initWithPithos:aPithos pithosContainer:aPithosContainer icon:nil];
77
}
78

    
79
- (id)initWithPithos:(ASIPithos *)aPithos containerName:(NSString *)aContainerName icon:(NSImage *)anIcon {
80
    ASIPithosContainer *container = [ASIPithosContainer container];
81
    container.name = aContainerName;
82
    return [self initWithPithos:aPithos pithosContainer:container icon:anIcon];
83
}
84

    
85
- (id)initWithPithos:(ASIPithos *)aPithos containerName:(NSString *)aContainerName {
86
    return [self initWithPithos:aPithos containerName:aContainerName icon:nil];
87
}
88

    
89
- (void)dealloc {
90
    [containerRequest clearDelegatesAndCancel];
91
    [containerRequest release];
92
    [refreshMetadataContainerRequest clearDelegatesAndCancel];
93
    [refreshMetadataContainerRequest release];
94
    [applyMetadataContainerRequest clearDelegatesAndCancel];
95
    [applyMetadataContainerRequest release];
96
    [policyQuota release];
97
    [policyVersioning release];
98
    [prefix release];
99
    [objects release];
100
    [pithosContainer release];
101
    [pithos release];
102
    [super dealloc];
103
}
104

    
105
#pragma mark -
106
#pragma mark Properties
107

    
108
- (void)setPithos:(ASIPithos *)aPithos {
109
    if (aPithos && ![aPithos isEqualTo:pithos]) {
110
        [pithos release];
111
        pithos = [aPithos retain];
112
        [url release];
113
        url = nil;
114
    }
115
}
116

    
117
- (NSString *)url {
118
    if (url == nil)
119
        url = [[NSString alloc] initWithFormat:@"%@/%@%@", 
120
               (sharingAccount ? [pithos storageURLWithAuthUser:sharingAccount] : pithos.storageURL), 
121
               pithosContainer.name, 
122
               (shared ? @"?shared" : @"")];
123
    return url;
124
}
125

    
126
- (NSArray *)children {
127
    @synchronized(self) {
128
        switch (freshness) {
129
            case PithosNodeStateFresh:
130
                break;
131
            case PithosNodeStateRefreshNeeded:
132
                freshness = PithosNodeStateRefreshing;
133
                containerRequest = [[ASIPithosContainerRequest listObjectsRequestWithPithos:pithos 
134
                                                                              containerName:pithosContainer.name 
135
                                                                                      limit:0 
136
                                                                                     marker:nil 
137
                                                                                     prefix:prefix 
138
                                                                                  delimiter:@"/" 
139
                                                                                       path:nil 
140
                                                                                       meta:nil 
141
                                                                                     shared:shared 
142
                                                                                      until:nil] retain];
143
                if (sharingAccount)
144
                    [containerRequest setRequestUserFromDefaultTo:sharingAccount withPithos:pithos];
145
                containerRequest.delegate = self;
146
                containerRequest.didFinishSelector = @selector(performRequestFinishedDelegateInBackground:);
147
                containerRequest.didFailSelector = @selector(performRequestFailedDelegateInBackground:);
148
                containerRequest.userInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys:
149
                                             [NSNumber numberWithInteger:NSOperationQueuePriorityVeryHigh], @"priority", 
150
                                             [NSNumber numberWithUnsignedInteger:10], @"retries", 
151
                                             NSStringFromSelector(@selector(containerRequestFinished:)), @"didFinishSelector", 
152
                                             NSStringFromSelector(@selector(containerRequestFailed:)), @"didFailSelector", 
153
                                             nil];
154
                if (!forcedRefresh)
155
                    containerRequest.downloadCache = [ASIDownloadCache sharedCache];
156
                [[PithosUtilities prepareRequest:containerRequest priority:NSOperationQueuePriorityVeryHigh] startAsynchronous];
157
                break;
158
            case PithosNodeStateRefreshing:
159
                break;
160
            case PithosNodeStateRefreshFinished:
161
                if (newChildren) {
162
                    [children release];
163
                    children = newChildren;
164
                    newChildren = nil;
165
                }
166
                freshness = PithosNodeStateFresh;
167
            default:
168
                break;
169
        }
170
        return children;
171
    }
172
}
173

    
174
- (NSString *)displayName {
175
    return [[pithosContainer.name copy] autorelease];
176
}
177

    
178
- (void)setDisplayName:(NSString *)aDisplayName {
179
}
180

    
181
- (NSImage *)icon {
182
    if (icon == nil) {
183
        if ([pithosContainer.name isEqualToString:@"pithos"])
184
            icon = [[[NSWorkspace sharedWorkspace] iconForFileType:NSFileTypeForHFSTypeCode(kToolbarHomeIcon)] retain];
185
        else if ([pithosContainer.name isEqualToString:@"trash"])
186
            icon = [[[NSWorkspace sharedWorkspace] iconForFileType:NSFileTypeForHFSTypeCode(kFullTrashIcon)] retain];
187
        else
188
            icon = [sharedIcon retain];
189
    }
190
    return icon;
191
}
192

    
193
- (void)setPithosContainer:(ASIPithosContainer *)aPithosContainer {
194
    if (![pithosContainer isEqualTo:aPithosContainer]) {
195
        [pithosContainer release];
196
        pithosContainer = [aPithosContainer retain];
197
    }
198
    if (pithosContainer.policy) {
199
        self.policyVersioning = [pithosContainer.policy objectForKey:@"versioning"];
200
        self.policyQuota = [NSNumber numberWithLongLong:[[pithosContainer.policy objectForKey:@"quota"] longLongValue]];
201
    } else {
202
        self.policyVersioning = @"manual";
203
        self.policyQuota = [NSNumber numberWithLongLong:0];
204
    }
205
}
206

    
207
- (void)setLimitedPithosContainer:(ASIPithosContainer *)aPithosContainer {
208
    if (![pithosContainer isEqualTo:aPithosContainer]) {
209
        self.pithosContainer.name = aPithosContainer.name;
210
        self.pithosContainer.count = aPithosContainer.count;
211
        self.pithosContainer.bytes = aPithosContainer.bytes;
212
        self.pithosContainer.lastModified = aPithosContainer.lastModified;
213
        self.pithosContainer.untilTimestamp = aPithosContainer.untilTimestamp;
214
        if (!pithosNodeInfoController) {
215
            self.pithosContainer.policy = aPithosContainer.policy;
216
            self.pithosContainer = pithosContainer;
217
        }
218
    }
219
}
220

    
221
#pragma mark -
222
#pragma mark ASIHTTPRequestDelegate
223

    
224
- (void)containerRequestFailed:(ASIPithosContainerRequest *)request {
225
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
226
    NSUInteger retries = [[containerRequest.userInfo objectForKey:@"retries"] unsignedIntegerValue];
227
    if (retries > 0) {
228
        ASIPithosContainerRequest *newContainerRequest = (ASIPithosContainerRequest *)[PithosUtilities copyRequest:containerRequest];
229
        [(NSMutableDictionary *)(newContainerRequest.userInfo)setObject:[NSNumber numberWithUnsignedInteger:(--retries)] forKey:@"retries"];
230
        [containerRequest release];
231
        containerRequest = newContainerRequest;
232
        [[PithosUtilities prepareRequest:containerRequest priority:[[containerRequest.userInfo objectForKey:@"priority"] integerValue]] startAsynchronous];
233
    } else {
234
        NSString *message;
235
        NSError *error = [containerRequest error];
236
        if (error)
237
            message = [NSString stringWithFormat:@"Container listing failed: %@", error];
238
        else
239
            message = [NSString stringWithFormat:@"Container listing failed: (%d) %@", 
240
                       containerRequest.responseStatusCode, containerRequest.responseStatusMessage];
241
        dispatch_async(dispatch_get_main_queue(), ^{
242
            [[PithosActivityFacility defaultPithosActivityFacility] startAndEndActivityWithType:PithosActivityOther message:message];
243
        });
244
        [newChildren release];
245
        newChildren = nil;
246
        [containerRequest release];
247
        containerRequest = nil;
248
        [objects release];
249
        objects = nil;
250
        forcedRefresh = NO;
251
        @synchronized(self) {
252
            freshness = PithosNodeStateRefreshNeeded;
253
        }
254
    }
255
    [pool drain];
256
}
257

    
258
- (void)containerRequestFinished:(ASIPithosContainerRequest *)request {
259
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
260
    NSLog(@"List container finished: %@", [containerRequest url]);
261
    NSLog(@"Cached: %d", [containerRequest didUseCachedResponse]);
262
    if (containerRequest.responseStatusCode == 200) {
263
        if ((pithosContainer.blockHash == nil) || (pithosContainer.blockSize == 0)) {
264
            pithosContainer.blockHash = [containerRequest blockHash];
265
            pithosContainer.blockSize = [containerRequest blockSize];
266
        }
267
    
268
        NSArray *someObjects = [containerRequest objects];
269
        if (objects == nil) {
270
            objects = [[NSMutableArray alloc] initWithArray:someObjects];
271
        } else {
272
            [objects addObjectsFromArray:someObjects];
273
        }
274
        if ([someObjects count] < 10000) {
275
            if (!containerRequest.didUseCachedResponse || ([objects count] != [someObjects count]) || !children) {
276
                // Save new children
277
                NSLog(@"using newChildren");
278
                newChildren = [[NSMutableArray alloc] init];
279
                NSArray *objectNames = [objects valueForKey:@"name"];
280
                NSMutableIndexSet *keptNodes = [NSMutableIndexSet indexSet];
281
                BOOL isSubdirNode = ([self class] == [PithosSubdirNode class]);
282
                for (ASIPithosObject *object in objects) {
283
                    if (!isSubdirNode || 
284
                        ([object.name hasPrefix:[((PithosSubdirNode *)self).prefix stringByAppendingString:@"/"]] &&
285
                         ([object.name length] > [((PithosSubdirNode *)self).prefix length] + 1))) {
286
                        // The check above removes false objects due to trailing slash or same prefix
287
                        if (object.subdir) {
288
                            NSUInteger sameNameObjectIndex = [objectNames indexOfObject:[object.name substringToIndex:([object.name length] - 1)]];
289
                            if ((sameNameObjectIndex == NSNotFound) || 
290
                                ![PithosUtilities isContentTypeDirectory:[[objects objectAtIndex:sameNameObjectIndex] contentType]]) {
291
                                PithosSubdirNode *node = [[[PithosSubdirNode alloc] initWithPithos:pithos 
292
                                                                                   pithosContainer:pithosContainer 
293
                                                                                      pithosObject:object] autorelease];
294
                                node.parent = self;
295
                                node.shared = shared;
296
                                node.sharingAccount = sharingAccount;
297
                                if (children) {
298
                                    NSUInteger oldIndex = [children indexOfObject:node];
299
                                    if (oldIndex != NSNotFound) {
300
                                        // Use the same pointer value, if possible
301
                                        node = [children objectAtIndex:oldIndex];
302
                                        node.pithosContainer = pithosContainer;
303
//                                        node.pithosObject = object;
304
                                        [node setLimitedPithosObject:object];
305
                                        [keptNodes addIndex:oldIndex];
306
                                    }
307
                                }
308
                                if (sharingAccount)
309
                                    node.pithosObject.allowedTo = [NSString stringWithString:@"read"];
310
                                [newChildren addObject:node];
311
                            }
312
                        } else if ([PithosUtilities isContentTypeDirectory:object.contentType]) {
313
                            PithosSubdirNode *node = [[[PithosSubdirNode alloc] initWithPithos:pithos 
314
                                                                               pithosContainer:pithosContainer 
315
                                                                                  pithosObject:object] autorelease];
316
                            node.parent = self;
317
                            node.shared = shared;
318
                            node.sharingAccount = sharingAccount;
319
                            if (children) {
320
                                NSUInteger oldIndex = [children indexOfObject:node];
321
                                if (oldIndex != NSNotFound) {
322
                                    // Use the same pointer value, if possible
323
                                    node = [children objectAtIndex:oldIndex];
324
                                    node.pithosContainer = pithosContainer;
325
//                                    node.pithosObject = object;
326
                                    [node setLimitedPithosObject:object];
327
                                    [keptNodes addIndex:oldIndex];
328
                                }
329
                            }
330
                            [newChildren addObject:node];
331
                        } else {
332
                            PithosObjectNode *node = [[[PithosObjectNode alloc] initWithPithos:pithos 
333
                                                                               pithosContainer:pithosContainer 
334
                                                                                  pithosObject:object] autorelease];
335
                            node.parent = self;
336
                            node.shared = shared;
337
                            node.sharingAccount = sharingAccount;
338
                            if (children) {
339
                                NSUInteger oldIndex = [children indexOfObject:node];
340
                                if (oldIndex != NSNotFound) {
341
                                    // Use the same pointer value, if possible
342
                                    node = [children objectAtIndex:oldIndex];
343
                                    node.pithosContainer = pithosContainer;
344
//                                    node.pithosObject = object;
345
                                    [node setLimitedPithosObject:object];
346
                                    [keptNodes addIndex:oldIndex];
347
                                }
348
                            }
349
                            [newChildren addObject:node];                                
350
                        }
351
                    }
352
                }
353
                [[children objectsAtIndexes:
354
                  [[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, [children count])] indexesPassingTest:^(NSUInteger idx, BOOL *stop){
355
                    if ([keptNodes containsIndex:idx])
356
                        return NO;
357
                    return YES;
358
                }]] makeObjectsPerformSelector:@selector(pithosNodeWillBeRemoved)];
359
            }
360
            // Else cache was used and all results were fetched during this request, so existing children can be reused
361
            [containerRequest release];
362
            containerRequest = nil;
363
            [objects release];
364
            objects = nil;
365
            forcedRefresh = NO;
366
            @synchronized(self) {
367
                freshness = PithosNodeStateRefreshFinished;
368
            }
369
            if (childrenUpdatedNotificationName) {
370
                // Notify observers that children are updated
371
                [[NSNotificationCenter defaultCenter] postNotificationName:childrenUpdatedNotificationName object:self];
372
            }
373
        } else {
374
            [containerRequest release];
375
            // Do an additional request to fetch more objects
376
            containerRequest = [[ASIPithosContainerRequest listObjectsRequestWithPithos:pithos 
377
                                                                          containerName:pithosContainer.name 
378
                                                                                  limit:0 
379
                                                                                 marker:[[someObjects lastObject] name] 
380
                                                                                 prefix:prefix 
381
                                                                              delimiter:@"/" 
382
                                                                                   path:nil 
383
                                                                                   meta:nil 
384
                                                                                 shared:shared 
385
                                                                                  until:nil] retain];
386
            if (sharingAccount)
387
                [containerRequest setRequestUserFromDefaultTo:sharingAccount withPithos:pithos];
388
            containerRequest.delegate = self;
389
            containerRequest.didFinishSelector = @selector(performRequestFinishedDelegateInBackground:);
390
            containerRequest.didFailSelector = @selector(performRequestFailedDelegateInBackground:);
391
            containerRequest.userInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys:
392
                                         [NSNumber numberWithInteger:NSOperationQueuePriorityVeryHigh], @"priority", 
393
                                         [NSNumber numberWithUnsignedInteger:10], @"retries", 
394
                                         NSStringFromSelector(@selector(containerRequestFinished:)), @"didFinishSelector", 
395
                                         NSStringFromSelector(@selector(containerRequestFailed:)), @"didFailSelector", 
396
                                         nil];
397
            if (!forcedRefresh)
398
            containerRequest.downloadCache = [ASIDownloadCache sharedCache];
399
            [[PithosUtilities prepareRequest:containerRequest priority:NSOperationQueuePriorityVeryHigh] startAsynchronous];
400
        }
401
    } else if (containerRequest.responseStatusCode == 304) {
402
        // Container is not modified, so existing children can be reused
403
        [containerRequest release];
404
        containerRequest = nil;
405
        [objects release];
406
        objects = nil;
407
        forcedRefresh = NO;
408
        @synchronized(self) {
409
            freshness = PithosNodeStateRefreshFinished;
410
        }
411
        if (childrenUpdatedNotificationName) {
412
            // Notify observers that children are updated
413
            [[NSNotificationCenter defaultCenter] postNotificationName:childrenUpdatedNotificationName object:self];
414
        }
415
    } else {
416
        [self containerRequestFailed:containerRequest];
417
    }
418
    [pool drain];
419
}
420

    
421
- (void)containerMetadataRequestFinished:(ASIPithosContainerRequest *)request {
422
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
423
    NSLog(@"URL: %@", [request url]);
424
    NSLog(@"cached: %d", [request didUseCachedResponse]);
425
    
426
    if ([request isEqualTo:applyMetadataContainerRequest]) {
427
        @synchronized(self) {
428
            [applyMetadataContainerRequest release];
429
            applyMetadataContainerRequest = nil;
430
        }
431
        [self refreshInfo];
432
    } else if ([request isEqualTo:refreshMetadataContainerRequest]) {
433
        [[pithosNodeInfoController window] makeFirstResponder:nil];
434
        self.pithosContainer = [refreshMetadataContainerRequest container];
435
        @synchronized(self) {
436
            [refreshMetadataContainerRequest release];
437
            refreshMetadataContainerRequest = nil;
438
        }
439
    }
440
    [pool drain];
441
}
442

    
443
- (void)containerMetadataRequestFailed:(ASIPithosContainerRequest *)request {
444
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
445
    NSUInteger retries = [[request.userInfo objectForKey:@"retries"] unsignedIntegerValue];
446
    if (retries > 0) {
447
        ASIPithosContainerRequest *newRequest = (ASIPithosContainerRequest *)[[PithosUtilities copyRequest:request] autorelease];
448
        [(NSMutableDictionary *)(newRequest.userInfo)setObject:[NSNumber numberWithUnsignedInteger:(--retries)] forKey:@"retries"];
449
        if ([request isEqualTo:applyMetadataContainerRequest]) {
450
            @synchronized(self) {
451
                [applyMetadataContainerRequest release];
452
                applyMetadataContainerRequest = newRequest;
453
            }
454
        } else if ([request isEqualTo:refreshMetadataContainerRequest]) {
455
            @synchronized(self) {
456
                [refreshMetadataContainerRequest release];
457
                refreshMetadataContainerRequest = newRequest;
458
            }
459
        }
460
        [[PithosUtilities prepareRequest:newRequest priority:[[newRequest.userInfo objectForKey:@"priority"] integerValue]] startAsynchronous];
461
    } else {
462
        if ([request isEqualTo:applyMetadataContainerRequest]) {
463
            dispatch_async(dispatch_get_main_queue(), ^{
464
                [PithosUtilities httpRequestErrorAlertWithRequest:applyMetadataContainerRequest];
465
            });
466
            @synchronized(self) {
467
                [applyMetadataContainerRequest release];
468
                applyMetadataContainerRequest = nil;
469
            }
470
        } else if ([request isEqualTo:refreshMetadataContainerRequest]) {
471
            dispatch_async(dispatch_get_main_queue(), ^{
472
                [PithosUtilities httpRequestErrorAlertWithRequest:refreshMetadataContainerRequest];
473
            });
474
            @synchronized(self) {
475
                [refreshMetadataContainerRequest release];
476
                refreshMetadataContainerRequest = nil;
477
            }
478
        }
479
    }
480
    [pool drain];
481
}
482

    
483
#pragma mark -
484
#pragma mark Info
485

    
486
- (void)applyInfo {
487
    @synchronized(self) {
488
        if (applyMetadataContainerRequest == nil) {
489
            [[pithosNodeInfoController window] makeFirstResponder:nil];
490
            applyMetadataContainerRequest = [[ASIPithosContainerRequest updateContainerMetadataRequestWithPithos:pithos 
491
                                                                                                   containerName:pithosContainer.name 
492
                                                                                                          policy:[NSDictionary dictionaryWithObjectsAndKeys:
493
                                                                                                                  policyVersioning, @"versioning", 
494
                                                                                                                  [policyQuota stringValue], @"quota", 
495
                                                                                                                  nil] 
496
                                                                                                        metadata:pithosContainer.metadata 
497
                                                                                                          update:NO] retain];
498
            applyMetadataContainerRequest.delegate = self;
499
            applyMetadataContainerRequest.didFinishSelector = @selector(performRequestFinishedDelegateInBackground:);
500
            applyMetadataContainerRequest.didFailSelector = @selector(performRequestFailedDelegateInBackground:);
501
            applyMetadataContainerRequest.userInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys:
502
                                                      [NSNumber numberWithInteger:NSOperationQueuePriorityHigh], @"priority", 
503
                                                      [NSNumber numberWithUnsignedInteger:10], @"retries", 
504
                                                      NSStringFromSelector(@selector(containerMetadataRequestFinished:)), @"didFinishSelector", 
505
                                                      NSStringFromSelector(@selector(containerMetadataRequestFailed:)), @"didFailSelector", 
506
                                                      nil];
507
            [[PithosUtilities prepareRequest:applyMetadataContainerRequest priority:NSOperationQueuePriorityHigh] startAsynchronous];
508
        }
509
    }
510
}
511

    
512
- (void)refreshInfo {
513
    @synchronized(self) {
514
        if (refreshMetadataContainerRequest == nil) {
515
            refreshMetadataContainerRequest = [[ASIPithosContainerRequest containerMetadataRequestWithPithos:pithos 
516
                                                                                               containerName:pithosContainer.name] retain];
517
            refreshMetadataContainerRequest.delegate = self;
518
            refreshMetadataContainerRequest.didFinishSelector = @selector(performRequestFinishedDelegateInBackground:);
519
            refreshMetadataContainerRequest.didFailSelector = @selector(performRequestFailedDelegateInBackground:);
520
            refreshMetadataContainerRequest.userInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys:
521
                                                        [NSNumber numberWithInteger:NSOperationQueuePriorityHigh], @"priority", 
522
                                                        [NSNumber numberWithUnsignedInteger:10], @"retries", 
523
                                                        NSStringFromSelector(@selector(containerMetadataRequestFinished:)), @"didFinishSelector", 
524
                                                        NSStringFromSelector(@selector(containerMetadataRequestFailed:)), @"didFailSelector", 
525
                                                        nil];
526
            refreshMetadataContainerRequest.downloadCache = [ASIDownloadCache sharedCache];
527
            [[PithosUtilities prepareRequest:refreshMetadataContainerRequest priority:NSOperationQueuePriorityHigh] startAsynchronous];
528
        }
529
    }
530
}
531

    
532
#pragma mark -
533
#pragma mark Actions
534

    
535
- (void)showPithosNodeInfo:(id)sender {
536
    if (!pithosNodeInfoController) {
537
        pithosNodeInfoController = [[PithosContainerNodeInfoController alloc] initWithPithosNode:self];
538
        [self refreshInfo];
539
    }
540
    [pithosNodeInfoController showWindow:sender];
541
    [[pithosNodeInfoController window] makeKeyAndOrderFront:sender];
542
    [NSApp activateIgnoringOtherApps:YES];
543
}
544

    
545
@end