|
@@ -7,49 +7,61 @@
|
|
//
|
|
//
|
|
|
|
|
|
#import "KTVHCDataUnit.h"
|
|
#import "KTVHCDataUnit.h"
|
|
-#import "KTVHCPathTool.h"
|
|
|
|
-#import "KTVHCURLTool.h"
|
|
|
|
-#import "KTVHCError.h"
|
|
|
|
|
|
+#import "KTVHCURLTools.h"
|
|
|
|
+#import "KTVHCPathTools.h"
|
|
#import "KTVHCLog.h"
|
|
#import "KTVHCLog.h"
|
|
|
|
|
|
@interface KTVHCDataUnit ()
|
|
@interface KTVHCDataUnit ()
|
|
|
|
|
|
-@property (nonatomic, strong) NSRecursiveLock *coreLock;
|
|
|
|
-@property (nonatomic, strong) NSMutableArray<KTVHCDataUnitItem *> *unitItemsInternal;
|
|
|
|
-@property (nonatomic, strong) NSMutableArray<NSArray<KTVHCDataUnitItem *> *> *lockingUnitItems;
|
|
|
|
|
|
+@property (nonatomic, strong) NSRecursiveLock * coreLock;
|
|
|
|
+@property (nonatomic, strong) NSMutableArray <KTVHCDataUnitItem *> * unitItemsInternal;
|
|
|
|
+@property (nonatomic, strong) NSMutableArray <NSArray <KTVHCDataUnitItem *> *> * lockingUnitItems;
|
|
|
|
|
|
@end
|
|
@end
|
|
|
|
|
|
@implementation KTVHCDataUnit
|
|
@implementation KTVHCDataUnit
|
|
|
|
|
|
|
|
++ (instancetype)unitWithURL:(NSURL *)URL
|
|
|
|
+{
|
|
|
|
+ return [[self alloc] initWithURL:URL];
|
|
|
|
+}
|
|
|
|
+
|
|
- (instancetype)initWithURL:(NSURL *)URL
|
|
- (instancetype)initWithURL:(NSURL *)URL
|
|
{
|
|
{
|
|
- if (self = [super init]) {
|
|
|
|
- self->_URL = [URL copy];
|
|
|
|
- self->_key = [[KTVHCURLTool tool] keyWithURL:self.URL];
|
|
|
|
- self->_createTimeInterval = [NSDate date].timeIntervalSince1970;
|
|
|
|
- [self commonInit];
|
|
|
|
|
|
+ if (self = [super init])
|
|
|
|
+ {
|
|
|
|
+ KTVHCLogAlloc(self);
|
|
|
|
+ _URL = URL;
|
|
|
|
+ _key = [KTVHCURLTools keyWithURL:self.URL];
|
|
|
|
+ _createTimeInterval = [NSDate date].timeIntervalSince1970;
|
|
|
|
+ _valid = YES;
|
|
|
|
+ [self prepare];
|
|
}
|
|
}
|
|
return self;
|
|
return self;
|
|
}
|
|
}
|
|
|
|
|
|
- (instancetype)initWithCoder:(NSCoder *)aDecoder
|
|
- (instancetype)initWithCoder:(NSCoder *)aDecoder
|
|
{
|
|
{
|
|
- if (self = [super init]) {
|
|
|
|
|
|
+ if (self = [super init])
|
|
|
|
+ {
|
|
|
|
+ KTVHCLogAlloc(self);
|
|
@try {
|
|
@try {
|
|
- self->_URL = [NSURL URLWithString:[aDecoder decodeObjectForKey:@"URLString"]];
|
|
|
|
- self->_key = [aDecoder decodeObjectForKey:@"uniqueIdentifier"];
|
|
|
|
- } @catch (NSException *exception) {
|
|
|
|
- self->_error = [KTVHCError errorForException:exception];
|
|
|
|
|
|
+ _URL = [NSURL URLWithString:[aDecoder decodeObjectForKey:@"URLString"]];
|
|
|
|
+ _key = [aDecoder decodeObjectForKey:@"uniqueIdentifier"];
|
|
|
|
+ _valid = YES;
|
|
|
|
+ } @catch (NSException * exception) {
|
|
|
|
+ _valid = NO;
|
|
}
|
|
}
|
|
@try {
|
|
@try {
|
|
- self->_createTimeInterval = [[aDecoder decodeObjectForKey:@"createTimeInterval"] doubleValue];
|
|
|
|
- self->_responseHeaders = [aDecoder decodeObjectForKey:@"responseHeaderFields"];
|
|
|
|
- self->_totalLength = [[aDecoder decodeObjectForKey:@"totalContentLength"] longLongValue];
|
|
|
|
- self->_unitItemsInternal = [[aDecoder decodeObjectForKey:@"unitItems"] mutableCopy];
|
|
|
|
- [self commonInit];
|
|
|
|
- } @catch (NSException *exception) {
|
|
|
|
- self->_error = [KTVHCError errorForException:exception];
|
|
|
|
|
|
+ _createTimeInterval = [[aDecoder decodeObjectForKey:@"createTimeInterval"] doubleValue];
|
|
|
|
+ _requestHeaders = [aDecoder decodeObjectForKey:@"requestHeaderFields"];
|
|
|
|
+ _responseHeaders = [aDecoder decodeObjectForKey:@"responseHeaderFields"];
|
|
|
|
+ _totalLength = [[aDecoder decodeObjectForKey:@"totalContentLength"] longLongValue];
|
|
|
|
+ self.unitItemsInternal = [aDecoder decodeObjectForKey:@"unitItems"];
|
|
|
|
+ [self prepare];
|
|
|
|
+ _valid = _valid && YES;
|
|
|
|
+ } @catch (NSException * exception) {
|
|
|
|
+ _valid = NO;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return self;
|
|
return self;
|
|
@@ -61,6 +73,7 @@
|
|
[aCoder encodeObject:self.URL.absoluteString forKey:@"URLString"];
|
|
[aCoder encodeObject:self.URL.absoluteString forKey:@"URLString"];
|
|
[aCoder encodeObject:self.key forKey:@"uniqueIdentifier"];
|
|
[aCoder encodeObject:self.key forKey:@"uniqueIdentifier"];
|
|
[aCoder encodeObject:@(self.createTimeInterval) forKey:@"createTimeInterval"];
|
|
[aCoder encodeObject:@(self.createTimeInterval) forKey:@"createTimeInterval"];
|
|
|
|
+ [aCoder encodeObject:self.requestHeaders forKey:@"requestHeaderFields"];
|
|
[aCoder encodeObject:self.responseHeaders forKey:@"responseHeaderFields"];
|
|
[aCoder encodeObject:self.responseHeaders forKey:@"responseHeaderFields"];
|
|
[aCoder encodeObject:@(self.totalLength) forKey:@"totalContentLength"];
|
|
[aCoder encodeObject:@(self.totalLength) forKey:@"totalContentLength"];
|
|
[aCoder encodeObject:self.unitItemsInternal forKey:@"unitItems"];
|
|
[aCoder encodeObject:self.unitItemsInternal forKey:@"unitItems"];
|
|
@@ -72,53 +85,63 @@
|
|
KTVHCLogDealloc(self);
|
|
KTVHCLogDealloc(self);
|
|
}
|
|
}
|
|
|
|
|
|
-- (void)commonInit
|
|
|
|
|
|
+- (void)prepare
|
|
{
|
|
{
|
|
- KTVHCLogAlloc(self);
|
|
|
|
[self lock];
|
|
[self lock];
|
|
- if (!self.unitItemsInternal) {
|
|
|
|
|
|
+ if (!self.unitItemsInternal)
|
|
|
|
+ {
|
|
self.unitItemsInternal = [NSMutableArray array];
|
|
self.unitItemsInternal = [NSMutableArray array];
|
|
}
|
|
}
|
|
- NSMutableArray *removal = [NSMutableArray array];
|
|
|
|
- for (KTVHCDataUnitItem *obj in self.unitItemsInternal) {
|
|
|
|
- if (obj.length == 0) {
|
|
|
|
- [KTVHCPathTool deleteFileAtPath:obj.absolutePath];
|
|
|
|
- [removal addObject:obj];
|
|
|
|
|
|
+ if (self.unitItemsInternal.count > 0)
|
|
|
|
+ {
|
|
|
|
+ NSMutableArray * removeArray = [NSMutableArray array];
|
|
|
|
+ for (KTVHCDataUnitItem * obj in self.unitItemsInternal)
|
|
|
|
+ {
|
|
|
|
+ if (obj.length <= 0)
|
|
|
|
+ {
|
|
|
|
+ [KTVHCPathTools deleteFileAtPath:obj.absolutePath];
|
|
|
|
+ [removeArray addObject:obj];
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
+ [self.unitItemsInternal removeObjectsInArray:removeArray];
|
|
|
|
+ [removeArray removeAllObjects];
|
|
|
|
+ [self sortUnitItems];
|
|
}
|
|
}
|
|
- [self.unitItemsInternal removeObjectsInArray:removal];
|
|
|
|
- [self sortUnitItems];
|
|
|
|
- KTVHCLogDataUnit(@"%p, Create Unit\nURL : %@\nkey : %@\ntimeInterval : %@\ntotalLength : %lld\ncacheLength : %lld\nvaildLength : %lld\nresponseHeaders : %@\nunitItems : %@", self, self.URL, self.key, [NSDate dateWithTimeIntervalSince1970:self.createTimeInterval], self.totalLength, self.cacheLength, self.validLength, self.responseHeaders, self.unitItemsInternal);
|
|
|
|
|
|
+ KTVHCLogDataUnit(@"%p, Create Unit\nURL : %@\nkey : %@\ntimeInterval : %@\ntotalLength : %lld\ncacheLength : %lld\nvaildLength : %lld\nrequestHeaders : %@\nresponseHeaders : %@\nunitItems : %@", self, self.URL, self.key, [NSDate dateWithTimeIntervalSince1970:self.createTimeInterval], self.totalLength, self.cacheLength, self.validLength, self.requestHeaders, self.responseHeaders, self.unitItemsInternal);
|
|
[self unlock];
|
|
[self unlock];
|
|
}
|
|
}
|
|
|
|
|
|
- (void)sortUnitItems
|
|
- (void)sortUnitItems
|
|
{
|
|
{
|
|
[self lock];
|
|
[self lock];
|
|
- KTVHCLogDataUnit(@"%p, Sort unitItems - Begin\n%@", self, self.unitItemsInternal);
|
|
|
|
- [self.unitItemsInternal sortUsingComparator:^NSComparisonResult(KTVHCDataUnitItem *obj1, KTVHCDataUnitItem *obj2) {
|
|
|
|
|
|
+ KTVHCLogDataSourceQueue(@"%p, Sort unitItems - Begin\n%@", self, self.unitItemsInternal);
|
|
|
|
+ [self.unitItemsInternal sortUsingComparator:^NSComparisonResult(KTVHCDataUnitItem * obj1, KTVHCDataUnitItem * obj2) {
|
|
NSComparisonResult result = NSOrderedDescending;
|
|
NSComparisonResult result = NSOrderedDescending;
|
|
- if (obj1.offset < obj2.offset) {
|
|
|
|
|
|
+ if (obj1.offset < obj2.offset)
|
|
|
|
+ {
|
|
result = NSOrderedAscending;
|
|
result = NSOrderedAscending;
|
|
- } else if ((obj1.offset == obj2.offset) && (obj1.length > obj2.length)) {
|
|
|
|
|
|
+ }
|
|
|
|
+ else if ((obj1.offset == obj2.offset) && (obj1.length > obj2.length))
|
|
|
|
+ {
|
|
result = NSOrderedAscending;
|
|
result = NSOrderedAscending;
|
|
}
|
|
}
|
|
return result;
|
|
return result;
|
|
}];
|
|
}];
|
|
- KTVHCLogDataUnit(@"%p, Sort unitItems - End \n%@", self, self.unitItemsInternal);
|
|
|
|
|
|
+ KTVHCLogDataSourceQueue(@"%p, Sort unitItems - End \n%@", self, self.unitItemsInternal);
|
|
[self unlock];
|
|
[self unlock];
|
|
}
|
|
}
|
|
|
|
|
|
-- (NSArray<KTVHCDataUnitItem *> *)unitItems
|
|
|
|
|
|
+- (NSArray <KTVHCDataUnitItem *> *)unitItems
|
|
{
|
|
{
|
|
[self lock];
|
|
[self lock];
|
|
- NSMutableArray *objs = [NSMutableArray array];
|
|
|
|
- for (KTVHCDataUnitItem *obj in self.unitItemsInternal) {
|
|
|
|
|
|
+ NSMutableArray * objs = [NSMutableArray array];
|
|
|
|
+ for (KTVHCDataUnitItem * obj in self.unitItemsInternal)
|
|
|
|
+ {
|
|
[objs addObject:[obj copy]];
|
|
[objs addObject:[obj copy]];
|
|
}
|
|
}
|
|
- KTVHCLogDataUnit(@"%p, Get unitItems\n%@", self, self.unitItemsInternal);
|
|
|
|
|
|
+ KTVHCLogDataSourceQueue(@"%p, Get unitItems\n%@", self, self.unitItemsInternal);
|
|
[self unlock];
|
|
[self unlock];
|
|
- return objs;
|
|
|
|
|
|
+ return [objs copy];
|
|
}
|
|
}
|
|
|
|
|
|
- (void)insertUnitItem:(KTVHCDataUnitItem *)unitItem
|
|
- (void)insertUnitItem:(KTVHCDataUnitItem *)unitItem
|
|
@@ -128,58 +151,48 @@
|
|
[self sortUnitItems];
|
|
[self sortUnitItems];
|
|
KTVHCLogDataUnit(@"%p, Insert unitItem, %@", self, unitItem);
|
|
KTVHCLogDataUnit(@"%p, Insert unitItem, %@", self, unitItem);
|
|
[self unlock];
|
|
[self unlock];
|
|
- [self.delegate ktv_unitDidChangeMetadata:self];
|
|
|
|
|
|
+ [self.fileDelegate unitShouldRearchive:self];
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+- (void)updateRequestHeaders:(NSDictionary *)requestHeaders
|
|
|
|
+{
|
|
|
|
+ [self lock];
|
|
|
|
+ _requestHeaders = requestHeaders;
|
|
|
|
+ KTVHCLogDataUnit(@"%p, Update requestHeaders\n%@", self, self.requestHeaders);
|
|
|
|
+ [self unlock];
|
|
|
|
+ [self.fileDelegate unitShouldRearchive:self];
|
|
}
|
|
}
|
|
|
|
|
|
- (void)updateResponseHeaders:(NSDictionary *)responseHeaders totalLength:(long long)totalLength
|
|
- (void)updateResponseHeaders:(NSDictionary *)responseHeaders totalLength:(long long)totalLength
|
|
{
|
|
{
|
|
[self lock];
|
|
[self lock];
|
|
- BOOL needs = NO;
|
|
|
|
- static NSArray *whiteList = nil;
|
|
|
|
- static dispatch_once_t onceToken;
|
|
|
|
- dispatch_once(&onceToken, ^{
|
|
|
|
- whiteList = @[@"Accept-Ranges",
|
|
|
|
- @"Connection",
|
|
|
|
- @"Content-Type",
|
|
|
|
- @"Server"];
|
|
|
|
- });
|
|
|
|
- NSMutableDictionary *headers = [NSMutableDictionary dictionary];
|
|
|
|
- for (NSString *key in whiteList) {
|
|
|
|
- NSString *value = [responseHeaders objectForKey:key];
|
|
|
|
- if (value) {
|
|
|
|
- [headers setObject:value forKey:key];
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- if (self.totalLength != totalLength || ![self.responseHeaders isEqualToDictionary:headers]) {
|
|
|
|
- self->_responseHeaders = headers;
|
|
|
|
- self->_totalLength = totalLength;
|
|
|
|
- needs = YES;
|
|
|
|
- }
|
|
|
|
|
|
+ _responseHeaders = responseHeaders;
|
|
|
|
+ _totalLength = totalLength;
|
|
KTVHCLogDataUnit(@"%p, Update responseHeaders\ntotalLength : %lld\n%@", self, self.totalLength, self.responseHeaders);
|
|
KTVHCLogDataUnit(@"%p, Update responseHeaders\ntotalLength : %lld\n%@", self, self.totalLength, self.responseHeaders);
|
|
[self unlock];
|
|
[self unlock];
|
|
- if (needs) {
|
|
|
|
- [self.delegate ktv_unitDidChangeMetadata:self];
|
|
|
|
- }
|
|
|
|
|
|
+ [self.fileDelegate unitShouldRearchive:self];
|
|
}
|
|
}
|
|
|
|
|
|
-- (NSURL *)completeURL
|
|
|
|
|
|
+- (NSURL *)fileURL
|
|
{
|
|
{
|
|
[self lock];
|
|
[self lock];
|
|
- NSURL *completeURL = nil;
|
|
|
|
- KTVHCDataUnitItem *item = self.unitItemsInternal.firstObject;
|
|
|
|
- if (item.offset == 0 && item.length > 0 && item.length == self.totalLength) {
|
|
|
|
- completeURL = [NSURL fileURLWithPath:item.absolutePath];
|
|
|
|
- KTVHCLogDataUnit(@"%p, Get file path\n%@", self, completeURL);
|
|
|
|
|
|
+ NSURL * fileURL = nil;
|
|
|
|
+ KTVHCDataUnitItem * item = self.unitItemsInternal.firstObject;
|
|
|
|
+ if (item.offset == 0 && item.length > 0 && item.length == self.totalLength)
|
|
|
|
+ {
|
|
|
|
+ fileURL = [NSURL fileURLWithPath:item.absolutePath];
|
|
|
|
+ KTVHCLogDataUnit(@"%p, Get file path\n%@", self, fileURL);
|
|
}
|
|
}
|
|
[self unlock];
|
|
[self unlock];
|
|
- return completeURL;
|
|
|
|
|
|
+ return fileURL;
|
|
}
|
|
}
|
|
|
|
|
|
- (long long)cacheLength
|
|
- (long long)cacheLength
|
|
{
|
|
{
|
|
[self lock];
|
|
[self lock];
|
|
long long length = 0;
|
|
long long length = 0;
|
|
- for (KTVHCDataUnitItem *obj in self.unitItemsInternal) {
|
|
|
|
|
|
+ for (KTVHCDataUnitItem * obj in self.unitItemsInternal)
|
|
|
|
+ {
|
|
length += obj.length;
|
|
length += obj.length;
|
|
}
|
|
}
|
|
[self unlock];
|
|
[self unlock];
|
|
@@ -191,7 +204,8 @@
|
|
[self lock];
|
|
[self lock];
|
|
long long offset = 0;
|
|
long long offset = 0;
|
|
long long length = 0;
|
|
long long length = 0;
|
|
- for (KTVHCDataUnitItem *obj in self.unitItemsInternal) {
|
|
|
|
|
|
+ for (KTVHCDataUnitItem * obj in self.unitItemsInternal)
|
|
|
|
+ {
|
|
long long invalidLength = MAX(offset - obj.offset, 0);
|
|
long long invalidLength = MAX(offset - obj.offset, 0);
|
|
long long vaildLength = MAX(obj.length - invalidLength, 0);
|
|
long long vaildLength = MAX(obj.length - invalidLength, 0);
|
|
offset = MAX(offset, obj.offset + obj.length);
|
|
offset = MAX(offset, obj.offset + obj.length);
|
|
@@ -205,8 +219,10 @@
|
|
{
|
|
{
|
|
[self lock];
|
|
[self lock];
|
|
NSTimeInterval timeInterval = self.createTimeInterval;
|
|
NSTimeInterval timeInterval = self.createTimeInterval;
|
|
- for (KTVHCDataUnitItem *obj in self.unitItemsInternal) {
|
|
|
|
- if (obj.createTimeInterval > timeInterval) {
|
|
|
|
|
|
+ for (KTVHCDataUnitItem * obj in self.unitItemsInternal)
|
|
|
|
+ {
|
|
|
|
+ if (obj.createTimeInterval > timeInterval)
|
|
|
|
+ {
|
|
timeInterval = obj.createTimeInterval;
|
|
timeInterval = obj.createTimeInterval;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -217,31 +233,37 @@
|
|
- (void)workingRetain
|
|
- (void)workingRetain
|
|
{
|
|
{
|
|
[self lock];
|
|
[self lock];
|
|
- self->_workingCount += 1;
|
|
|
|
|
|
+ _workingCount++;
|
|
KTVHCLogDataUnit(@"%p, Working retain : %ld", self, (long)self.workingCount);
|
|
KTVHCLogDataUnit(@"%p, Working retain : %ld", self, (long)self.workingCount);
|
|
[self unlock];
|
|
[self unlock];
|
|
}
|
|
}
|
|
|
|
|
|
- (void)workingRelease
|
|
- (void)workingRelease
|
|
{
|
|
{
|
|
|
|
+ BOOL mergeSuccess = NO;
|
|
[self lock];
|
|
[self lock];
|
|
- self->_workingCount -= 1;
|
|
|
|
|
|
+ _workingCount--;
|
|
KTVHCLogDataUnit(@"%p, Working release : %ld", self, (long)self.workingCount);
|
|
KTVHCLogDataUnit(@"%p, Working release : %ld", self, (long)self.workingCount);
|
|
- BOOL needs = [self mergeFilesIfNeeded];
|
|
|
|
|
|
+ if (self.workingCount <= 0)
|
|
|
|
+ {
|
|
|
|
+ mergeSuccess = [self mergeFilesIfNeeded];
|
|
|
|
+ }
|
|
[self unlock];
|
|
[self unlock];
|
|
- if (needs) {
|
|
|
|
- [self.delegate ktv_unitDidChangeMetadata:self];
|
|
|
|
|
|
+ if (mergeSuccess)
|
|
|
|
+ {
|
|
|
|
+ [self.fileDelegate unitShouldRearchive:self];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- (void)deleteFiles
|
|
- (void)deleteFiles
|
|
{
|
|
{
|
|
- if (!self.URL) {
|
|
|
|
|
|
+ if (!self.URL)
|
|
|
|
+ {
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
[self lock];
|
|
[self lock];
|
|
- NSString *path = [KTVHCPathTool directoryPathWithURL:self.URL];
|
|
|
|
- [KTVHCPathTool deleteDirectoryAtPath:path];
|
|
|
|
|
|
+ NSString * path = [KTVHCPathTools directoryPathWithURL:self.URL];
|
|
|
|
+ [KTVHCPathTools deleteDirectoryAtPath:path];
|
|
KTVHCLogDataUnit(@"%p, Delete files", self);
|
|
KTVHCLogDataUnit(@"%p, Delete files", self);
|
|
[self unlock];
|
|
[self unlock];
|
|
}
|
|
}
|
|
@@ -249,56 +271,72 @@
|
|
- (BOOL)mergeFilesIfNeeded
|
|
- (BOOL)mergeFilesIfNeeded
|
|
{
|
|
{
|
|
[self lock];
|
|
[self lock];
|
|
- if (self.workingCount > 0 || self.totalLength == 0 || self.unitItemsInternal.count == 0) {
|
|
|
|
|
|
+ if (self.workingCount > 0 || self.totalLength <= 0 || self.unitItemsInternal.count <= 0)
|
|
|
|
+ {
|
|
[self unlock];
|
|
[self unlock];
|
|
return NO;
|
|
return NO;
|
|
}
|
|
}
|
|
- NSString *path = [KTVHCPathTool completeFilePathWithURL:self.URL];
|
|
|
|
- if ([self.unitItemsInternal.firstObject.absolutePath isEqualToString:path]) {
|
|
|
|
|
|
+ NSString * path = [KTVHCPathTools completeFilePathWithURL:self.URL];
|
|
|
|
+ if ([self.unitItemsInternal.firstObject.absolutePath isEqualToString:path])
|
|
|
|
+ {
|
|
[self unlock];
|
|
[self unlock];
|
|
return NO;
|
|
return NO;
|
|
}
|
|
}
|
|
- if (self.totalLength != self.validLength) {
|
|
|
|
|
|
+ if (self.totalLength != self.validLength)
|
|
|
|
+ {
|
|
[self unlock];
|
|
[self unlock];
|
|
return NO;
|
|
return NO;
|
|
}
|
|
}
|
|
- NSError *error = nil;
|
|
|
|
|
|
+ BOOL failed = NO;
|
|
long long offset = 0;
|
|
long long offset = 0;
|
|
- [KTVHCPathTool deleteFileAtPath:path];
|
|
|
|
- [KTVHCPathTool createFileAtPath:path];
|
|
|
|
- NSFileHandle *writingHandle = [NSFileHandle fileHandleForWritingAtPath:path];
|
|
|
|
- for (KTVHCDataUnitItem *obj in self.unitItemsInternal) {
|
|
|
|
- if (error) {
|
|
|
|
|
|
+ [KTVHCPathTools deleteFileAtPath:path];
|
|
|
|
+ [KTVHCPathTools createFileAtPath:path];
|
|
|
|
+ NSFileHandle * writingHandle = [NSFileHandle fileHandleForWritingAtPath:path];
|
|
|
|
+ for (KTVHCDataUnitItem * obj in self.unitItemsInternal)
|
|
|
|
+ {
|
|
|
|
+ if (failed)
|
|
|
|
+ {
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
NSAssert(offset >= obj.offset, @"invaild unit item.");
|
|
NSAssert(offset >= obj.offset, @"invaild unit item.");
|
|
- if (offset >= (obj.offset + obj.length)) {
|
|
|
|
|
|
+ if (offset >= (obj.offset + obj.length))
|
|
|
|
+ {
|
|
KTVHCLogDataUnit(@"%p, Merge files continue", self);
|
|
KTVHCLogDataUnit(@"%p, Merge files continue", self);
|
|
continue;
|
|
continue;
|
|
}
|
|
}
|
|
- NSFileHandle *readingHandle = [NSFileHandle fileHandleForReadingAtPath:obj.absolutePath];
|
|
|
|
- @try {
|
|
|
|
|
|
+ NSFileHandle * readingHandle = [NSFileHandle fileHandleForReadingAtPath:obj.absolutePath];
|
|
|
|
+ @try
|
|
|
|
+ {
|
|
[readingHandle seekToFileOffset:offset - obj.offset];
|
|
[readingHandle seekToFileOffset:offset - obj.offset];
|
|
- } @catch (NSException *exception) {
|
|
|
|
|
|
+ }
|
|
|
|
+ @catch (NSException * exception)
|
|
|
|
+ {
|
|
KTVHCLogDataUnit(@"%p, Merge files seek exception\n%@", self, exception);
|
|
KTVHCLogDataUnit(@"%p, Merge files seek exception\n%@", self, exception);
|
|
- error = [KTVHCError errorForException:exception];
|
|
|
|
|
|
+ failed = YES;
|
|
}
|
|
}
|
|
- if (error) {
|
|
|
|
|
|
+ if (failed)
|
|
|
|
+ {
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
- while (!error) {
|
|
|
|
- @autoreleasepool {
|
|
|
|
- NSData *data = [readingHandle readDataOfLength:1024 * 1024 * 1];
|
|
|
|
- if (data.length == 0) {
|
|
|
|
|
|
+ while (!failed)
|
|
|
|
+ {
|
|
|
|
+ @autoreleasepool
|
|
|
|
+ {
|
|
|
|
+ NSData * data = [readingHandle readDataOfLength:1024 * 1024 * 1];
|
|
|
|
+ if (data.length <= 0)
|
|
|
|
+ {
|
|
KTVHCLogDataUnit(@"%p, Merge files break", self);
|
|
KTVHCLogDataUnit(@"%p, Merge files break", self);
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
KTVHCLogDataUnit(@"%p, Merge write data : %lld", self, (long long)data.length);
|
|
KTVHCLogDataUnit(@"%p, Merge write data : %lld", self, (long long)data.length);
|
|
- @try {
|
|
|
|
|
|
+ @try
|
|
|
|
+ {
|
|
[writingHandle writeData:data];
|
|
[writingHandle writeData:data];
|
|
- } @catch (NSException *exception) {
|
|
|
|
|
|
+ }
|
|
|
|
+ @catch (NSException * exception)
|
|
|
|
+ {
|
|
KTVHCLogDataUnit(@"%p, Merge files write exception\n%@", self, exception);
|
|
KTVHCLogDataUnit(@"%p, Merge files write exception\n%@", self, exception);
|
|
- error = [KTVHCError errorForException:exception];
|
|
|
|
|
|
+ failed = YES;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -306,23 +344,28 @@
|
|
offset = obj.offset + obj.length;
|
|
offset = obj.offset + obj.length;
|
|
KTVHCLogDataUnit(@"%p, Merge next : %lld", self, offset);
|
|
KTVHCLogDataUnit(@"%p, Merge next : %lld", self, offset);
|
|
}
|
|
}
|
|
- @try {
|
|
|
|
|
|
+ @try
|
|
|
|
+ {
|
|
[writingHandle synchronizeFile];
|
|
[writingHandle synchronizeFile];
|
|
[writingHandle closeFile];
|
|
[writingHandle closeFile];
|
|
- } @catch (NSException *exception) {
|
|
|
|
- KTVHCLogDataUnit(@"%p, Merge files close exception, %@", self, exception);
|
|
|
|
- error = [KTVHCError errorForException:exception];
|
|
|
|
|
|
+ }
|
|
|
|
+ @catch (NSException * exception)
|
|
|
|
+ {
|
|
|
|
+ KTVHCLogDataUnit(@"%p, Merge files close exception, %d\n%@", self, failed, exception);
|
|
|
|
+ failed = YES;
|
|
}
|
|
}
|
|
KTVHCLogDataUnit(@"%p, Merge finished\ntotalLength : %lld\noffset : %lld", self, self.totalLength, offset);
|
|
KTVHCLogDataUnit(@"%p, Merge finished\ntotalLength : %lld\noffset : %lld", self, self.totalLength, offset);
|
|
- if (error || [KTVHCPathTool sizeAtPath:path] != self.totalLength) {
|
|
|
|
- [KTVHCPathTool deleteFileAtPath:path];
|
|
|
|
|
|
+ if (failed || [KTVHCPathTools sizeOfItemAtPath:path] != self.totalLength)
|
|
|
|
+ {
|
|
|
|
+ [KTVHCPathTools deleteFileAtPath:path];
|
|
[self unlock];
|
|
[self unlock];
|
|
return NO;
|
|
return NO;
|
|
}
|
|
}
|
|
KTVHCLogDataUnit(@"%p, Merge replace items", self);
|
|
KTVHCLogDataUnit(@"%p, Merge replace items", self);
|
|
- KTVHCDataUnitItem *item = [[KTVHCDataUnitItem alloc] initWithPath:path];
|
|
|
|
- for (KTVHCDataUnitItem *obj in self.unitItemsInternal) {
|
|
|
|
- [KTVHCPathTool deleteFileAtPath:obj.absolutePath];
|
|
|
|
|
|
+ KTVHCDataUnitItem * item = [[KTVHCDataUnitItem alloc] initWithPath:path offset:0];
|
|
|
|
+ for (KTVHCDataUnitItem * obj in self.unitItemsInternal)
|
|
|
|
+ {
|
|
|
|
+ [KTVHCPathTools deleteFileAtPath:obj.absolutePath];
|
|
}
|
|
}
|
|
[self.unitItemsInternal removeAllObjects];
|
|
[self.unitItemsInternal removeAllObjects];
|
|
[self.unitItemsInternal addObject:item];
|
|
[self.unitItemsInternal addObject:item];
|
|
@@ -332,28 +375,33 @@
|
|
|
|
|
|
- (void)lock
|
|
- (void)lock
|
|
{
|
|
{
|
|
- if (!self.coreLock) {
|
|
|
|
|
|
+ if (!self.coreLock)
|
|
|
|
+ {
|
|
self.coreLock = [[NSRecursiveLock alloc] init];
|
|
self.coreLock = [[NSRecursiveLock alloc] init];
|
|
}
|
|
}
|
|
[self.coreLock lock];
|
|
[self.coreLock lock];
|
|
- if (!self.lockingUnitItems) {
|
|
|
|
|
|
+ if (!self.lockingUnitItems)
|
|
|
|
+ {
|
|
self.lockingUnitItems = [NSMutableArray array];
|
|
self.lockingUnitItems = [NSMutableArray array];
|
|
}
|
|
}
|
|
- NSArray<KTVHCDataUnitItem *> *objs = [NSArray arrayWithArray:self.unitItemsInternal];
|
|
|
|
|
|
+ NSArray <KTVHCDataUnitItem *> * objs = [NSArray arrayWithArray:self.unitItemsInternal];
|
|
[self.lockingUnitItems addObject:objs];
|
|
[self.lockingUnitItems addObject:objs];
|
|
- for (KTVHCDataUnitItem *obj in objs) {
|
|
|
|
|
|
+ for (KTVHCDataUnitItem * obj in objs)
|
|
|
|
+ {
|
|
[obj lock];
|
|
[obj lock];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- (void)unlock
|
|
- (void)unlock
|
|
{
|
|
{
|
|
- NSArray<KTVHCDataUnitItem *> *objs = self.lockingUnitItems.lastObject;
|
|
|
|
|
|
+ NSArray <KTVHCDataUnitItem *> * objs = self.lockingUnitItems.lastObject;
|
|
[self.lockingUnitItems removeLastObject];
|
|
[self.lockingUnitItems removeLastObject];
|
|
- if (self.lockingUnitItems.count <= 0) {
|
|
|
|
|
|
+ if (self.lockingUnitItems.count <= 0)
|
|
|
|
+ {
|
|
self.lockingUnitItems = nil;
|
|
self.lockingUnitItems = nil;
|
|
}
|
|
}
|
|
- for (KTVHCDataUnitItem *obj in objs) {
|
|
|
|
|
|
+ for (KTVHCDataUnitItem * obj in objs)
|
|
|
|
+ {
|
|
[obj unlock];
|
|
[obj unlock];
|
|
}
|
|
}
|
|
[self.coreLock unlock];
|
|
[self.coreLock unlock];
|