Statistics
| Branch: | Tag: | Revision:

root / pithos-macos / PithosContainerNode.m @ 46b46b83

History | View | Annotate | Download (28.1 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
        childrenUpdatedNotificationName = @"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
    [childrenUpdatedNotificationName release];
99
    [prefix release];
100
    [objects release];
101
    [pithosContainer release];
102
    [pithos release];
103
    [super dealloc];
104
}
105

    
106
#pragma mark -
107
#pragma mark Properties
108

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

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

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

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

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

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

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

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

    
222
#pragma mark -
223
#pragma mark ASIHTTPRequestDelegate
224

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

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

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

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

    
480
#pragma mark -
481
#pragma mark Info
482

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

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

    
529
#pragma mark -
530
#pragma mark Actions
531

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

    
542
@end