diff --git a/rtgui/cachemanager.cc b/rtgui/cachemanager.cc index d86f6c41f..d5a42e84b 100644 --- a/rtgui/cachemanager.cc +++ b/rtgui/cachemanager.cc @@ -16,18 +16,19 @@ * You should have received a copy of the GNU General Public License * along with RawTherapee. If not, see . */ -#include "cachemanager.h" #include #include #include +#include #include #ifdef WIN32 #include #endif +#include "cachemanager.h" #include "guiutils.h" #include "options.h" #include "procparamchangers.h" @@ -340,66 +341,63 @@ Glib::ustring CacheManager::getCacheFileName (const Glib::ustring& subDir, void CacheManager::applyCacheSizeLimitation () const { // first count files without fetching file name and timestamp. + auto cachedir = opendir(Glib::build_filename(baseDir, "data").c_str()); + if (!cachedir) { + return; + } + std::size_t numFiles = 0; - try { + while (readdir(cachedir)) { + ++numFiles; + } - const auto dirName = Glib::build_filename (baseDir, "data"); - const auto dir = Gio::File::create_for_path (dirName); - - auto enumerator = dir->enumerate_children (""); - - while (numFiles <= options.maxCacheEntries && enumerator->next_file ()) { - ++numFiles; - } - - } catch (Glib::Exception&) {} + closedir(cachedir); + numFiles -= 2; // because . and .. are counted if (numFiles <= options.maxCacheEntries) { return; } using FNameMTime = std::pair; + std::vector files; + files.reserve(numFiles); + constexpr auto md5_size = 32; + // get filenames and timestamps try { + const auto dir = Gio::File::create_for_path(Glib::build_filename(baseDir, "data")); + const auto enumerator = dir->enumerate_children("standard::name,time::modified"); - const auto dirName = Glib::build_filename (baseDir, "data"); - const auto dir = Gio::File::create_for_path (dirName); - - auto enumerator = dir->enumerate_children ("standard::name,time::modified"); - - while (auto file = enumerator->next_file ()) { - files.emplace_back (file->get_name (), file->modification_time ()); + while (const auto file = enumerator->next_file()) { + const auto name = file->get_name(); + if (name.size() >= md5_size + 5) { + files.emplace_back(name, file->modification_time()); + } } } catch (Glib::Exception&) {} - if (files.size () <= options.maxCacheEntries) { + if (files.size() <= options.maxCacheEntries) { + // limit not reached return; } - std::sort (files.begin (), files.end (), [] (const FNameMTime& lhs, const FNameMTime& rhs) + constexpr auto reserve = 0.05f; // reserve 5% free cache space + const size_t toDelete = files.size() - options.maxCacheEntries + options.maxCacheEntries * reserve; + + std::nth_element(files.begin(), files.begin() + toDelete, files.end(), [] (const FNameMTime& lhs, const FNameMTime& rhs) { return lhs.second < rhs.second; }); - auto cacheEntries = files.size (); - - for (auto entry = files.begin (); cacheEntries-- > options.maxCacheEntries; ++entry) { - + for (auto entry = files.begin(); entry < files.begin() + toDelete; ++entry) { const auto& name = entry->first; + const auto name_size = name.size() - md5_size; + const auto fname = name.substr(0, name_size - 5); + const auto md5 = name.substr(name_size - 4, md5_size); - constexpr auto md5_size = 32; - const auto name_size = name.size(); - - if (name_size < md5_size + 5) { - continue; - } - - const auto fname = name.substr (0, name_size - md5_size - 5); - const auto md5 = name.substr (name_size - md5_size - 4, md5_size); - - deleteFiles (fname, md5, true, false); + deleteFiles(fname, md5, true, false); } }