78 lines
2.8 KiB
Swift
78 lines
2.8 KiB
Swift
//
|
|
// Copyright 2022 Signal Messenger, LLC
|
|
// SPDX-License-Identifier: AGPL-3.0-only
|
|
//
|
|
|
|
import Foundation
|
|
import GRDB
|
|
|
|
public struct DatabaseCorruptionState: Equatable {
|
|
public enum DatabaseCorruptionStatus: Int, Codable {
|
|
// We used to store these as booleans, so the value is important.
|
|
case notCorrupted = 0
|
|
case corrupted = 1
|
|
case corruptedButAlreadyDumpedAndRestored = 2
|
|
// This case was deprecated, but is left here such that we don't
|
|
// inadvertently reuse this rawValue and resurrect it.
|
|
// case readCorrupted = 3
|
|
|
|
public var isCorrupted: Bool {
|
|
switch self {
|
|
case .notCorrupted: return false
|
|
case .corrupted, .corruptedButAlreadyDumpedAndRestored: return true
|
|
}
|
|
}
|
|
}
|
|
|
|
public let status: DatabaseCorruptionStatus
|
|
|
|
init(status: DatabaseCorruptionStatus) {
|
|
self.status = status
|
|
}
|
|
|
|
// MARK: - Reading and writing from `UserDefaults`
|
|
|
|
// The value of this key doesn't match the name because that's what we used to store.
|
|
static var databaseCorruptionStatusKey: String { "hasGrdbDatabaseCorruption" }
|
|
|
|
public init(userDefaults: UserDefaults) {
|
|
let rawStatus = userDefaults.integer(forKey: Self.databaseCorruptionStatusKey)
|
|
let status = DatabaseCorruptionStatus(rawValue: rawStatus) ?? .notCorrupted
|
|
self.init(status: status)
|
|
}
|
|
|
|
private func save(to userDefaults: UserDefaults) {
|
|
userDefaults.set(status.rawValue, forKey: Self.databaseCorruptionStatusKey)
|
|
}
|
|
|
|
public static func flagDatabaseAsCorrupted(userDefaults: UserDefaults) {
|
|
let oldState = DatabaseCorruptionState(userDefaults: userDefaults)
|
|
switch oldState.status {
|
|
case .notCorrupted:
|
|
Self(status: .corrupted).save(to: userDefaults)
|
|
case .corrupted, .corruptedButAlreadyDumpedAndRestored:
|
|
break
|
|
}
|
|
}
|
|
|
|
public static func flagCorruptedDatabaseAsDumpedAndRestored(userDefaults: UserDefaults) {
|
|
let oldState = DatabaseCorruptionState(userDefaults: userDefaults)
|
|
switch oldState.status {
|
|
case .corrupted:
|
|
DatabaseCorruptionState(status: .corruptedButAlreadyDumpedAndRestored).save(to: userDefaults)
|
|
case .notCorrupted, .corruptedButAlreadyDumpedAndRestored:
|
|
owsFailDebug("Flagging database as partially recovered, but it was not in the right state previously")
|
|
}
|
|
}
|
|
|
|
public static func flagDatabaseAsNotCorrupted(userDefaults: UserDefaults) {
|
|
let oldState = DatabaseCorruptionState(userDefaults: userDefaults)
|
|
switch oldState.status {
|
|
case .notCorrupted:
|
|
break
|
|
case .corrupted, .corruptedButAlreadyDumpedAndRestored:
|
|
Self(status: .notCorrupted).save(to: userDefaults)
|
|
}
|
|
}
|
|
}
|