فهرست منبع

do more check on error

ibireme 9 سال پیش
والد
کامیت
ce66cec58b
3فایلهای تغییر یافته به همراه68 افزوده شده و 36 حذف شده
  1. 4 0
      YYCache/YYDiskCache.h
  2. 26 0
      YYCache/YYDiskCache.m
  3. 38 36
      YYCache/YYKVStorage.m

+ 4 - 0
YYCache/YYDiskCache.h

@@ -131,6 +131,10 @@ NS_ASSUME_NONNULL_BEGIN
  */
 @property NSTimeInterval autoTrimInterval;
 
+/**
+ Set `YES` to enable error logs for debug.
+ */
+@property BOOL errorLogsEnabled;
 
 #pragma mark - Initializer
 ///=============================================================================

+ 26 - 0
YYCache/YYDiskCache.m

@@ -11,6 +11,7 @@
 
 #import "YYDiskCache.h"
 #import "YYKVStorage.h"
+#import <UIKit/UIKit.h>
 #import <CommonCrypto/CommonCrypto.h>
 #import <objc/runtime.h>
 #import <time.h>
@@ -149,8 +150,18 @@ static void _YYDiskCacheSetGlobal(YYDiskCache *cache) {
     return filename;
 }
 
+- (void)_appWillBeTerminated {
+    Lock();
+    _kv = nil;
+    Unlock();
+}
+
 #pragma mark - public
 
+- (void)dealloc {
+    [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationWillTerminateNotification object:nil];
+}
+
 - (instancetype)init {
     @throw [NSException exceptionWithName:@"YYDiskCache init error" reason:@"YYDiskCache must be initialized with a path. Use 'initWithPath:' or 'initWithPath:inlineThreshold:' instead." userInfo:nil];
     return [self initWithPath:@"" inlineThreshold:0];
@@ -193,6 +204,8 @@ static void _YYDiskCacheSetGlobal(YYDiskCache *cache) {
     
     [self _trimRecursively];
     _YYDiskCacheSetGlobal(self);
+    
+    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_appWillBeTerminated) name:UIApplicationWillTerminateNotification object:nil];
     return self;
 }
 
@@ -429,4 +442,17 @@ static void _YYDiskCacheSetGlobal(YYDiskCache *cache) {
     else return [NSString stringWithFormat:@"<%@: %p> (%@)", self.class, self, _path];
 }
 
+- (BOOL)errorLogsEnabled {
+    Lock();
+    BOOL enabled = _kv.errorLogsEnabled;
+    Unlock();
+    return enabled;
+}
+
+- (void)setErrorLogsEnabled:(BOOL)errorLogsEnabled {
+    Lock();
+    _kv.errorLogsEnabled = errorLogsEnabled;
+    Unlock();
+}
+
 @end

+ 38 - 36
YYCache/YYKVStorage.m

@@ -27,6 +27,17 @@ static NSString *const kDataDirectoryName = @"data";
 static NSString *const kTrashDirectoryName = @"trash";
 
 /*
+ File:
+ /path/
+      /manifest.sqlite
+      /manifest.sqlite-shm
+      /manifest.sqlite-wal
+      /data/
+           /e10adc3949ba59abbe56e057f20f883e
+           /e10adc3949ba59abbe56e057f20f883e
+      /trash/
+            /unused_file_or_folder
+ 
  SQL:
  create table if not exists manifest (
     key                 text,
@@ -41,6 +52,22 @@ static NSString *const kTrashDirectoryName = @"trash";
  create index if not exists last_access_time_idx on manifest(last_access_time);
  */
 
+/// Returns nil in App Extension.
+static UIApplication *_YYSharedApplication() {
+    static BOOL isAppExtension = NO;
+    static dispatch_once_t onceToken;
+    dispatch_once(&onceToken, ^{
+        Class cls = NSClassFromString(@"UIApplication");
+        if(!cls || ![cls respondsToSelector:@selector(sharedApplication)]) isAppExtension = YES;
+        if ([[[NSBundle mainBundle] bundlePath] hasSuffix:@".appex"]) isAppExtension = YES;
+    });
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wundeclared-selector"
+    return isAppExtension ? nil : [UIApplication performSelector:@selector(sharedApplication)];
+#pragma clang diagnostic pop
+}
+
+
 @implementation YYKVStorageItem
 @end
 
@@ -54,24 +81,13 @@ static NSString *const kTrashDirectoryName = @"trash";
     
     sqlite3 *_db;
     CFMutableDictionaryRef _dbStmtCache;
-    
-    BOOL _invalidated; ///< If YES, then the db should not open again, all read/write should be ignored.
-    BOOL _dbIsClosing; ///< If YES, then the db is during closing.
 }
 
 
 #pragma mark - db
 
 - (BOOL)_dbOpen {
-    BOOL shouldOpen = YES;
-    if (_invalidated) {
-        shouldOpen = NO;
-    } else if (_dbIsClosing) {
-        shouldOpen = NO;
-    } else if (_db){
-        shouldOpen = NO;
-    }
-    if (!shouldOpen) return YES;
+    if (_db) return YES;
     
     int result = sqlite3_open(_dbPath.UTF8String, &_db);
     if (result == SQLITE_OK) {
@@ -80,23 +96,17 @@ static NSString *const kTrashDirectoryName = @"trash";
         _dbStmtCache = CFDictionaryCreateMutable(CFAllocatorGetDefault(), 0, &keyCallbacks, &valueCallbacks);
         return YES;
     } else {
+        _db = NULL;
+        if (_dbStmtCache) CFRelease(_dbStmtCache);
+        _dbStmtCache = NULL;
+        
         NSLog(@"%s line:%d sqlite open failed (%d).", __FUNCTION__, __LINE__, result);
         return NO;
     }
 }
 
 - (BOOL)_dbClose {
-    BOOL needClose = YES;
-    if (!_db) {
-        needClose = NO;
-    } else if (_invalidated) {
-        needClose = NO;
-    } else if (_dbIsClosing) {
-        needClose = NO;
-    } else {
-        _dbIsClosing = YES;
-    }
-    if (!needClose) return YES;
+    if (!_db) return YES;
     
     int  result = 0;
     BOOL retry = NO;
@@ -122,12 +132,11 @@ static NSString *const kTrashDirectoryName = @"trash";
         }
     } while (retry);
     _db = NULL;
-    _dbIsClosing = NO;
     return YES;
 }
 
 - (BOOL)_dbIsReady {
-    return (_db && !_dbIsClosing && !_invalidated);
+    return (_db);
 }
 
 - (BOOL)_dbInitialize {
@@ -580,26 +589,22 @@ static NSString *const kTrashDirectoryName = @"trash";
 #pragma mark - file
 
 - (BOOL)_fileWriteWithName:(NSString *)filename data:(NSData *)data {
-    if (_invalidated) return NO;
     NSString *path = [_dataPath stringByAppendingPathComponent:filename];
     return [data writeToFile:path atomically:NO];
 }
 
 - (NSData *)_fileReadWithName:(NSString *)filename {
-    if (_invalidated) return nil;
     NSString *path = [_dataPath stringByAppendingPathComponent:filename];
     NSData *data = [NSData dataWithContentsOfFile:path];
     return data;
 }
 
 - (BOOL)_fileDeleteWithName:(NSString *)filename {
-    if (_invalidated) return NO;
     NSString *path = [_dataPath stringByAppendingPathComponent:filename];
     return [[NSFileManager defaultManager] removeItemAtPath:path error:NULL];
 }
 
 - (BOOL)_fileMoveAllToTrash {
-    if (_invalidated) return NO;
     CFUUIDRef uuidRef = CFUUIDCreate(NULL);
     CFStringRef uuid = CFUUIDCreateString(NULL, uuidRef);
     CFRelease(uuidRef);
@@ -613,7 +618,6 @@ static NSString *const kTrashDirectoryName = @"trash";
 }
 
 - (void)_fileEmptyTrashInBackground {
-    if (_invalidated) return;
     NSString *trashPath = _trashPath;
     dispatch_queue_t queue = _trashQueue;
     dispatch_async(queue, ^{
@@ -641,10 +645,6 @@ static NSString *const kTrashDirectoryName = @"trash";
     [self _fileEmptyTrashInBackground];
 }
 
-- (void)_appWillBeTerminated {
-    _invalidated = YES;
-}
-
 #pragma mark - public
 
 - (instancetype)init {
@@ -698,13 +698,15 @@ static NSString *const kTrashDirectoryName = @"trash";
         return nil;
     }
     [self _fileEmptyTrashInBackground]; // empty the trash if failed at last time
-    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_appWillBeTerminated) name:UIApplicationWillTerminateNotification object:nil];
     return self;
 }
 
 - (void)dealloc {
-    [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationWillTerminateNotification object:nil];
+    UIBackgroundTaskIdentifier taskID = [_YYSharedApplication() beginBackgroundTaskWithExpirationHandler:^{}];
     [self _dbClose];
+    if (taskID != UIBackgroundTaskInvalid) {
+        [_YYSharedApplication() endBackgroundTask:taskID];
+    }
 }
 
 - (BOOL)saveItem:(YYKVStorageItem *)item {