// Try to look at a SQL statement and figure out which repoId it's targeting. static int debugComputeRepoIdFromSQL(Repo& repo, const std::string& stmt) { for (int i = 0; i < RepoIdCount; ++i) { auto name = repo.dbName(i); if (stmt.find(folly::format(" {}.", name).str()) != std::string::npos) { return i; } } return 0; }
static void reportDbCorruption(Repo& repo, int repoId, const std::string& where) { std::string report = folly::sformat("{} returned SQLITE_CORRUPT.\n", where); auto repoPath = sqlite3_db_filename(repo.dbc(), repo.dbName(repoId)); if (repoPath) { report += folly::sformat("Path: '{}'\n", repoPath); struct stat repoStat; if (stat(repoPath, &repoStat) == 0) { time_t now = time(nullptr); report += folly::sformat("{} bytes, c_age: {}, m_age: {}\n", repoStat.st_size, now - repoStat.st_ctime, now - repoStat.st_mtime); } else { report += "stat() failed\n"; } } else { report += "sqlite3_db_filename() returned nullptr\n"; } // Use raw SQLite here because we just want to hit the raw DB itself. sqlite3_exec(repo.dbc(), folly::sformat( "PRAGMA {}.integrity_check(4);", repo.dbName(repoId)).c_str(), [](void* _report, int columns, char** text, char** names) { std::string& report = *reinterpret_cast<std::string*>(_report); for (int column = 0; column < columns; ++column) { report += folly::sformat("Integrity Check ({}): {}\n", column, text[column]); } return 0; }, &report, nullptr); Logger::Error(report); }