KTVHCDataSourceManager.m 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  1. //
  2. // KTVHCDataSourceManager.m
  3. // KTVHTTPCache
  4. //
  5. // Created by Single on 2017/8/11.
  6. // Copyright © 2017年 Single. All rights reserved.
  7. //
  8. #import "KTVHCDataSourceManager.h"
  9. #import "KTVHCDataCallback.h"
  10. #import "KTVHCLog.h"
  11. @interface KTVHCDataSourceManager () <NSLocking, KTVHCDataFileSourceDelegate, KTVHCDataNetworkSourceDelegate>
  12. @property (nonatomic, strong) NSLock *coreLock;
  13. @property (nonatomic, strong) id <KTVHCDataSource> currentSource;
  14. @property (nonatomic, strong) KTVHCDataNetworkSource *currentNetworkSource;
  15. @property (nonatomic, strong) NSMutableArray<id<KTVHCDataSource>> *sources;
  16. @property (nonatomic) BOOL calledPrepare;
  17. @property (nonatomic) BOOL calledReceiveResponse;
  18. @end
  19. @implementation KTVHCDataSourceManager
  20. @synthesize error = _error;
  21. @synthesize range = _range;
  22. @synthesize closed = _closed;
  23. @synthesize prepared = _prepared;
  24. @synthesize finished = _finished;
  25. @synthesize readedLength = _readedLength;
  26. - (instancetype)initWithSources:(NSArray<id<KTVHCDataSource>> *)sources delegate:(id<KTVHCDataSourceManagerDelegate>)delegate delegateQueue:(dispatch_queue_t)delegateQueue
  27. {
  28. if (self = [super init]) {
  29. KTVHCLogAlloc(self);
  30. self->_sources = [sources mutableCopy];
  31. self->_delegate = delegate;
  32. self->_delegateQueue = delegateQueue;
  33. self.coreLock = [[NSLock alloc] init];
  34. }
  35. return self;
  36. }
  37. - (void)dealloc
  38. {
  39. KTVHCLogDealloc(self);
  40. KTVHCLogDataReader(@"%p, Destory reader\nError : %@\ncurrentSource : %@\ncurrentNetworkSource : %@", self, self.error, self.currentSource, self.currentNetworkSource);
  41. }
  42. - (void)prepare
  43. {
  44. [self lock];
  45. if (self.isClosed) {
  46. [self unlock];
  47. return;
  48. }
  49. if (self.calledPrepare) {
  50. [self unlock];
  51. return;
  52. }
  53. self->_calledPrepare = YES;
  54. KTVHCLogDataSourceManager(@"%p, Call prepare", self);
  55. KTVHCLogDataSourceManager(@"%p, Sort sources - Begin\nSources : %@", self, self.sources);
  56. [self.sources sortUsingComparator:^NSComparisonResult(id <KTVHCDataSource> obj1, id <KTVHCDataSource> obj2) {
  57. if (obj1.range.start < obj2.range.start) {
  58. return NSOrderedAscending;
  59. }
  60. return NSOrderedDescending;
  61. }];
  62. KTVHCLogDataSourceManager(@"%p, Sort sources - End \nSources : %@", self, self.sources);
  63. for (id <KTVHCDataSource> obj in self.sources) {
  64. if ([obj isKindOfClass:[KTVHCDataFileSource class]]) {
  65. KTVHCDataFileSource *source = (KTVHCDataFileSource *)obj;
  66. [source setDelegate:self delegateQueue:self.delegateQueue];
  67. }
  68. else if ([obj isKindOfClass:[KTVHCDataNetworkSource class]]) {
  69. KTVHCDataNetworkSource *source = (KTVHCDataNetworkSource *)obj;
  70. [source setDelegate:self delegateQueue:self.delegateQueue];
  71. }
  72. }
  73. self.currentSource = self.sources.firstObject;
  74. for (id<KTVHCDataSource> obj in self.sources) {
  75. if ([obj isKindOfClass:[KTVHCDataNetworkSource class]]) {
  76. self.currentNetworkSource = obj;
  77. break;
  78. }
  79. }
  80. KTVHCLogDataSourceManager(@"%p, Sort source\ncurrentSource : %@\ncurrentNetworkSource : %@", self, self.currentSource, self.currentNetworkSource);
  81. [self.currentSource prepare];
  82. [self.currentNetworkSource prepare];
  83. [self unlock];
  84. }
  85. - (void)close
  86. {
  87. [self lock];
  88. if (self.isClosed) {
  89. [self unlock];
  90. return;
  91. }
  92. self->_closed = YES;
  93. KTVHCLogDataSourceManager(@"%p, Call close", self);
  94. for (id <KTVHCDataSource> obj in self.sources) {
  95. [obj close];
  96. }
  97. [self unlock];
  98. }
  99. - (NSData *)readDataOfLength:(NSUInteger)length
  100. {
  101. [self lock];
  102. if (self.isClosed) {
  103. [self unlock];
  104. return nil;
  105. }
  106. if (self.isFinished) {
  107. [self unlock];
  108. return nil;
  109. }
  110. if (self.error) {
  111. [self unlock];
  112. return nil;
  113. }
  114. NSData *data = [self.currentSource readDataOfLength:length];
  115. self->_readedLength += data.length;
  116. KTVHCLogDataSourceManager(@"%p, Read data : %lld", self, (long long)data.length);
  117. if (self.currentSource.isFinished) {
  118. self.currentSource = [self nextSource];
  119. if (self.currentSource) {
  120. KTVHCLogDataSourceManager(@"%p, Switch to next source, %@", self, self.currentSource);
  121. if ([self.currentSource isKindOfClass:[KTVHCDataFileSource class]]) {
  122. [self.currentSource prepare];
  123. }
  124. } else {
  125. KTVHCLogDataSourceManager(@"%p, Read data did finished", self);
  126. self->_finished = YES;
  127. }
  128. }
  129. [self unlock];
  130. return data;
  131. }
  132. - (id<KTVHCDataSource>)nextSource
  133. {
  134. NSUInteger index = [self.sources indexOfObject:self.currentSource] + 1;
  135. if (index < self.sources.count) {
  136. KTVHCLogDataSourceManager(@"%p, Fetch next source : %@", self, [self.sources objectAtIndex:index]);
  137. return [self.sources objectAtIndex:index];
  138. }
  139. KTVHCLogDataSourceManager(@"%p, Fetch netxt source failed", self);
  140. return nil;
  141. }
  142. - (KTVHCDataNetworkSource *)nextNetworkSource
  143. {
  144. NSUInteger index = [self.sources indexOfObject:self.currentNetworkSource] + 1;
  145. for (; index < self.sources.count; index++) {
  146. id <KTVHCDataSource> obj = [self.sources objectAtIndex:index];
  147. if ([obj isKindOfClass:[KTVHCDataNetworkSource class]]) {
  148. KTVHCLogDataSourceManager(@"%p, Fetch next network source : %@", self, obj);
  149. return obj;
  150. }
  151. }
  152. KTVHCLogDataSourceManager(@"%p, Fetch netxt network source failed", self);
  153. return nil;
  154. }
  155. #pragma mark - KTVHCDataFileSourceDelegate
  156. - (void)ktv_fileSourceDidPrepare:(KTVHCDataFileSource *)fileSource
  157. {
  158. [self lock];
  159. [self callbackForPrepared];
  160. [self unlock];
  161. }
  162. - (void)ktv_fileSource:(KTVHCDataFileSource *)fileSource didFailWithError:(NSError *)error
  163. {
  164. [self callbackForFailed:error];
  165. }
  166. #pragma mark - KTVHCDataNetworkSourceDelegate
  167. - (void)ktv_networkSourceDidPrepare:(KTVHCDataNetworkSource *)networkSource
  168. {
  169. [self lock];
  170. [self callbackForPrepared];
  171. [self callbackForReceiveResponse:networkSource.response];
  172. [self unlock];
  173. }
  174. - (void)ktv_networkSourceHasAvailableData:(KTVHCDataNetworkSource *)networkSource
  175. {
  176. [self lock];
  177. if ([self.delegate respondsToSelector:@selector(ktv_sourceManagerHasAvailableData:)]) {
  178. KTVHCLogDataSourceManager(@"%p, Callback for has available data - Begin\nSource : %@", self, networkSource);
  179. [KTVHCDataCallback callbackWithQueue:self.delegateQueue block:^{
  180. KTVHCLogDataSourceManager(@"%p, Callback for has available data - End", self);
  181. [self.delegate ktv_sourceManagerHasAvailableData:self];
  182. }];
  183. }
  184. [self unlock];
  185. }
  186. - (void)ktv_networkSourceDidFinisheDownload:(KTVHCDataNetworkSource *)networkSource
  187. {
  188. [self lock];
  189. self.currentNetworkSource = [self nextNetworkSource];
  190. [self.currentNetworkSource prepare];
  191. [self unlock];
  192. }
  193. - (void)ktv_networkSource:(KTVHCDataNetworkSource *)networkSource didFailWithError:(NSError *)error
  194. {
  195. [self callbackForFailed:error];
  196. }
  197. #pragma mark - Callback
  198. - (void)callbackForPrepared
  199. {
  200. if (self.isClosed) {
  201. return;
  202. }
  203. if (self.isPrepared) {
  204. return;
  205. }
  206. self->_prepared = YES;
  207. if ([self.delegate respondsToSelector:@selector(ktv_sourceManagerDidPrepare:)]) {
  208. KTVHCLogDataSourceManager(@"%p, Callback for prepared - Begin", self);
  209. [KTVHCDataCallback callbackWithQueue:self.delegateQueue block:^{
  210. KTVHCLogDataSourceManager(@"%p, Callback for prepared - End", self);
  211. [self.delegate ktv_sourceManagerDidPrepare:self];
  212. }];
  213. }
  214. }
  215. - (void)callbackForReceiveResponse:(KTVHCDataResponse *)response
  216. {
  217. if (self.isClosed) {
  218. return;
  219. }
  220. if (self.calledReceiveResponse) {
  221. return;
  222. }
  223. self->_calledReceiveResponse = YES;
  224. if ([self.delegate respondsToSelector:@selector(ktv_sourceManager:didReceiveResponse:)]) {
  225. KTVHCLogDataSourceManager(@"%p, Callback for did receive response - End", self);
  226. [KTVHCDataCallback callbackWithQueue:self.delegateQueue block:^{
  227. KTVHCLogDataSourceManager(@"%p, Callback for did receive response - End", self);
  228. [self.delegate ktv_sourceManager:self didReceiveResponse:response];
  229. }];
  230. }
  231. }
  232. - (void)callbackForFailed:(NSError *)error
  233. {
  234. if (!error) {
  235. return;
  236. }
  237. [self lock];
  238. if (self.isClosed) {
  239. [self unlock];
  240. return;
  241. }
  242. if (self.error) {
  243. [self unlock];
  244. return;
  245. }
  246. self->_error = error;
  247. KTVHCLogDataSourceManager(@"failure, %d", (int)self.error.code);
  248. if (self.error && [self.delegate respondsToSelector:@selector(ktv_sourceManager:didFailWithError:)]) {
  249. KTVHCLogDataSourceManager(@"%p, Callback for network source failed - Begin\nError : %@", self, self.error);
  250. [KTVHCDataCallback callbackWithQueue:self.delegateQueue block:^{
  251. KTVHCLogDataSourceManager(@"%p, Callback for network source failed - End", self);
  252. [self.delegate ktv_sourceManager:self didFailWithError:self.error];
  253. }];
  254. }
  255. [self unlock];
  256. }
  257. #pragma mark - NSLocking
  258. - (void)lock
  259. {
  260. [self.coreLock lock];
  261. }
  262. - (void)unlock
  263. {
  264. [self.coreLock unlock];
  265. }
  266. @end