Skip to content

Commit 3cd2386

Browse files
committed
[FCM] Recovery logic for a corrupt database
1 parent 45210bd commit 3cd2386

File tree

1 file changed

+31
-11
lines changed

1 file changed

+31
-11
lines changed

FirebaseMessaging/Sources/FIRMessagingRmqManager.m

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -501,7 +501,7 @@ - (void)openDatabase {
501501
#ifdef SQLITE_OPEN_FILEPROTECTION_NONE
502502
flags |= SQLITE_OPEN_FILEPROTECTION_NONE;
503503
#endif
504-
int result = sqlite3_open_v2([path UTF8String], &self -> _database, flags, NULL);
504+
int result = sqlite3_open_v2([path UTF8String], &self->_database, flags, NULL);
505505
if (result != SQLITE_OK) {
506506
NSString *errorString = FIRMessagingStringFromSQLiteResult(result);
507507
NSString *errorMessage = [NSString
@@ -517,21 +517,41 @@ - (void)openDatabase {
517517
[self createTableWithName:kTableLastRmqId command:kCreateTableLastRmqId];
518518
[self createTableWithName:kTableS2DRmqIds command:kCreateTableS2DRmqIds];
519519
} else {
520-
// Calling sqlite3_open should create the database, since the file doesn't exist.
520+
// The file exists, try to open it. If it fails, it might be corrupt.
521521
int flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
522522
#ifdef SQLITE_OPEN_FILEPROTECTION_NONE
523523
flags |= SQLITE_OPEN_FILEPROTECTION_NONE;
524524
#endif
525-
int result = sqlite3_open_v2([path UTF8String], &self -> _database, flags, NULL);
525+
int result = sqlite3_open_v2([path UTF8String], &self->_database, flags, NULL);
526+
527+
// If opening the database failed, it might be corrupt. Try to recover by deleting and
528+
// recreating it.
526529
if (result != SQLITE_OK) {
527-
NSString *errorString = FIRMessagingStringFromSQLiteResult(result);
528-
NSString *errorMessage =
529-
[NSString stringWithFormat:@"Could not create RMQ database at path %@, error: %@", path,
530-
errorString];
531-
FIRMessagingLoggerError(kFIRMessagingMessageCodeRmq2PersistentStoreErrorCreatingDatabase,
532-
@"%@", errorMessage);
533-
NSAssert(NO, errorMessage);
534-
didOpenDatabase = NO;
530+
FIRMessagingLoggerWarn(kFIRMessagingMessageCodeRmq2PersistentStoreErrorOpeningDatabase,
531+
@"Could not open RMQ database at path: %@. "
532+
"Will delete and try to recreate it.",
533+
path);
534+
[[NSFileManager defaultManager] removeItemAtPath:path error:nil];
535+
// After deleting, try to open it again.
536+
result = sqlite3_open_v2([path UTF8String], &self->_database, flags, NULL);
537+
// If it still fails after the recovery attempt, then assert and crash.
538+
if (result != SQLITE_OK) {
539+
NSString *errorString = FIRMessagingStringFromSQLiteResult(result);
540+
NSString *errorMessage = [NSString
541+
stringWithFormat:@"Could not open or create RMQ database at path %@, error: %@", path,
542+
errorString];
543+
FIRMessagingLoggerError(kFIRMessagingMessageCodeRmq2PersistentStoreErrorOpeningDatabase,
544+
@"%@", errorMessage);
545+
NSAssert(NO, errorMessage);
546+
didOpenDatabase = NO; // Still failed, so indicate database did not open.
547+
} else {
548+
// Successfully recreated after corruption, so treat as a new database for table creation.
549+
didOpenDatabase = YES; // Indicate successful opening after recreation.
550+
[self createTableWithName:kTableOutgoingRmqMessages
551+
command:kCreateTableOutgoingRmqMessages];
552+
[self createTableWithName:kTableLastRmqId command:kCreateTableLastRmqId];
553+
[self createTableWithName:kTableS2DRmqIds command:kCreateTableS2DRmqIds];
554+
}
535555
} else {
536556
[self updateDBWithStringRmqID];
537557
}

0 commit comments

Comments
 (0)