5 // Created by Mike Mayo on 10/21/10.
6 // The OpenStack project is provided under the Apache 2.0 license.
9 #import "AccountManager.h"
10 #import "OpenStackAccount.h"
11 #import "OpenStackRequest.h"
15 #import "StorageObject.h"
16 #import "GetContainersRequest.h"
17 #import "GetObjectsRequest.h"
18 #import "ASINetworkQueue.h"
19 #import "APICallback.h"
21 #import "OpenStackAppDelegate.h"
23 @implementation AccountManager
25 @synthesize account, queue, objectDownloadRequests;
27 #pragma mark - Callbacks
29 - (APICallback *)callbackWithRequest:(id)request success:(APIResponseBlock)success failure:(APIResponseBlock)failure {
30 APICallback *callback = [[[APICallback alloc] initWithAccount:self.account request:request] autorelease];
31 ((OpenStackRequest *)request).delegate = self;
32 ((OpenStackRequest *)request).callback = callback;
34 [request setCompletionBlock:^{
35 if ([request isSuccess]) {
43 [request setFailedBlock:^{
47 [request startAsynchronous];
51 - (APICallback *)callbackWithRequest:(id)request success:(APIResponseBlock)success {
52 return [self callbackWithRequest:request success:success failure:^(OpenStackRequest *request){}];
55 - (APICallback *)callbackWithRequest:(id)request {
56 return [self callbackWithRequest:request success:^(OpenStackRequest *request){} failure:^(OpenStackRequest *request){}];
59 #pragma mark - Notification
61 - (NSString *)notificationName:(NSString *)key identifier:(NSString *)identifier {
62 return [NSString stringWithFormat:@"%@-%@-%@", key, self.account.uuid, identifier];
65 - (void)requestFinished:(OpenStackRequest *)request {
66 NSString *notificationName = [request.userInfo objectForKey:@"notificationName"];
67 if (!notificationName)
70 id notificationObject = [request.userInfo objectForKey:@"notificationObject"];
71 if ([request isSuccess]) {
72 NSNotification *notification = [NSNotification notificationWithName:[NSString stringWithFormat:@"%@Succeeded", notificationName] object:notificationObject];
73 [[NSNotificationCenter defaultCenter] postNotification:notification];
75 NSNotification *notification = [NSNotification notificationWithName:[NSString stringWithFormat:@"%@Failed", notificationName] object:notificationObject userInfo:[NSDictionary dictionaryWithObject:request forKey:@"request"]];
76 [[NSNotificationCenter defaultCenter] postNotification:notification];
80 - (void)requestFailed:(OpenStackRequest *)request {
81 NSString *notificationName = [request.userInfo objectForKey:@"notificationName"];
82 if (!notificationName)
85 id notificationObject = [request.userInfo objectForKey:@"notificationObject"];
86 NSNotification *notification = [NSNotification notificationWithName:[NSString stringWithFormat:@"%@Failed", notificationName] object:notificationObject userInfo:[NSDictionary dictionaryWithObject:request forKey:@"request"]];
87 [[NSNotificationCenter defaultCenter] postNotification:notification];
90 - (void)notify:(NSString *)name request:(OpenStackRequest *)request {
91 NSNotification *notification = [NSNotification notificationWithName:name object:nil userInfo:[NSDictionary dictionaryWithObject:request forKey:@"request"]];
92 [[NSNotificationCenter defaultCenter] postNotification:notification];
95 - (void)notify:(NSString *)name request:(OpenStackRequest *)request object:(id)object {
96 NSNotification *notification = [NSNotification notificationWithName:name object:object userInfo:[NSDictionary dictionaryWithObject:request forKey:@"request"]];
97 [[NSNotificationCenter defaultCenter] postNotification:notification];
100 #pragma mark - API Calls
102 #pragma mark Object Storage
104 - (APICallback *)getStorageAccountInfo {
105 __block OpenStackRequest *request = [OpenStackRequest getStorageAccountInfoRequest:self.account];
106 return [self callbackWithRequest:request success:^(OpenStackRequest *request) {
107 self.account.containerCount = [[[request responseHeaders] objectForKey:@"X-Account-Container-Count"] intValue];
108 NSString *numStr = [[request responseHeaders] objectForKey:@"X-Account-Bytes-Used"];
109 self.account.totalBytesUsed = strtoull([numStr UTF8String], NULL, 0);
110 [self.account persist];
111 self.account.containerCount = [self.account.containers count];
115 - (APICallback *)getSharingAccounts {
116 __block OpenStackRequest *request = [OpenStackRequest getSharingAccountsRequest:self.account];
117 return [self callbackWithRequest:request];
120 - (APICallback *)getContainers {
121 __block OpenStackRequest *request = [OpenStackRequest filesRequest:self.account method:@"GET" path:@""];
122 return [self callbackWithRequest:request];
125 - (APICallback *)createContainer:(Container *)container {
126 __block OpenStackRequest *request = [OpenStackRequest createContainerRequest:self.account container:container];
127 return [self callbackWithRequest:request success:^(OpenStackRequest *request) {
129 [self.account.containers setObject:container forKey:container.name];
130 [self.account persist];
131 self.account.containerCount = [self.account.containers count];
135 - (APICallback *)deleteContainer:(Container *)container {
136 __block OpenStackRequest *request = [OpenStackRequest deleteContainerRequest:self.account container:container];
137 return [self callbackWithRequest:request];
141 - (void)getObjects:(Container *)container {
142 [self getObjects:container afterMarker:nil objectsBuffer:nil];
145 - (void)getObjects:(Container *)container
146 afterMarker:(NSString *)marker
147 objectsBuffer:(NSMutableDictionary *)objectsBuffer {
149 [self setQueue:(ASINetworkQueue *)[[[NSOperationQueue alloc] init] autorelease]];
151 GetObjectsRequest *request = [GetObjectsRequest request:self.account container:container marker:marker objectsBuffer:objectsBuffer];
152 [queue addOperation:request];
155 - (void)getObjectsSucceeded:(OpenStackRequest *)request {
156 if ([request isSuccess]) {
157 Container *container = [request.userInfo objectForKey:@"container"];
158 NSMutableDictionary *objects = [request objects];
159 container.rootFolder = [Folder folder];
160 container.rootFolder.objects = objects;
161 [self.account persist];
163 NSNotification *notification = [NSNotification notificationWithName:@"getObjectsSucceeded" object:self.account userInfo:[NSDictionary dictionaryWithObject:container forKey:@"container"]];
164 [[NSNotificationCenter defaultCenter] postNotification:notification];
166 NSNotification *notification = [NSNotification notificationWithName:@"getObjectsFailed" object:self.account userInfo:[NSDictionary dictionaryWithObject:request forKey:@"request"]];
167 [[NSNotificationCenter defaultCenter] postNotification:notification];
171 - (void)getObjectsFailed:(OpenStackRequest *)request {
172 NSNotification *notification = [NSNotification notificationWithName:@"getObjectsFailed" object:self.account userInfo:[NSDictionary dictionaryWithObject:request forKey:@"request"]];
173 [[NSNotificationCenter defaultCenter] postNotification:notification];
176 - (APICallback *)getContainerInfo:(Container *)container {
177 __block OpenStackRequest *request = [OpenStackRequest getContainerInfoRequest:self.account container:container];
178 return [self callbackWithRequest:request];
181 - (APICallback *)getObjectInfo:(Container *)container object:(StorageObject *)object {
182 __block OpenStackRequest *request = [OpenStackRequest getObjectInfoRequest:self.account container:container object:object];
183 return [self callbackWithRequest:request];
186 - (APICallback *)getObjectInfo:(Container *)container object:(StorageObject *)object version:(NSString *)version {
188 return [self getObjectInfo:container object:object];
190 __block OpenStackRequest *request = [OpenStackRequest getObjectInfoRequest:self.account container:container object:object version:version];
191 return [self callbackWithRequest:request];
194 - (APICallback *)getObjectVersionsList:(Container *)container object:(StorageObject *)object {
195 __block OpenStackRequest *request = [OpenStackRequest getObjectVersionsRequest:account container:container object:object];
196 return [self callbackWithRequest:request];
199 - (APICallback *)getObject:(Container *)container object:(StorageObject *)object downloadProgressDelegate:(id)downloadProgressDelegate {
200 return [self getObject:container object:object downloadProgressDelegate:downloadProgressDelegate requestUserInfo:nil];
203 - (APICallback *)getObject:(Container *)container
204 object:(StorageObject *)object
205 downloadProgressDelegate:(id)downloadProgressDelegate
206 requestUserInfo:(NSDictionary *)requestUserInfo {
208 return [self getObject:container object:object downloadProgressDelegate:downloadProgressDelegate requestUserInfo:requestUserInfo version:nil];
211 - (APICallback *)getObject:(Container *)container
212 object:(StorageObject *)object
213 downloadProgressDelegate:(id)downloadProgressDelegate
214 requestUserInfo:(NSDictionary *)requestUserInfo
215 version:(NSString *)version{
216 __block OpenStackRequest *request = [OpenStackRequest getObjectRequest:self.account container:container object:object version:version];
217 request.delegate = self;
218 request.downloadProgressDelegate = downloadProgressDelegate;
219 request.showAccurateProgress = YES;
220 if (requestUserInfo) {
221 request.userInfo = requestUserInfo;
223 if (!objectDownloadRequests)
224 self.objectDownloadRequests = [NSMutableDictionary dictionary];
225 [objectDownloadRequests setObject:request forKey:object.fullPath];
226 return [self callbackWithRequest:request success:^(OpenStackRequest *request) {
227 OpenStackAppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
228 NSString *filePath = [appDelegate.cacheDirectoryPath stringByAppendingFormat:@"/%@.%@",object.hash, object.name.pathExtension];
229 [[request responseData] writeToFile:filePath atomically:YES];
230 @synchronized(appDelegate.cachedObjectsDictionary) {
232 object.hash = [request.responseHeaders objectForKey:@"X-Object-Hash"];
233 [appDelegate.cachedObjectsDictionary setObject:filePath forKey:object.hash];
234 [appDelegate saveCacheDictionary];
236 [objectDownloadRequests removeObjectForKey:object.fullPath];
238 failure:^(OpenStackRequest *request) {
239 [objectDownloadRequests removeObjectForKey:object.fullPath];
243 - (APICallback *)writeObject:(Container *)container object:(StorageObject *)object downloadProgressDelegate:(id)downloadProgressDelegate {
244 __block OpenStackRequest *request = [OpenStackRequest writeObjectRequest:self.account container:container object:object];
245 request.delegate = self;
246 request.uploadProgressDelegate = downloadProgressDelegate;
247 request.showAccurateProgress = YES;
249 return [self callbackWithRequest:request];
252 - (APICallback *)deleteObject:(Container *)container object:(StorageObject *)object {
253 __block OpenStackRequest *request = [OpenStackRequest deleteObjectRequest:self.account container:container object:object];
254 return [self callbackWithRequest:request];
257 - (APICallback *)writeObjectMetadata:(Container *)container object:(StorageObject *)object {
258 __block OpenStackRequest *request = [OpenStackRequest writeObjectMetadataRequest:self.account container:container object:object];
259 return [self callbackWithRequest:request];
262 - (APICallback *)writeAccountMetadata:(NSDictionary *)accountInfo {
263 __block OpenStackRequest *request = [OpenStackRequest writeAccountMetadataRequest:self.account withAccountInfo:accountInfo];
264 return [self callbackWithRequest:request];
267 - (APICallback *)writeContainerPolicy:(Container *)container {
268 __block OpenStackRequest *request = [OpenStackRequest writeContainerPolicyRequest:self.account container:container];
269 return [self callbackWithRequest:request];
273 #pragma mark Memory Management
276 [objectDownloadRequests release];