diff --git a/src/switch_core_db.c b/src/switch_core_db.c index 6cc8896fab..c507c99368 100644 --- a/src/switch_core_db.c +++ b/src/switch_core_db.c @@ -45,6 +45,20 @@ static void db_pick_path(const char *dbname, char *buf, switch_size_t size) } } +struct integrity_check_cb_arg { + int rows; + int ok; +}; + +/* pragma integrity_check returns a single row with the value "ok" if no errors are found */ +static int integrity_check_cb(void *pArg, int argc, char **argv, char **columnNames) +{ + struct integrity_check_cb_arg *cb_arg = (struct integrity_check_cb_arg *)pArg; + cb_arg->rows++; + cb_arg->ok = (0 == strcasecmp(argv[0], "ok")); + return 0; +} + SWITCH_DECLARE(int) switch_core_db_open(const char *filename, switch_core_db_t **ppDb) { return sqlite3_open(filename, ppDb); @@ -197,14 +211,41 @@ SWITCH_DECLARE(int) switch_core_db_load_extension(switch_core_db_t *db, const ch SWITCH_DECLARE(switch_core_db_t *) switch_core_db_open_file(const char *filename) { - switch_core_db_t *db; + switch_core_db_t *db = NULL; char path[1024]; int db_ret; + struct integrity_check_cb_arg cb_arg; + int i; + db_pick_path(filename, path, sizeof(path)); - if ((db_ret = switch_core_db_open(path, &db)) != SQLITE_OK) { - goto end; + + for (i = 0; i < 2; i++) { + if ((db_ret = switch_core_db_open(path, &db)) != SQLITE_OK) { + goto end; + } + + memset(&cb_arg, 0, sizeof(cb_arg)); + if ((db_ret = switch_core_db_exec(db, "PRAGMA integrity_check;", integrity_check_cb, &cb_arg, NULL) != SQLITE_OK)) { + goto end; + } + + if (cb_arg.ok && (1 == cb_arg.rows)) { + break; + } else if (0 == i) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "SQLite integrity_check failed for [%s]. Deleting file and retrying\n", path); + switch_core_db_close(db); + remove(path); + continue; + + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "SQLite integrity_check failed second time for [%s]\n", path); + switch_core_db_close(db); + db = NULL; + goto end; + } } + if ((db_ret = switch_core_db_exec(db, "PRAGMA synchronous=OFF;", NULL, NULL, NULL) != SQLITE_OK)) { goto end; }