Detect on startup if the netdata-meta.db file is not a valid database file (#17924)
* Detect on startup if the netdata-meta.db file is not a database and move it aside * Log error
Stelios Fragkakis committed
Jun 25, 2024 at 16:35 UTC
e46a29a04585c32711da6d2d02add6a010c0d878
2 files changed
+18
-6
src/database/sqlite/sqlite_functions.c
+6
-6
@@ -43,7 +43,7 @@ SQLITE_API int sqlite3_step_monitored(sqlite3_stmt *stmt) {
43
return rc;
44
}
45
46
-static bool mark_database_to_recover(sqlite3_stmt *res, sqlite3 *database)
46
+static bool mark_database_to_recover(sqlite3_stmt *res, sqlite3 *database, int rc)
47
{
48
49
if (!res && !database)
@@ -54,7 +54,7 @@ static bool mark_database_to_recover(sqlite3_stmt *res, sqlite3 *database)
54
55
if (db_meta == database) {
56
char recover_file[FILENAME_MAX + 1];
57
- snprintfz(recover_file, FILENAME_MAX, "%s/.netdata-meta.db.recover", netdata_configured_cache_dir);
57
+ snprintfz(recover_file, FILENAME_MAX, "%s/.netdata-meta.db.%s", netdata_configured_cache_dir, SQLITE_CORRUPT == rc ? "recover" : "delete" );
58
int fd = open(recover_file, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, 444);
59
if (fd >= 0) {
60
close(fd);
@@ -69,7 +69,7 @@ int execute_insert(sqlite3_stmt *res)
69
int rc;
70
rc = sqlite3_step_monitored(res);
71
if (rc == SQLITE_CORRUPT) {
72
- (void)mark_database_to_recover(res, NULL);
72
+ (void)mark_database_to_recover(res, NULL, rc);
73
error_report("SQLite error %d", rc);
74
}
75
return rc;
@@ -229,8 +229,8 @@ int init_database_batch(sqlite3 *database, const char *batch[], const char *desc
229
analytics_set_data_str(&analytics_data.netdata_fail_reason, error_str);
230
sqlite3_free(err_msg);
231
freez(error_str);
232
- if (SQLITE_CORRUPT == rc) {
233
- if (mark_database_to_recover(NULL, database))
232
+ if (SQLITE_CORRUPT == rc || SQLITE_NOTADB == rc) {
233
+ if (mark_database_to_recover(NULL, database, rc))
234
error_report("Database is corrupted will attempt to fix");
235
return SQLITE_CORRUPT;
236
}
@@ -263,7 +263,7 @@ int db_execute(sqlite3 *db, const char *cmd)
263
}
264
265
if (rc == SQLITE_CORRUPT)
266
- mark_database_to_recover(NULL, db);
266
+ mark_database_to_recover(NULL, db, rc);
267
break;
268
}
269
return (rc != SQLITE_OK);
src/database/sqlite/sqlite_metadata.c
+12
@@ -668,6 +668,18 @@ int sql_init_meta_database(db_check_action_type_t rebuild, int memory)
668
if (rebuild & DB_CHECK_RECOVER)
669
return 0;
670
}
671
+
672
+ snprintfz(sqlite_database, sizeof(sqlite_database) - 1, "%s/.netdata-meta.db.delete", netdata_configured_cache_dir);
673
+ rc = unlink(sqlite_database);
674
+ snprintfz(sqlite_database, FILENAME_MAX, "%s/netdata-meta.db", netdata_configured_cache_dir);
675
+ if (rc == 0) {
676
+ char new_sqlite_database[FILENAME_MAX + 1];
677
+ snprintfz(new_sqlite_database, sizeof(new_sqlite_database) - 1, "%s/netdata-meta.bad", netdata_configured_cache_dir);
678
+ rc = rename(sqlite_database, new_sqlite_database);
679
+ if (rc)
680
+ error_report("Failed to rename %s to %s", sqlite_database, new_sqlite_database);
681
+ }
682
+ // note: sqlite_database contains the right name
683
}
684
else
685
strncpyz(sqlite_database, ":memory:", sizeof(sqlite_database) - 1);