Add per-device file facts and frozen storage policy to the schema

This commit is contained in:
evgeny committed 2026-11-03 12:52:55 +01:00
1 parent 7e7e670c0d
commit cf12ee03fa
2 files changed
+53

No files matched your search

+50
View File
@@ -26,6 +26,56 @@ static int schema_has_column(sqlite3* db, const char* table, const char* column)
return (rc == SQLITE_ROW || rc == SQLITE_DONE) && final == SQLITE_OK ? found : schema_error(db, "column lookup");
}
int dm_media_schema_init(struct UTUN_INSTANCE* inst) {
sqlite3* db = inst ? inst->topo_sqlite_db : NULL;
if (!db) return schema_error(db, "media database absent");
if (schema_exec(db, "SAVEPOINT dm_media_schema")) return -1;
const char* files = "CREATE TABLE IF NOT EXISTS dm_files(id BLOB PRIMARY KEY,conv_id TEXT NOT NULL,dir INTEGER NOT NULL,"
"seq INTEGER NOT NULL,author INTEGER NOT NULL,recipient INTEGER NOT NULL,plain_size INTEGER NOT NULL,"
"cipher_hash BLOB NOT NULL,body BLOB NOT NULL,group_id INTEGER NOT NULL,local_path TEXT NOT NULL,"
"ready INTEGER NOT NULL DEFAULT 0,holder INTEGER NOT NULL,expires INTEGER NOT NULL DEFAULT 0,receipt BLOB,"
"downloading INTEGER NOT NULL DEFAULT 0,retry_at INTEGER NOT NULL DEFAULT 0,manual INTEGER NOT NULL DEFAULT 0,"
"first_attempt INTEGER NOT NULL DEFAULT 0,UNIQUE(conv_id,author,seq))";
if (schema_exec(db, files)) goto fail;
int found = schema_has_column(db, "dm_files", "manual");
if (found < 0) goto fail;
if (!found) {
if (schema_exec(db, "ALTER TABLE dm_files RENAME TO dm_files_previous") || schema_exec(db, files) ||
schema_exec(db, "INSERT INTO dm_files(id,conv_id,dir,seq,author,recipient,plain_size,cipher_hash,body,group_id,"
"local_path,ready,holder,expires,receipt,downloading,retry_at) SELECT id,conv_id,dir,seq,author,recipient,"
"plain_size,cipher_hash,body,group_id,local_path,ready,holder,expires,receipt,downloading,retry_at FROM dm_files_previous") ||
schema_exec(db, "DROP TABLE dm_files_previous")) goto fail;
}
if (schema_exec(db, "CREATE TABLE IF NOT EXISTS dm_file_targets(id BLOB NOT NULL,node INTEGER NOT NULL,side INTEGER NOT NULL,"
"received BLOB,taken BLOB,PRIMARY KEY(id,node));"
"CREATE TABLE IF NOT EXISTS dm_file_sources(id BLOB NOT NULL,node INTEGER NOT NULL,group_id INTEGER NOT NULL,"
"expires INTEGER NOT NULL DEFAULT 0,PRIMARY KEY(id,node));"
"CREATE TABLE IF NOT EXISTS dm_custody(id BLOB PRIMARY KEY,author INTEGER NOT NULL,recipient INTEGER NOT NULL,"
"plain_size INTEGER NOT NULL,cipher_size INTEGER NOT NULL,body BLOB NOT NULL,body_hash BLOB NOT NULL,"
"group_id INTEGER NOT NULL,supernode INTEGER NOT NULL,expires INTEGER NOT NULL,ready INTEGER NOT NULL DEFAULT 0,"
"receipt BLOB,retry_at INTEGER NOT NULL DEFAULT 0);"
"CREATE TABLE IF NOT EXISTS dm_custody_done(id BLOB PRIMARY KEY,body_hash BLOB NOT NULL,receipt BLOB);"
"CREATE TABLE IF NOT EXISTS dm_media_jobs(id BLOB PRIMARY KEY,author INTEGER NOT NULL,recipient INTEGER NOT NULL,"
"seq INTEGER NOT NULL,body BLOB,body_hash BLOB NOT NULL,group_id INTEGER NOT NULL,holder INTEGER NOT NULL DEFAULT 0,"
"stored INTEGER NOT NULL DEFAULT 0,expires INTEGER NOT NULL DEFAULT 0,expired INTEGER NOT NULL DEFAULT 0,"
"receipt BLOB,retry_at INTEGER NOT NULL DEFAULT 0)")) goto fail;
const char* tables[] = {"dm_custody", "dm_custody_done", "dm_media_jobs"};
for (unsigned i = 0; i < 3; i++) {
found = schema_has_column(db, tables[i], "delete_on_open");
if (found < 0) goto fail;
if (!found) {
char sql[256];
snprintf(sql, sizeof(sql), "ALTER TABLE %s ADD COLUMN delete_on_open INTEGER NOT NULL DEFAULT %d", tables[i], i == 2 ? -1 : 1);
if (schema_exec(db, sql)) goto fail;
}
}
if (schema_exec(db, "RELEASE dm_media_schema")) goto fail;
DEBUG_INFO(DEBUG_CATEGORY_DM, "DM media schema: author identity, device receipts and retention policy ready");
return 0;
fail:
schema_exec(db, "ROLLBACK TO dm_media_schema"); schema_exec(db, "RELEASE dm_media_schema"); return -1;
}
int dm_schema_init(struct UTUN_INSTANCE* inst) {
sqlite3* db = inst ? inst->topo_sqlite_db : NULL;
if (!db) return schema_error(db, "missing database");
+3
View File
@@ -8,6 +8,9 @@ struct UTUN_INSTANCE;
/* 0/-1: создать схему и перенести существующие DEVICE-записи без переподписи. */
int dm_schema_init(struct UTUN_INSTANCE* inst);
/* Общая схема файлов endpoint/S/M и квитанций устройств; вызывается до media owners.
* Сохранённые DEVICE-файлы остаются, уникальность меняется с dir на author. 0/-1. */
int dm_media_schema_init(struct UTUN_INSTANCE* inst);
/* 0/-1: прочитать следующий seq автора. Резервирование выполняет take в той же
* транзакции, что запись сообщения; до commit тело нельзя передавать в сеть. */
int dm_sequence_next(struct UTUN_INSTANCE* inst, uint64_t* seq);