Reset sync daemon local state if the client version has changed
[pithos-macos] / pithos-macos / PithosSharingAccountsNode.m
1 //
2 //  PithosAccountNode.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 "PithosSharingAccountsNode.h"
39 #import "PithosAccountNode.h"
40 #import "ASIPithosRequest.h"
41 #import "ASIPithos.h"
42 #import "ASIPithosAccount.h"
43 #import "ASIDownloadCache.h"
44 #import "PithosAccount.h"
45 #import "PithosUtilities.h"
46 #import "PithosActivityFacility.h"
47
48 @implementation PithosSharingAccountsNode
49 @synthesize pithos;
50
51 #pragma mark -
52 #pragma mark Object Lifecycle
53
54 - (id)initWithPithos:(ASIPithos *)aPithos {
55     if ((self = [super init])) {
56         pithos = aPithos;
57         self.sharingAccount = @"";
58     }
59     return self;
60 }
61
62 - (void)dealloc {
63     [sharingAccountsRequest clearDelegatesAndCancel];
64 }
65
66 #pragma mark -
67 #pragma mark Properties
68
69 - (void)setPithos:(ASIPithos *)aPithos {
70     if (aPithos && ![aPithos isEqualTo:pithos]) {
71         pithos = aPithos;
72         url = nil;
73         [sharingAccountsRequest clearDelegatesAndCancel];
74         sharingAccountsRequest = nil;
75         reset = YES;
76     }
77 }
78
79 - (NSString *)url {
80     if (url == nil) 
81         url = [pithos.storageURLPrefix copy];
82     return url;
83 }
84
85 - (NSArray *)children {
86     @synchronized(self) {
87         if (reset) {
88             [sharingAccountsRequest clearDelegatesAndCancel];
89             sharingAccountsRequest = nil;
90             children = nil;
91             newChildren = nil;
92             freshness = PithosNodeStateRefreshNeeded;
93             forcedRefresh = YES;
94             reset = NO;
95             [self postChildrenUpdatedNotificationName];
96         }
97         switch (freshness) {
98             case PithosNodeStateFresh:
99                 break;
100             case PithosNodeStateRefreshNeeded:
101                 freshness = PithosNodeStateRefreshing;
102                 sharingAccountsRequest = [ASIPithosRequest listSharingAccountsRequestWithPithos:pithos limit:0 marker:nil];
103                 sharingAccountsRequest.delegate = self;
104                 sharingAccountsRequest.didFinishSelector = @selector(performRequestFinishedDelegateInBackground:);
105                 sharingAccountsRequest.didFailSelector = @selector(performRequestFailedDelegateInBackground:);
106                 sharingAccountsRequest.userInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys:
107                                                    [NSNumber numberWithInteger:NSOperationQueuePriorityVeryHigh], @"priority", 
108                                                    [NSNumber numberWithUnsignedInteger:10], @"retries", 
109                                                    NSStringFromSelector(@selector(sharingAccountsRequestFinished:)), @"didFinishSelector", 
110                                                    NSStringFromSelector(@selector(sharingAccountsRequestFailed:)), @"didFailSelector", 
111                                                    nil];
112 //                if (!forcedRefresh)
113 //                    sharingAccountsRequest.downloadCache = [ASIDownloadCache sharedCache];
114                 [[PithosUtilities prepareRequest:sharingAccountsRequest priority:NSOperationQueuePriorityVeryHigh] startAsynchronous];
115                 break;
116             case PithosNodeStateRefreshing:
117                 break;
118             case PithosNodeStateRefreshFinished:
119                 if (newChildren) {
120                     children = newChildren;
121                     newChildren = nil;
122                 }
123                 freshness = PithosNodeStateFresh;
124             default:
125                 break;
126         }
127         return children;
128     }
129 }
130
131 - (NSString *)displayName {
132     if (displayName == nil)
133         return @"sharing accounts";
134     return [displayName copy];
135 }
136
137 #pragma mark -
138 #pragma mark ASIHTTPRequestDelegate
139
140 - (void)sharingAccountsRequestFailed:(ASIPithosRequest *)request {
141     @autoreleasepool {
142         NSString *message;
143         NSError *error = [sharingAccountsRequest error];
144         if (error)
145             message = [NSString stringWithFormat:@"Sharing accounts listing %@ failed: %@", 
146                        sharingAccountsRequest.url, [error localizedDescription]];
147         else
148             message = [NSString stringWithFormat:@"Sharing accounts listing %@ failed: (%d) %@", 
149                        sharingAccountsRequest.url, sharingAccountsRequest.responseStatusCode, sharingAccountsRequest.responseStatusMessage];
150         dispatch_async(dispatch_get_main_queue(), ^{
151             [[PithosActivityFacility defaultPithosActivityFacility] startAndEndActivityWithType:PithosActivityOther message:message];
152         });
153         NSUInteger retries = [[sharingAccountsRequest.userInfo objectForKey:@"retries"] unsignedIntegerValue];
154         if (retries > 0) {
155             ASIPithosRequest *newSharingAccountsRequest = (ASIPithosRequest *)[PithosUtilities copyRequest:sharingAccountsRequest];
156             [(NSMutableDictionary *)(newSharingAccountsRequest.userInfo)setObject:[NSNumber numberWithUnsignedInteger:(--retries)] forKey:@"retries"];
157             sharingAccountsRequest = newSharingAccountsRequest;
158             [[PithosUtilities prepareRequest:sharingAccountsRequest priority:[[sharingAccountsRequest.userInfo objectForKey:@"priority"] integerValue]] startAsynchronous];
159         } else {
160             newChildren = nil;
161             sharingAccountsRequest = nil;
162             sharingAccounts = nil;
163             forcedRefresh = NO;
164             @synchronized(self) {
165                 freshness = PithosNodeStateRefreshNeeded;
166             }
167         }
168     }
169 }
170
171 - (void)sharingAccountsRequestFinished:(ASIPithosRequest *)request {
172     @autoreleasepool {
173         DLog(@"List sharing accounts finished: %@", [sharingAccountsRequest url]);
174         DLog(@"Cached: %d", [sharingAccountsRequest didUseCachedResponse]);
175         if (sharingAccountsRequest.responseStatusCode == 200) {
176             NSArray *someSharingAccounts = [sharingAccountsRequest sharingAccounts];
177             if (sharingAccounts == nil) {
178                 sharingAccounts = [[NSMutableArray alloc] initWithArray:someSharingAccounts];
179             } else {
180                 [sharingAccounts addObjectsFromArray:someSharingAccounts];
181             }
182             if ([someSharingAccounts count] < 10000) {
183                 if (!sharingAccountsRequest.didUseCachedResponse || ([sharingAccounts count] != [someSharingAccounts count]) || !children) {
184                     // Save new children
185                     DLog(@"using newChildren");
186                     newChildren = [[NSMutableArray alloc] init];
187                     NSMutableIndexSet *keptNodes = [NSMutableIndexSet indexSet];
188                     NSMutableArray *sharingAccountsNames = [NSMutableArray arrayWithCapacity:sharingAccounts.count];
189                     for (ASIPithosAccount *account in sharingAccounts) {
190                         [sharingAccountsNames addObject:account.name];
191                         if (![account.name isEqualToString:pithos.authUser]) {
192                             PithosAccountNode *node = [[PithosAccountNode alloc] initWithPithos:pithos];
193                             node.parent = self;
194                             node.shared = shared;
195                             node.sharingAccount = account.name;
196                             node.inheritChildrenUpdatedNotificationName = inheritChildrenUpdatedNotificationName;
197                             node.pithosAccountManager = pithosAccountManager;
198                             if (children) {
199                                 NSUInteger oldIndex = [children indexOfObject:node];
200                                 if (oldIndex != NSNotFound) {
201                                     // Use the same pointer value, if possible
202                                     node = [children objectAtIndex:oldIndex];
203                                     [keptNodes addIndex:oldIndex];
204                                 }
205                             }
206                             [newChildren addObject:node];
207                         }
208                     }
209                     [pithosAccountManager updateUserCatalogForForDisplaynames:nil UUIDs:sharingAccountsNames];
210                     [[children objectsAtIndexes:
211                       [[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, [children count])] indexesPassingTest:^(NSUInteger idx, BOOL *stop){
212                         if ([keptNodes containsIndex:idx])
213                             return NO;
214                         return YES;
215                     }]] makeObjectsPerformSelector:@selector(pithosNodeWillBeRemoved)];
216                 }
217                 // Else cache was used and all results were fetched during this request, so existing children can be reused
218                 sharingAccountsRequest = nil;
219                 sharingAccounts = nil;
220                 forcedRefresh = NO;
221                 @synchronized(self) {
222                     freshness = PithosNodeStateRefreshFinished;
223                 }
224                 [self postChildrenUpdatedNotificationName];
225             } else {
226                 // Do an additional request to fetch more objects
227                 sharingAccountsRequest = [ASIPithosRequest listSharingAccountsRequestWithPithos:pithos 
228                                                                                            limit:0 
229                                                                                           marker:[[someSharingAccounts lastObject] name]];
230                 sharingAccountsRequest.delegate = self;
231                 sharingAccountsRequest.didFinishSelector = @selector(performRequestFinishedDelegateInBackground:);
232                 sharingAccountsRequest.didFailSelector = @selector(performRequestFailedDelegateInBackground:);
233                 sharingAccountsRequest.userInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys:
234                                                    [NSNumber numberWithInteger:NSOperationQueuePriorityVeryHigh], @"priority", 
235                                                    [NSNumber numberWithUnsignedInteger:10], @"retries", 
236                                                    NSStringFromSelector(@selector(sharingAccountsRequestFinished:)), @"didFinishSelector", 
237                                                    NSStringFromSelector(@selector(sharingAccountsRequestFailed:)), @"didFailSelector", 
238                                                    nil];
239 //              if (!forcedRefresh)
240 //                  sharingAccountsRequest.downloadCache = [ASIDownloadCache sharedCache];
241                 [[PithosUtilities prepareRequest:sharingAccountsRequest priority:NSOperationQueuePriorityVeryHigh] startAsynchronous];
242             }
243         } else {
244             [self sharingAccountsRequestFailed:sharingAccountsRequest];
245         }
246     }
247 }
248
249 @end