From 423fb04b40dc320dd9a2125d0ec00dc111e9266a Mon Sep 17 00:00:00 2001 From: Egutierrez Date: Mon, 13 Apr 2026 01:31:33 +0200 Subject: [PATCH] fix: soporte Windows UNC paths y busy timeout en SQLite MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit En Windows, si el path a registry.db es UNC (\\wsl.localhost\...), SQLite no puede hacer locking correctamente. Se copia el DB a un archivo temporal local antes de abrirlo. Se aƱade busy_timeout de 3 segundos para evitar SQLITE_BUSY en lecturas concurrentes. Co-Authored-By: Claude Opus 4.6 (1M context) --- data.cpp | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 53 insertions(+), 2 deletions(-) diff --git a/data.cpp b/data.cpp index 1b32d70..6c3ca29 100644 --- a/data.cpp +++ b/data.cpp @@ -1,6 +1,13 @@ #include "data.h" #include #include +#include +#include + +#ifdef _WIN32 +#include +#include +#endif // Helper: execute a query and call row_fn for each row template @@ -52,13 +59,57 @@ void RegistryData::prepare_chart_data() { } } +// Copy file src to dst. Returns true on success. +static bool copy_file(const char* src, const char* dst) { +#ifdef _WIN32 + return CopyFileA(src, dst, FALSE) != 0; +#else + FILE* in = fopen(src, "rb"); + if (!in) return false; + FILE* out = fopen(dst, "wb"); + if (!out) { fclose(in); return false; } + char buf[65536]; + size_t n; + while ((n = fread(buf, 1, sizeof(buf), in)) > 0) + fwrite(buf, 1, n, out); + fclose(in); + fclose(out); + return true; +#endif +} + +// On Windows, if the path is a network/UNC path (like \\wsl.localhost\...), +// copy the DB to a local temp file so SQLite locking works correctly. +// Returns the path to use (may be the original or a temp copy). +static std::string ensure_local_db(const char* db_path) { +#ifdef _WIN32 + // Detect UNC / network paths + if (strncmp(db_path, "\\\\", 2) == 0 || strncmp(db_path, "//", 2) == 0) { + char temp_dir[MAX_PATH] = {0}; + GetTempPathA(MAX_PATH, temp_dir); + std::string local_path = std::string(temp_dir) + "fn_registry_dashboard.db"; + + fprintf(stdout, "Copying DB to local temp: %s\n", local_path.c_str()); + if (copy_file(db_path, local_path.c_str())) { + return local_path; + } + fprintf(stderr, "Warning: failed to copy DB locally, using original path\n"); + } +#endif + return db_path; +} + bool load_registry_data(const char* db_path, RegistryData& out) { + std::string effective_path = ensure_local_db(db_path); + sqlite3* db = nullptr; - if (sqlite3_open_v2(db_path, &db, SQLITE_OPEN_READONLY, nullptr) != SQLITE_OK) { - fprintf(stderr, "Cannot open %s: %s\n", db_path, sqlite3_errmsg(db)); + if (sqlite3_open_v2(effective_path.c_str(), &db, SQLITE_OPEN_READONLY, nullptr) != SQLITE_OK) { + fprintf(stderr, "Cannot open %s: %s\n", effective_path.c_str(), sqlite3_errmsg(db)); return false; } + sqlite3_busy_timeout(db, 3000); + // --- Counts --- query(db, "SELECT COUNT(*) FROM functions", [&](sqlite3_stmt* s) { out.stats.total_functions = col_int(s, 0);