ibireme 9 лет назад
Родитель
Сommit
f83f8e62ea
1 измененных файлов с 33 добавлено и 11 удалено
  1. 33 11
      YYCache/YYKVStorage.m

+ 33 - 11
YYCache/YYKVStorage.m

@@ -19,6 +19,9 @@
 #import "sqlite3.h"
 #endif
 
+
+static const NSUInteger kMaxErrorRetryCount = 8;
+static const NSTimeInterval kMinRetryTimeInterval = 2.0;
 static const int kPathLengthMax = PATH_MAX - 64;
 static NSString *const kDBFileName = @"manifest.sqlite";
 static NSString *const kDBShmFileName = @"manifest.sqlite-shm";
@@ -26,6 +29,7 @@ static NSString *const kDBWalFileName = @"manifest.sqlite-wal";
 static NSString *const kDataDirectoryName = @"data";
 static NSString *const kTrashDirectoryName = @"trash";
 
+
 /*
  File:
  /path/
@@ -81,6 +85,8 @@ static UIApplication *_YYSharedApplication() {
     
     sqlite3 *_db;
     CFMutableDictionaryRef _dbStmtCache;
+    NSTimeInterval _dbLastOpenErrorTime;
+    NSUInteger _dbOpenErrorCount;
 }
 
 
@@ -94,13 +100,19 @@ static UIApplication *_YYSharedApplication() {
         CFDictionaryKeyCallBacks keyCallbacks = kCFCopyStringDictionaryKeyCallBacks;
         CFDictionaryValueCallBacks valueCallbacks = {0};
         _dbStmtCache = CFDictionaryCreateMutable(CFAllocatorGetDefault(), 0, &keyCallbacks, &valueCallbacks);
+        _dbLastOpenErrorTime = 0;
+        _dbOpenErrorCount = 0;
         return YES;
     } else {
         _db = NULL;
         if (_dbStmtCache) CFRelease(_dbStmtCache);
         _dbStmtCache = NULL;
+        _dbLastOpenErrorTime = CACurrentMediaTime();
+        _dbOpenErrorCount++;
         
-        NSLog(@"%s line:%d sqlite open failed (%d).", __FUNCTION__, __LINE__, result);
+        if (_errorLogsEnabled) {
+            NSLog(@"%s line:%d sqlite open failed (%d).", __FUNCTION__, __LINE__, result);
+        }
         return NO;
     }
 }
@@ -128,15 +140,25 @@ static UIApplication *_YYSharedApplication() {
                 }
             }
         } else if (result != SQLITE_OK) {
-            NSLog(@"%s line:%d sqlite close failed (%d).", __FUNCTION__, __LINE__, result);
+            if (_errorLogsEnabled) {
+                NSLog(@"%s line:%d sqlite close failed (%d).", __FUNCTION__, __LINE__, result);
+            }
         }
     } while (retry);
     _db = NULL;
     return YES;
 }
 
-- (BOOL)_dbIsReady {
-    return (_db);
+- (BOOL)_dbCheck {
+    if (!_db) {
+        if (_dbOpenErrorCount < kMaxErrorRetryCount &&
+            CACurrentMediaTime() - _dbLastOpenErrorTime > kMinRetryTimeInterval) {
+            return [self _dbOpen] && [self _dbInitialize];
+        } else {
+            return NO;
+        }
+    }
+    return YES;
 }
 
 - (BOOL)_dbInitialize {
@@ -145,14 +167,14 @@ static UIApplication *_YYSharedApplication() {
 }
 
 - (void)_dbCheckpoint {
-    if (![self _dbIsReady]) return;
+    if (![self _dbCheck]) return;
     // Cause a checkpoint to occur, merge `sqlite-wal` file to `sqlite` file.
     sqlite3_wal_checkpoint(_db, NULL);
 }
 
 - (BOOL)_dbExecute:(NSString *)sql {
     if (sql.length == 0) return NO;
-    if (![self _dbIsReady]) return NO;
+    if (![self _dbCheck]) return NO;
     
     char *error = NULL;
     int result = sqlite3_exec(_db, sql.UTF8String, NULL, NULL, &error);
@@ -165,7 +187,7 @@ static UIApplication *_YYSharedApplication() {
 }
 
 - (sqlite3_stmt *)_dbPrepareStmt:(NSString *)sql {
-    if (![self _dbIsReady] || sql.length == 0 || !_dbStmtCache) return NULL;
+    if (![self _dbCheck] || sql.length == 0 || !_dbStmtCache) return NULL;
     sqlite3_stmt *stmt = (sqlite3_stmt *)CFDictionaryGetValue(_dbStmtCache, (__bridge const void *)(sql));
     if (!stmt) {
         int result = sqlite3_prepare_v2(_db, sql.UTF8String, -1, &stmt, NULL);
@@ -239,7 +261,7 @@ static UIApplication *_YYSharedApplication() {
 }
 
 - (BOOL)_dbUpdateAccessTimeWithKeys:(NSArray *)keys {
-    if (![self _dbIsReady]) return NO;
+    if (![self _dbCheck]) return NO;
     int t = (int)time(NULL);
      NSString *sql = [NSString stringWithFormat:@"update manifest set last_access_time = %d where key in (%@);", t, [self _dbJoinedKeys:keys]];
     
@@ -275,7 +297,7 @@ static UIApplication *_YYSharedApplication() {
 }
 
 - (BOOL)_dbDeleteItemWithKeys:(NSArray *)keys {
-    if (![self _dbIsReady]) return NO;
+    if (![self _dbCheck]) return NO;
     NSString *sql =  [NSString stringWithFormat:@"delete from manifest where key in (%@);", [self _dbJoinedKeys:keys]];
     sqlite3_stmt *stmt = NULL;
     int result = sqlite3_prepare_v2(_db, sql.UTF8String, -1, &stmt, NULL);
@@ -362,7 +384,7 @@ static UIApplication *_YYSharedApplication() {
 }
 
 - (NSMutableArray *)_dbGetItemWithKeys:(NSArray *)keys excludeInlineData:(BOOL)excludeInlineData {
-    if (![self _dbIsReady]) return nil;
+    if (![self _dbCheck]) return nil;
     NSString *sql;
     if (excludeInlineData) {
         sql = [NSString stringWithFormat:@"select key, filename, size, modification_time, last_access_time, extended_data from manifest where key in (%@);", [self _dbJoinedKeys:keys]];
@@ -436,7 +458,7 @@ static UIApplication *_YYSharedApplication() {
 }
 
 - (NSMutableArray *)_dbGetFilenameWithKeys:(NSArray *)keys {
-    if (![self _dbIsReady]) return nil;
+    if (![self _dbCheck]) return nil;
     NSString *sql = [NSString stringWithFormat:@"select filename from manifest where key in (%@);", [self _dbJoinedKeys:keys]];
     sqlite3_stmt *stmt = NULL;
     int result = sqlite3_prepare_v2(_db, sql.UTF8String, -1, &stmt, NULL);