Skip to content

Commit f5d1279

Browse files
Merge pull request #49 from ParsePlatform/richardross.filestaging.clear
Added PFFileStagingController to manage staging.
2 parents 280792a + 65b870e commit f5d1279

File tree

8 files changed

+252
-72
lines changed

8 files changed

+252
-72
lines changed

Parse.xcodeproj/project.pbxproj

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -800,6 +800,8 @@
800800
F50C66331B33A708001941A6 /* PFPushUtilities.h in Headers */ = {isa = PBXBuildFile; fileRef = F50C66311B33A708001941A6 /* PFPushUtilities.h */; };
801801
F50C66341B33A708001941A6 /* PFPushUtilities.m in Sources */ = {isa = PBXBuildFile; fileRef = F50C66321B33A708001941A6 /* PFPushUtilities.m */; };
802802
F50C667C1B34B231001941A6 /* PFPushUtilities.m in Sources */ = {isa = PBXBuildFile; fileRef = F50C66321B33A708001941A6 /* PFPushUtilities.m */; };
803+
F50E486E1B83ED270055094D /* PFFileStagingController.h in Headers */ = {isa = PBXBuildFile; fileRef = F50E486C1B83ED270055094D /* PFFileStagingController.h */; };
804+
F50E486F1B83ED270055094D /* PFFileStagingController.m in Sources */ = {isa = PBXBuildFile; fileRef = F50E486D1B83ED270055094D /* PFFileStagingController.m */; };
803805
F510509F1B6AA4CE00749060 /* ExtensionDataSharingTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 814915E61B66D44500EFD14F /* ExtensionDataSharingTests.m */; };
804806
F51050A01B6AA4D100749060 /* ExtensionDataSharingTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 814915E61B66D44500EFD14F /* ExtensionDataSharingTests.m */; };
805807
F51050A11B6AA4D600749060 /* ExtensionDataSharingMobileTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 814915E51B66D44500EFD14F /* ExtensionDataSharingMobileTests.m */; };
@@ -900,6 +902,7 @@
900902
F5C42CDB1B38761B00C720D8 /* PFObjectSubclassInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = F5C42CD81B38761B00C720D8 /* PFObjectSubclassInfo.h */; };
901903
F5C42CDC1B38761B00C720D8 /* PFObjectSubclassInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = F5C42CD91B38761B00C720D8 /* PFObjectSubclassInfo.m */; };
902904
F5C42CDD1B38761B00C720D8 /* PFObjectSubclassInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = F5C42CD91B38761B00C720D8 /* PFObjectSubclassInfo.m */; };
905+
F5C6B38B1B83F7A100690F3A /* PFFileStagingController.m in Sources */ = {isa = PBXBuildFile; fileRef = F50E486D1B83ED270055094D /* PFFileStagingController.m */; };
903906
F5C8F2C01B1F7E7800CD98E7 /* PFAsyncTaskQueue.m in Sources */ = {isa = PBXBuildFile; fileRef = F5C8F2BF1B1F7E6B00CD98E7 /* PFAsyncTaskQueue.m */; };
904907
F5C8F2C11B1F7E7900CD98E7 /* PFAsyncTaskQueue.m in Sources */ = {isa = PBXBuildFile; fileRef = F5C8F2BF1B1F7E6B00CD98E7 /* PFAsyncTaskQueue.m */; };
905908
F5E381311B68832000A3B9F2 /* URLSessionTests.m in Sources */ = {isa = PBXBuildFile; fileRef = F5556A141B66F36000410837 /* URLSessionTests.m */; };
@@ -1486,6 +1489,8 @@
14861489
E9E81E8316EEF93E001D034F /* PFSubclassing.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PFSubclassing.h; sourceTree = "<group>"; };
14871490
F50C66311B33A708001941A6 /* PFPushUtilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PFPushUtilities.h; sourceTree = "<group>"; };
14881491
F50C66321B33A708001941A6 /* PFPushUtilities.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PFPushUtilities.m; sourceTree = "<group>"; };
1492+
F50E486C1B83ED270055094D /* PFFileStagingController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PFFileStagingController.h; sourceTree = "<group>"; };
1493+
F50E486D1B83ED270055094D /* PFFileStagingController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PFFileStagingController.m; sourceTree = "<group>"; };
14891494
F51534F61B571E9100C49F56 /* PFACLPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PFACLPrivate.h; sourceTree = "<group>"; };
14901495
F51534F81B571E9100C49F56 /* PFACLState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PFACLState.h; sourceTree = "<group>"; };
14911496
F51534F91B571E9100C49F56 /* PFACLState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PFACLState.m; sourceTree = "<group>"; };
@@ -2890,6 +2895,8 @@
28902895
children = (
28912896
81EB595C1AF46434001EA1FC /* PFFileController.h */,
28922897
81EB595D1AF46434001EA1FC /* PFFileController.m */,
2898+
F50E486C1B83ED270055094D /* PFFileStagingController.h */,
2899+
F50E486D1B83ED270055094D /* PFFileStagingController.m */,
28932900
);
28942901
path = Controller;
28952902
sourceTree = "<group>";
@@ -3152,6 +3159,7 @@
31523159
F5B0B2DF1B449EEF00F3EBC4 /* PFCommandCache_Private.h in Headers */,
31533160
F5B0B2E01B449EEF00F3EBC4 /* PFCommandResult.h in Headers */,
31543161
812B02961B5DE3EE003846EE /* PFURLSession.h in Headers */,
3162+
F50E486E1B83ED270055094D /* PFFileStagingController.h in Headers */,
31553163
8166FC731B50376D003841A2 /* PFObjectController.h in Headers */,
31563164
F5B0B2EB1B449EEF00F3EBC4 /* PFAlertView.h in Headers */,
31573165
8119C9971A76E28F0085B516 /* PFNetworkCommand.h in Headers */,
@@ -4028,6 +4036,7 @@
40284036
814881471B795C63008763BF /* PFKeyValueCache.m in Sources */,
40294037
81C3825119CCAD2C0066284A /* PFNetworkActivityIndicatorManager.m in Sources */,
40304038
81C3824819CCAD2C0066284A /* PFObject.m in Sources */,
4039+
F50E486F1B83ED270055094D /* PFFileStagingController.m in Sources */,
40314040
F51D06351B792CF10044539E /* PFSQLiteDatabaseController.m in Sources */,
40324041
815960A31ABCA3B30069EBCC /* PFFileManager.m in Sources */,
40334042
81CD66561B4DA5A70042FC0B /* PFCurrentInstallationController.m in Sources */,
@@ -4195,6 +4204,7 @@
41954204
81EBF3461B33E7DE00991947 /* PFPushChannelsController.m in Sources */,
41964205
9701108A1630B45800AB761E /* PFRole.m in Sources */,
41974206
9701108C1630B45800AB761E /* PFUser.m in Sources */,
4207+
F5C6B38B1B83F7A100690F3A /* PFFileStagingController.m in Sources */,
41984208
81E7A2281B6042BD006CB680 /* PFObjectFileCodingLogic.m in Sources */,
41994209
8166FCEB1B504083003841A2 /* PFPushManager.m in Sources */,
42004210
819A4B0B1A67330200D01241 /* PFHash.m in Sources */,

Parse/Internal/File/Controller/PFFileController.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,15 @@
1616
@class BFCancellationToken;
1717
@class BFTask;
1818
@class PFFileState;
19+
@class PFFileStagingController;
1920

2021
@interface PFFileController : NSObject
2122

2223
@property (nonatomic, weak, readonly) id<PFCommandRunnerProvider, PFFileManagerProvider> dataSource;
2324

25+
@property (nonatomic, strong, readonly) PFFileStagingController *fileStagingController;
26+
2427
@property (nonatomic, copy, readonly) NSString *cacheFilesDirectoryPath;
25-
@property (nonatomic, copy, readonly) NSString *stagedFilesDirectoryPath;
2628

2729
///--------------------------------------
2830
/// @name Init

Parse/Internal/File/Controller/PFFileController.m

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -17,24 +17,27 @@
1717
#import "PFCommandResult.h"
1818
#import "PFCommandRunning.h"
1919
#import "PFFileManager.h"
20+
#import "PFFileStagingController.h"
2021
#import "PFFileState.h"
2122
#import "PFHash.h"
2223
#import "PFMacros.h"
2324
#import "PFRESTFileCommand.h"
2425

2526
static NSString *const PFFileControllerCacheDirectoryName_ = @"PFFileCache";
26-
static NSString *const PFFileControllerStagingDirectoryName_ = @"PFFileStaging";
2727

2828
@interface PFFileController () {
2929
NSMutableDictionary *_downloadTasks; // { "urlString" : BFTask }
3030
NSMutableDictionary *_downloadProgressBlocks; // { "urlString" : [ block1, block2 ] }
3131
dispatch_queue_t _downloadDataAccessQueue;
32+
dispatch_queue_t _fileStagingControllerAccessQueue;
3233
}
3334

3435
@end
3536

3637
@implementation PFFileController
3738

39+
@synthesize fileStagingController = _fileStagingController;
40+
3841
///--------------------------------------
3942
#pragma mark - Init
4043
///--------------------------------------
@@ -52,6 +55,7 @@ - (instancetype)initWithDataSource:(id<PFCommandRunnerProvider, PFFileManagerPro
5255
_downloadTasks = [NSMutableDictionary dictionary];
5356
_downloadProgressBlocks = [NSMutableDictionary dictionary];
5457
_downloadDataAccessQueue = dispatch_queue_create("com.parse.fileController.download", DISPATCH_QUEUE_SERIAL);
58+
_fileStagingControllerAccessQueue = dispatch_queue_create("com.parse.filestaging.controller.access", DISPATCH_QUEUE_SERIAL);
5559

5660
return self;
5761
}
@@ -60,6 +64,21 @@ + (instancetype)controllerWithDataSource:(id<PFCommandRunnerProvider, PFFileMana
6064
return [[self alloc] initWithDataSource:dataSource];
6165
}
6266

67+
///--------------------------------------
68+
#pragma mark - Properties
69+
///--------------------------------------
70+
71+
- (PFFileStagingController *)fileStagingController {
72+
__block PFFileStagingController *result = nil;
73+
dispatch_sync(_fileStagingControllerAccessQueue, ^{
74+
if (!_fileStagingController) {
75+
_fileStagingController = [PFFileStagingController controllerWithDataSource:self.dataSource];
76+
}
77+
result = _fileStagingController;
78+
});
79+
return result;
80+
}
81+
6382
///--------------------------------------
6483
#pragma mark - Download
6584
///--------------------------------------
@@ -244,15 +263,4 @@ - (BFTask *)clearFileCacheAsync {
244263
return [PFFileManager removeDirectoryContentsAsyncAtPath:path];
245264
}
246265

247-
///--------------------------------------
248-
#pragma mark - Staging
249-
///--------------------------------------
250-
251-
- (NSString *)stagedFilesDirectoryPath {
252-
NSString *folderPath = [self.dataSource.fileManager parseLocalSandboxDataDirectoryPath];
253-
NSString *path = [folderPath stringByAppendingPathComponent:PFFileControllerStagingDirectoryName_];
254-
[[PFFileManager createDirectoryIfNeededAsyncAtPath:path] waitForResult:nil withMainThreadWarning:NO];
255-
return path;
256-
}
257-
258266
@end
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
/**
2+
* Copyright (c) 2015-present, Parse, LLC.
3+
* All rights reserved.
4+
*
5+
* This source code is licensed under the BSD-style license found in the
6+
* LICENSE file in the root directory of this source tree. An additional grant
7+
* of patent rights can be found in the PATENTS file in the same directory.
8+
*/
9+
10+
#import <Foundation/Foundation.h>
11+
12+
#import <Bolts/BFTask.h>
13+
14+
NS_ASSUME_NONNULL_BEGIN
15+
16+
@protocol PFFileManagerProvider;
17+
18+
@interface PFFileStagingController : NSObject
19+
20+
@property (nonatomic, weak, readonly) id<PFFileManagerProvider> dataSource;
21+
22+
@property (nonatomic, copy, readonly) NSString *stagedFilesDirectoryPath;
23+
24+
///--------------------------------------
25+
/// @name Init
26+
///--------------------------------------
27+
28+
- (instancetype)init NS_UNAVAILABLE;
29+
- (instancetype)initWithDataSource:(id<PFFileManagerProvider>)dataSource NS_DESIGNATED_INITIALIZER;
30+
31+
+ (instancetype)controllerWithDataSource:(id<PFFileManagerProvider>)dataSource;
32+
33+
///--------------------------------------
34+
/// @name Staging
35+
///--------------------------------------
36+
37+
/*!
38+
Moves a file from the specified path to the staging directory based off of the name and unique ID passed in.
39+
40+
@param filePath The source path to stage
41+
@param name The name of the file to stage
42+
@param uniqueId A unique ID for this file to be used when differentiating between files with the same name.
43+
44+
@return A task, which yields the path of the staged file on disk.
45+
*/
46+
- (BFTask *)stageFileAsyncAtPath:(NSString *)filePath name:(NSString *)name uniqueId:(uint64_t)uniqueId;
47+
48+
/*!
49+
Creates a file from the specified data and places it into the staging directory based off of the name and unique
50+
ID passed in.
51+
52+
@param fileData The data to stage
53+
@param name The name of the file to stage
54+
@param uniqueId The unique ID for this file to be used when differentiating between files with the same name.
55+
56+
@return A task, which yields the path of the staged file on disk.
57+
*/
58+
- (BFTask *)stageFileAsyncWithData:(NSData *)fileData name:(NSString *)name uniqueId:(uint64_t)uniqueId;
59+
60+
/*!
61+
Get the staged directory path for a file with the specified name and unique ID.
62+
63+
@param name The name of the staged file
64+
@param uniqueId The unique ID of the staged file
65+
66+
@return The path in the staged directory folder which contains the contents of the requested file.
67+
*/
68+
- (NSString *)stagedFilePathForFileWithName:(NSString *)name uniqueId:(uint64_t)uniqueId;
69+
70+
@end
71+
72+
NS_ASSUME_NONNULL_END
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
/**
2+
* Copyright (c) 2015-present, Parse, LLC.
3+
* All rights reserved.
4+
*
5+
* This source code is licensed under the BSD-style license found in the
6+
* LICENSE file in the root directory of this source tree. An additional grant
7+
* of patent rights can be found in the PATENTS file in the same directory.
8+
*/
9+
10+
#import "PFFileStagingController.h"
11+
12+
#import "BFTask+Private.h"
13+
#import "PFAssert.h"
14+
#import "PFAsyncTaskQueue.h"
15+
#import "PFDataProvider.h"
16+
#import "PFFileManager.h"
17+
#import "PFLogging.h"
18+
19+
static NSString *const PFFileStagingControllerDirectoryName_ = @"PFFileStaging";
20+
21+
@implementation PFFileStagingController {
22+
PFAsyncTaskQueue *_taskQueue;
23+
}
24+
25+
///--------------------------------------
26+
#pragma mark - Init
27+
///--------------------------------------
28+
29+
- (instancetype)init {
30+
PFNotDesignatedInitializer();
31+
}
32+
33+
- (instancetype)initWithDataSource:(id<PFFileManagerProvider>)dataSource {
34+
self = [super init];
35+
if (!self) return nil;
36+
37+
_dataSource = dataSource;
38+
_taskQueue = [PFAsyncTaskQueue taskQueue];
39+
40+
[self _clearStagedFilesAsync];
41+
42+
return self;
43+
}
44+
45+
+ (instancetype)controllerWithDataSource:(id<PFFileManagerProvider>)dataSource {
46+
return [[self alloc] initWithDataSource:dataSource];
47+
}
48+
49+
///--------------------------------------
50+
#pragma mark - Properties
51+
///--------------------------------------
52+
53+
- (NSString *)stagedFilesDirectoryPath {
54+
NSString *folderPath = [self.dataSource.fileManager parseLocalSandboxDataDirectoryPath];
55+
return [folderPath stringByAppendingPathComponent:PFFileStagingControllerDirectoryName_];
56+
}
57+
58+
///--------------------------------------
59+
#pragma mark - Staging
60+
///--------------------------------------
61+
62+
- (BFTask *)stageFileAsyncAtPath:(NSString *)filePath name:(NSString *)name uniqueId:(uint64_t)uniqueId {
63+
return [_taskQueue enqueue:^id(BFTask *task) {
64+
return [[PFFileManager createDirectoryIfNeededAsyncAtPath:[self stagedFilesDirectoryPath]] continueWithBlock:^id(BFTask *task) {
65+
NSString *destinationPath = [self stagedFilePathForFileWithName:name uniqueId:uniqueId];
66+
return [[PFFileManager copyItemAsyncAtPath:filePath toPath:destinationPath] continueWithSuccessResult:destinationPath];
67+
}];
68+
}];
69+
}
70+
71+
- (BFTask *)stageFileAsyncWithData:(NSData *)fileData name:(NSString *)name uniqueId:(uint64_t)uniqueId {
72+
return [_taskQueue enqueue:^id(BFTask *task) {
73+
return [[PFFileManager createDirectoryIfNeededAsyncAtPath:[self stagedFilesDirectoryPath]] continueWithBlock:^id(BFTask *task) {
74+
NSString *destinationPath = [self stagedFilePathForFileWithName:name uniqueId:uniqueId];
75+
return [[PFFileManager writeDataAsync:fileData toFile:destinationPath] continueWithSuccessResult:destinationPath];
76+
}];
77+
}];
78+
}
79+
80+
- (NSString *)stagedFilePathForFileWithName:(NSString *)name uniqueId:(uint64_t)uniqueId {
81+
NSString *fileName = [NSString stringWithFormat:@"%llX_%@", uniqueId, name];
82+
return [[self stagedFilesDirectoryPath] stringByAppendingPathComponent:fileName];
83+
}
84+
85+
///--------------------------------------
86+
#pragma mark - Clearing
87+
///--------------------------------------
88+
89+
- (BFTask *)_clearStagedFilesAsync {
90+
return [_taskQueue enqueue:^id(BFTask *task) {
91+
NSString *stagedFilesDirectoryPath = [self stagedFilesDirectoryPath];
92+
return [PFFileManager removeItemAtPathAsync:stagedFilesDirectoryPath];
93+
}];
94+
}
95+
96+
@end

0 commit comments

Comments
 (0)