void CleanCache(agi::fs::path const& directory, std::string const& file_type, uint64_t max_size, uint64_t max_files) { static std::unique_ptr<agi::dispatch::Queue> queue; if (!queue) queue = agi::dispatch::Create(); max_size <<= 20; if (max_files == 0) max_files = std::numeric_limits<uint64_t>::max(); queue->Async([=]{ LOG_D("utils/clean_cache") << "cleaning " << directory/file_type; uint64_t total_size = 0; std::multimap<int64_t, agi::fs::path> cachefiles; for (auto const& file : agi::fs::DirectoryIterator(directory, file_type)) { agi::fs::path path = directory/file; cachefiles.insert(std::make_pair(agi::fs::ModifiedTime(path), path)); total_size += agi::fs::Size(path); } if (cachefiles.size() <= max_files && total_size <= max_size) { LOG_D("utils/clean_cache") << boost::format("cache does not need cleaning (maxsize=%d, cursize=%d, maxfiles=%d, numfiles=%d), exiting") % max_size % total_size % max_files % cachefiles.size(); return; } int deleted = 0; for (auto const& i : cachefiles) { // stop cleaning? if ((total_size <= max_size && cachefiles.size() - deleted <= max_files) || cachefiles.size() - deleted < 2) break; uint64_t size = agi::fs::Size(i.second); try { agi::fs::Remove(i.second); LOG_D("utils/clean_cache") << "deleted " << i.second; } catch (agi::Exception const& e) { LOG_D("utils/clean_cache") << "failed to delete file " << i.second << ": " << e.GetChainedMessage(); continue; } total_size -= size; ++deleted; } LOG_D("utils/clean_cache") << "deleted " << deleted << " files, exiting"; }); }