MCPcopy Create free account
hub / github.com/DeusData/codebase-memory-mcp / prepare_snapshot_db

Function prepare_snapshot_db

src/pipeline/artifact.c:487–542  ·  view source on GitHub ↗

Prepare a stripped DB copy for best-quality export. * VACUUM INTO → (optionally) drop indexes → VACUUM. Returns malloc'd buffer * or NULL. VACUUM INTO runs on BOTH quality levels: it is the consistent * snapshot — the store runs in WAL mode, so raw main-file bytes miss * committed transactions still in the -wal and can be mid-checkpoint torn * (#895). Only the index-stripping is BEST-only. */

Source from the content-addressed store, hash-verified

485 * committed transactions still in the -wal and can be mid-checkpoint torn
486 * (#895). Only the index-stripping is BEST-only. */
487static char *prepare_snapshot_db(const char *db_path, size_t *out_size, bool strip_indexes) {
488 artifact_snapshot_tmp_t tmp;
489 if (!artifact_snapshot_tmp_open(&tmp)) {
490 artifact_export_fail("prepare_snapshot_dir", cbm_tmpdir(), "private_tmpdir_failed", errno);
491 return NULL;
492 }
493 /* Fresh private directory ⇒ the destination is absent by construction, which
494 * is exactly what VACUUM INTO requires. The old unlink-the-stale-file step
495 * is gone with the fixed name it existed to clear. */
496 const char *tmp_path = tmp.db;
497
498 /* VACUUM INTO: clean compacted copy. Use raw sqlite3 to bypass store authorizer
499 * (which blocks ATTACH, used internally by VACUUM INTO). */
500 sqlite3 *raw_db = NULL;
501 if (sqlite3_open_v2(db_path, &raw_db, SQLITE_OPEN_READWRITE, NULL) != SQLITE_OK) {
502 const char *err = raw_db ? sqlite3_errmsg(raw_db) : "sqlite_open";
503 artifact_export_fail("open_source_db", db_path, err, 0);
504 sqlite3_close(raw_db);
505 artifact_snapshot_tmp_close(&tmp);
506 return NULL;
507 }
508
509 char vacuum_sql[CBM_SZ_4K];
510 snprintf(vacuum_sql, sizeof(vacuum_sql), "VACUUM INTO '%s';", tmp_path);
511 char *errmsg = NULL;
512 int vrc = sqlite3_exec(raw_db, vacuum_sql, NULL, NULL, &errmsg);
513 sqlite3_close(raw_db);
514
515 if (vrc != SQLITE_OK) {
516 artifact_export_fail("vacuum_into", tmp_path, errmsg ? errmsg : sqlite3_errstr(vrc), 0);
517 sqlite3_free(errmsg);
518 artifact_snapshot_tmp_close(&tmp);
519 return NULL;
520 }
521
522 /* Strip indexes from the copy for better compression (BEST only). */
523 if (strip_indexes) {
524 sqlite3 *tmp_db = NULL;
525 if (sqlite3_open_v2(tmp_path, &tmp_db, SQLITE_OPEN_READWRITE, NULL) == SQLITE_OK) {
526 sqlite3_exec(tmp_db, DROP_INDEXES_SQL, NULL, NULL, NULL);
527 sqlite3_exec(tmp_db, "VACUUM;", NULL, NULL, NULL);
528 sqlite3_close(tmp_db);
529 }
530 }
531
532 /* Reopened by path rather than held on a descriptor across VACUUM INTO,
533 * because sqlite owns the create. The private directory is what makes that
534 * safe: an attacker who cannot enter it cannot swap the file underneath. */
535 char *data = read_file_alloc(tmp_path, out_size);
536 if (!data || *out_size == 0) {
537 artifact_export_fail("read_stripped_db", tmp_path, "empty_or_unreadable", errno);
538 }
539 /* Removes the copy, its WAL/SHM sidecars, and the private directory. */
540 artifact_snapshot_tmp_close(&tmp);
541 return data;
542}
543
544/* ── Export ───────────────────────────────────────────────────────── */

Callers 1

cbm_artifact_exportFunction · 0.85

Calls 5

artifact_export_failFunction · 0.85
cbm_tmpdirFunction · 0.85
read_file_allocFunction · 0.85

Tested by

no test coverage detected