Save session data once on shutdown, before waiting for stopped announces

Write it after downloads stop, or after the loop if skipped; one error policy for saves.
This commit is contained in:
Ivan
2026-10-16 11:48:46 +03:00
committed by Jari Sundell
parent 9dd54038b4
commit 5a3b4e50cd
5 changed files with 79 additions and 32 deletions
+58 -31
View File
@@ -429,42 +429,62 @@ SessionManager::process_finished_saves() {
if (!m_active)
throw torrent::internal_error("SessionManager::process_finished_saves() called while not active.");
for (auto& request : m_finished_saves) {
try {
request.first.get();
} catch (torrent::storage_error& e) {
LT_LOG("error saving download : storage error :download:%p path:%s : %s", request.second.download, request.second.path.c_str(), e.what());
if (m_last_storage_error_message + std::chrono::minutes(5) > torrent::this_thread::cached_time()) {
m_ignored_storage_error_count++;
continue;
}
lt_log_print(torrent::LOG_ERRORS, "Storage errors saving session data for download: ignored:%u : %s", m_ignored_storage_error_count, e.what());
m_last_storage_error_message = torrent::this_thread::cached_time();
m_ignored_storage_error_count = 0;
continue;
} catch (torrent::internal_error& e) {
LT_LOG("error saving download : internal error : download:%p path:%s : %s", request.second.download, request.second.path.c_str(), e.what());
throw;
} catch (...) {
LT_LOG("error saving download : unknown error : download:%p path:%s", request.second.download, request.second.path.c_str());
throw;
}
LT_LOG("finished saving download : download:%p path:%s", request.second.download, request.second.path.c_str());
}
for (auto& request : m_finished_saves)
consume_finished_save_unsafe(request);
m_finished_saves.clear();
callback_save_request();
}
// Storage errors share a five-minute log limit and count what they suppress.
// Callers hold m_mutex.
void
SessionManager::report_storage_error_unsafe(const std::string& what) {
if (m_last_storage_error_message + std::chrono::minutes(5) > torrent::this_thread::cached_time()) {
m_ignored_storage_error_count++;
return;
}
lt_log_print(torrent::LOG_ERRORS, "Storage errors saving session data for download: ignored:%u : %s", m_ignored_storage_error_count, what.c_str());
m_last_storage_error_message = torrent::this_thread::cached_time();
m_ignored_storage_error_count = 0;
}
// The one policy for a finished save, on the session thread and in shutdown
// flushes: storage errors go to report_storage_error_unsafe(), internal and
// unknown errors propagate. Callers hold m_mutex.
void
SessionManager::consume_finished_save_unsafe(ProcessingSave& request) {
try {
request.first.get();
} catch (torrent::storage_error& e) {
LT_LOG("error saving download : storage error :download:%p path:%s : %s", request.second.download, request.second.path.c_str(), e.what());
report_storage_error_unsafe(e.what());
return;
} catch (torrent::internal_error& e) {
LT_LOG("error saving download : internal error : download:%p path:%s : %s", request.second.download, request.second.path.c_str(), e.what());
throw;
} catch (...) {
LT_LOG("error saving download : unknown error : download:%p path:%s", request.second.download, request.second.path.c_str());
throw;
}
LT_LOG("finished saving download : download:%p path:%s", request.second.download, request.second.path.c_str());
}
void
SessionManager::flush_shutdown_saves() {
assert(torrent::this_thread::thread() == torrent::main_thread::thread());
flush_all_pending_builds();
std::unique_lock<std::mutex> lock(m_mutex);
flush_all_and_wait_unsafe(lock);
}
void
SessionManager::flush_all_and_wait_unsafe(std::unique_lock<std::mutex>& lock) {
LT_LOG("flushing all pending saves", 0);
@@ -484,10 +504,17 @@ SessionManager::flush_all_and_wait_unsafe(std::unique_lock<std::mutex>& lock) {
m_finished_condition.wait(lock);
for (auto& request : m_finished_saves)
LT_LOG("finished saving download : download:%p path:%s", request.second.download, request.second.path.c_str());
consume_finished_save_unsafe(request);
m_finished_saves.clear();
// Report and reset what was suppressed since the last error line. The count
// includes saves the session thread consumed while this flush waited.
if (m_ignored_storage_error_count != 0) {
lt_log_print(torrent::LOG_ERRORS, "Storage errors flushing session data: ignored:%u", m_ignored_storage_error_count);
m_ignored_storage_error_count = 0;
}
LT_LOG("flushed all pending saves", 0);
}
+4
View File
@@ -79,6 +79,7 @@ protected:
void cleanup();
void flush_all_pending_builds();
void flush_shutdown_saves();
private:
void callback_pending_builds();
@@ -98,6 +99,9 @@ private:
using ProcessingSave = std::pair<std::future<void>, SaveRequest>;
void consume_finished_save_unsafe(ProcessingSave& request);
void report_storage_error_unsafe(const std::string& what);
torrent::system::Thread* m_thread;
torrent::system::callback_id m_callback_id;