Preserve indexed and unfinished files during orphan cleanup
This commit is contained in:
1 parent
15fafc42c9
commit
9117813c4d
2 files changed
+29
-19
No files matched your search
+25
-17
@@ -1341,10 +1341,8 @@ void chat_media_autodownload_backfill(struct UTUN_INSTANCE* inst) {
|
||||
uint64_t now_ms = (uint64_t)ntp_time_get_seconds(inst) * 1000ULL;
|
||||
uint64_t cutoff_ms = now_ms - (uint64_t)days * 86400ULL * 1000ULL;
|
||||
|
||||
char media_base[512];
|
||||
const char* last_slash = strrchr(cc->db_path, '/');
|
||||
if (last_slash) snprintf(media_base, sizeof(media_base), "%.*s", (int)(last_slash - cc->db_path), cc->db_path);
|
||||
else snprintf(media_base, sizeof(media_base), "%s", cc->db_path);
|
||||
char media_base[MEDIA_BASE_MAX];
|
||||
if (media_index_get_base(cc->db, media_base)) return;
|
||||
|
||||
struct bf_list list = {0};
|
||||
bf_collect(cc, media_base, NULL, &list);
|
||||
@@ -1411,10 +1409,8 @@ void chat_media_autodownload_backfill_channel(struct UTUN_INSTANCE* inst, const
|
||||
uint64_t now_ms = (uint64_t)ntp_time_get_seconds(inst) * 1000ULL;
|
||||
uint64_t cutoff_ms = now_ms - (uint64_t)days * 86400ULL * 1000ULL;
|
||||
|
||||
char media_base[512];
|
||||
const char* last_slash = strrchr(cc->db_path, '/');
|
||||
if (last_slash) snprintf(media_base, sizeof(media_base), "%.*s", (int)(last_slash - cc->db_path), cc->db_path);
|
||||
else snprintf(media_base, sizeof(media_base), "%s", cc->db_path);
|
||||
char media_base[MEDIA_BASE_MAX];
|
||||
if (media_index_get_base(cc->db, media_base)) return;
|
||||
|
||||
struct bf_list list = {0};
|
||||
bf_collect(cc, media_base, ch_id, &list);
|
||||
@@ -1454,12 +1450,6 @@ struct media_msg_file {
|
||||
|
||||
typedef void (*media_msg_file_cb)(const struct media_msg_file* f, void* arg);
|
||||
|
||||
static void chat_media_base(struct chat_core_ctx* cc, char* out, size_t out_sz) {
|
||||
const char* ls = strrchr(cc->db_path, '/');
|
||||
if (ls) snprintf(out, out_sz, "%.*s", (int)(ls - cc->db_path), cc->db_path);
|
||||
else snprintf(out, out_sz, "%s", cc->db_path);
|
||||
}
|
||||
|
||||
/* Итератор по всем медиасообщениям всех каналов (без фильтра по node_id/времени). */
|
||||
static void chat_media_foreach_media_message(struct chat_core_ctx* cc, const char* media_base, media_msg_file_cb cb, void* arg) {
|
||||
if (!cc->db || !cb) return;
|
||||
@@ -1604,7 +1594,8 @@ static void cache_file_collect_cb(const struct media_msg_file* f, void* arg) {
|
||||
|
||||
/* Фактическая сумма размеров файлов, соответствующих сообщениям. */
|
||||
static uint64_t chat_media_cache_scan_sum(struct chat_core_ctx* cc) {
|
||||
char media_base[512]; chat_media_base(cc, media_base, sizeof(media_base));
|
||||
char media_base[MEDIA_BASE_MAX];
|
||||
if (media_index_get_base(cc->db, media_base)) return;
|
||||
struct cache_file_list files = {0};
|
||||
chat_media_foreach_media_message(cc, media_base, cache_file_collect_cb, &files);
|
||||
uint64_t sum = 0;
|
||||
@@ -1661,7 +1652,8 @@ static void chat_media_cache_cleanup_orphans(struct UTUN_INSTANCE* inst) {
|
||||
struct chat_core_ctx* cc = CC(inst);
|
||||
if (!cc || !cc->initialized || !cc->db || !inst) return;
|
||||
|
||||
char media_base[512]; chat_media_base(cc, media_base, sizeof(media_base));
|
||||
char media_base[MEDIA_BASE_MAX];
|
||||
if (media_index_get_base(cc->db, media_base)) return;
|
||||
char media_dir[600]; snprintf(media_dir, sizeof(media_dir), "%s/media", media_base);
|
||||
|
||||
struct file_io_info directory;
|
||||
@@ -1671,6 +1663,21 @@ static void chat_media_cache_cleanup_orphans(struct UTUN_INSTANCE* inst) {
|
||||
|
||||
struct cache_rel_list rels = {0};
|
||||
chat_media_foreach_media_message(cc, media_base, cache_rel_collect_cb, &rels);
|
||||
sqlite3_stmt* preparations = NULL;
|
||||
int prep_rc = sqlite3_prepare_v2(cc->db, "SELECT location FROM media_preparations UNION SELECT location FROM media_files",
|
||||
-1, &preparations, NULL);
|
||||
if (prep_rc == SQLITE_OK) {
|
||||
while ((prep_rc = sqlite3_step(preparations)) == SQLITE_ROW) {
|
||||
const char* location = (const char*)sqlite3_column_text(preparations, 0);
|
||||
if (location) cache_rel_add(&rels, location);
|
||||
}
|
||||
}
|
||||
int prep_finish = preparations ? sqlite3_finalize(preparations) : SQLITE_OK;
|
||||
if (prep_rc != SQLITE_DONE || prep_finish != SQLITE_OK) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_MEDIA, "media orphan scan cannot protect indexed/preparing files rc=%d", prep_rc);
|
||||
for (int i = 0; i < rels.count; i++) u_free(rels.items[i]);
|
||||
u_free(rels.items); return;
|
||||
}
|
||||
/* Ещё не опубликованные контейнеры и их временные файлы принадлежат crypto worker. */
|
||||
if (cc->attachment_initialized) {
|
||||
sqlite3_stmt* active = NULL;
|
||||
@@ -1719,7 +1726,8 @@ void chat_media_cache_enforce(struct UTUN_INSTANCE* inst) {
|
||||
return;
|
||||
}
|
||||
|
||||
char media_base[512]; chat_media_base(cc, media_base, sizeof(media_base));
|
||||
char media_base[MEDIA_BASE_MAX];
|
||||
if (media_index_get_base(cc->db, media_base)) return;
|
||||
|
||||
struct cache_file_list files = {0};
|
||||
chat_media_foreach_media_message(cc, media_base, cache_file_collect_cb, &files);
|
||||
|
||||
@@ -103,7 +103,8 @@ int media_index_get_base(sqlite3* db, char base[MEDIA_BASE_MAX]) {
|
||||
sqlite3_stmt* st = NULL;
|
||||
int rc = db && base ? sqlite3_prepare_v2(db, "SELECT value FROM ui_state WHERE key='media_base'", -1, &st, NULL) : SQLITE_MISUSE;
|
||||
if (rc == SQLITE_OK) rc = sqlite3_step(st);
|
||||
int valid = rc == SQLITE_ROW && !mi_clean_path((const char*)sqlite3_column_text(st, 0), base, MEDIA_BASE_MAX);
|
||||
const char* value = rc == SQLITE_ROW ? (const char*)sqlite3_column_text(st, 0) : NULL;
|
||||
int valid = value && sqlite3_column_bytes(st, 0) == (int)strlen(value) && !mi_clean_path(value, base, MEDIA_BASE_MAX);
|
||||
if (st && sqlite3_finalize(st) != SQLITE_OK) valid = 0;
|
||||
if (valid) return 0;
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_MEDIA, "media_index cannot read media_base rc=%d: %s", rc, db ? sqlite3_errmsg(db) : "no DB");
|
||||
@@ -256,7 +257,8 @@ static int mi_remove(const char* path) {
|
||||
}
|
||||
|
||||
int media_index_delete_channel(sqlite3* db, const char* chat_id, const char* media_base) {
|
||||
if (!db || !chat_id || !*chat_id || !sqlite3_get_autocommit(db)) {
|
||||
char checked_base[MEDIA_BASE_MAX];
|
||||
if (!db || !chat_id || !*chat_id || !sqlite3_get_autocommit(db) || mi_clean_path(media_base, checked_base, sizeof(checked_base))) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_MEDIA, "media_index delete invalid args/external transaction"); return -1;
|
||||
}
|
||||
struct mi_delete_file { char location[MEDIA_PATH_MAX]; char path[MEDIA_PATH_MAX]; int shared; };
|
||||
|
||||
Reference in new issue
Block a user